btrfs: preallocate radix tree node for global readahead tree
authorDavid Sterba <dsterba@suse.com>
Thu, 2 Mar 2017 17:54:52 +0000 (18:54 +0100)
committerDavid Sterba <dsterba@suse.com>
Tue, 18 Apr 2017 12:07:25 +0000 (14:07 +0200)
We can preallocate the node so insertion does not have to do that under
the lock. The GFP flags for the global radix tree are initialized to
 GFP_NOFS & ~__GFP_DIRECT_RECLAIM
but we can use GFP_KERNEL, because readahead is optional and not on any
critical writeout path.

Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/reada.c

index bd415e1..12eba54 100644 (file)
@@ -2693,7 +2693,7 @@ int open_ctree(struct super_block *sb,
        fs_info->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
        fs_info->avg_delayed_ref_runtime = NSEC_PER_SEC >> 6; /* div by 64 */
        /* readahead state */
-       INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+       INIT_RADIX_TREE(&fs_info->reada_tree, GFP_KERNEL);
        spin_lock_init(&fs_info->reada_lock);
 
        fs_info->thread_pool_size = min_t(unsigned long,
index fdae8ca..a7fa4a5 100644 (file)
@@ -393,6 +393,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);
@@ -402,13 +406,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);