]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/reada.c
Merge tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel...
[karo-tx-linux.git] / fs / btrfs / reada.c
index e88bca87f5d275c7c25b2ee6279fe4cdc1482413..a17e775a4a89fca1e48214c5abb02756dd1c69d6 100644 (file)
@@ -209,9 +209,9 @@ cleanup:
        return;
 }
 
-int btree_readahead_hook(struct btrfs_fs_info *fs_info,
-                        struct extent_buffer *eb, int err)
+int btree_readahead_hook(struct extent_buffer *eb, int err)
 {
+       struct btrfs_fs_info *fs_info = eb->fs_info;
        int ret = 0;
        struct reada_extent *re;
 
@@ -235,10 +235,10 @@ start_machine:
        return ret;
 }
 
-static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
-                                         struct btrfs_device *dev, u64 logical,
+static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,
                                          struct btrfs_bio *bbio)
 {
+       struct btrfs_fs_info *fs_info = dev->fs_info;
        int ret;
        struct reada_zone *zone;
        struct btrfs_block_group_cache *cache = NULL;
@@ -270,6 +270,12 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
        if (!zone)
                return NULL;
 
+       ret = radix_tree_preload(GFP_KERNEL);
+       if (ret) {
+               kfree(zone);
+               return NULL;
+       }
+
        zone->start = start;
        zone->end = end;
        INIT_LIST_HEAD(&zone->list);
@@ -299,6 +305,7 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
                        zone = NULL;
        }
        spin_unlock(&fs_info->reada_lock);
+       radix_tree_preload_end();
 
        return zone;
 }
@@ -313,7 +320,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
        struct btrfs_bio *bbio = NULL;
        struct btrfs_device *dev;
        struct btrfs_device *prev_dev;
-       u32 blocksize;
        u64 length;
        int real_stripes;
        int nzones = 0;
@@ -334,7 +340,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
        if (!re)
                return NULL;
 
-       blocksize = fs_info->nodesize;
        re->logical = logical;
        re->top = *top;
        INIT_LIST_HEAD(&re->extctl);
@@ -344,10 +349,10 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
        /*
         * map block
         */
-       length = blocksize;
+       length = fs_info->nodesize;
        ret = btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
                        &length, &bbio, 0);
-       if (ret || !bbio || length < blocksize)
+       if (ret || !bbio || length < fs_info->nodesize)
                goto error;
 
        if (bbio->num_stripes > BTRFS_MAX_MIRRORS) {
@@ -367,7 +372,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                 if (!dev->bdev)
                        continue;
 
-               zone = reada_find_zone(fs_info, dev, logical, bbio);
+               zone = reada_find_zone(dev, logical, bbio);
                if (!zone)
                        continue;
 
@@ -386,6 +391,10 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                goto error;
        }
 
+       ret = radix_tree_preload(GFP_KERNEL);
+       if (ret)
+               goto error;
+
        /* insert extent in reada_tree + all per-device trees, all or nothing */
        btrfs_dev_replace_lock(&fs_info->dev_replace, 0);
        spin_lock(&fs_info->reada_lock);
@@ -395,13 +404,16 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                re_exist->refcnt++;
                spin_unlock(&fs_info->reada_lock);
                btrfs_dev_replace_unlock(&fs_info->dev_replace, 0);
+               radix_tree_preload_end();
                goto error;
        }
        if (ret) {
                spin_unlock(&fs_info->reada_lock);
                btrfs_dev_replace_unlock(&fs_info->dev_replace, 0);
+               radix_tree_preload_end();
                goto error;
        }
+       radix_tree_preload_end();
        prev_dev = NULL;
        dev_replace_is_ongoing = btrfs_dev_replace_is_ongoing(
                        &fs_info->dev_replace);
@@ -639,9 +651,9 @@ static int reada_pick_zone(struct btrfs_device *dev)
        return 1;
 }
 
-static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
-                                  struct btrfs_device *dev)
+static int reada_start_machine_dev(struct btrfs_device *dev)
 {
+       struct btrfs_fs_info *fs_info = dev->fs_info;
        struct reada_extent *re = NULL;
        int mirror_num = 0;
        struct extent_buffer *eb = NULL;
@@ -754,8 +766,7 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info)
                list_for_each_entry(device, &fs_devices->devices, dev_list) {
                        if (atomic_read(&device->reada_in_flight) <
                            MAX_IN_FLIGHT)
-                               enqueued += reada_start_machine_dev(fs_info,
-                                                                   device);
+                               enqueued += reada_start_machine_dev(device);
                }
                mutex_unlock(&fs_devices->device_list_mutex);
                total += enqueued;