btrfs: don't set SHAREABLE flag for data reloc tree
authorQu Wenruo <wqu@suse.com>
Fri, 15 May 2020 06:01:42 +0000 (14:01 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 May 2020 09:25:35 +0000 (11:25 +0200)
SHAREABLE flag is set for subvolumes because users can create snapshot
for subvolumes, thus sharing tree blocks of them.

But data reloc tree is not exposed to user space, as it's only an
internal tree for data relocation, thus it doesn't need the full path
replacement handling at all.

This patch will make data reloc tree a non-shareable tree, and add
btrfs_fs_info::data_reloc_root for data reloc tree, so relocation code
can grab it from fs_info directly.

This would slightly improve tree relocation, as now data reloc tree
can go through regular COW routine to get relocated, without bothering
the complex tree reloc tree routine.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/relocation.c

index bf46093be76e4673556e1846d690078e3fe44582..616fdbc5369562936c3c03ca3597651117b59155 100644 (file)
@@ -582,6 +582,7 @@ struct btrfs_fs_info {
        struct btrfs_root *quota_root;
        struct btrfs_root *uuid_root;
        struct btrfs_root *free_space_root;
+       struct btrfs_root *data_reloc_root;
 
        /* the log root tree is a directory of all the other log roots */
        struct btrfs_root *log_root_tree;
index 248086cca1240e8b327afb4111be3a7f3cc35ec4..f1143741f6ba057685de32ca6e94e80ba15c0a94 100644 (file)
@@ -1417,7 +1417,8 @@ static int btrfs_init_fs_root(struct btrfs_root *root)
        if (ret)
                goto fail;
 
-       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
+       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
+           root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
                set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
                btrfs_check_and_init_root_item(&root->root_item);
        }
@@ -1523,6 +1524,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
        btrfs_put_root(fs_info->uuid_root);
        btrfs_put_root(fs_info->free_space_root);
        btrfs_put_root(fs_info->fs_root);
+       btrfs_put_root(fs_info->data_reloc_root);
        btrfs_check_leaked_roots(fs_info);
        btrfs_extent_buffer_leak_debug_check(fs_info);
        kfree(fs_info->super_copy);
@@ -1979,6 +1981,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
        free_root_extent_buffers(info->quota_root);
        free_root_extent_buffers(info->uuid_root);
        free_root_extent_buffers(info->fs_root);
+       free_root_extent_buffers(info->data_reloc_root);
        if (free_chunk_root)
                free_root_extent_buffers(info->chunk_root);
        free_root_extent_buffers(info->free_space_root);
@@ -2285,6 +2288,19 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
        set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
        fs_info->csum_root = root;
 
+       /*
+        * This tree can share blocks with some other fs tree during relocation
+        * and we need a proper setup by btrfs_get_fs_root
+        */
+       location.objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
+       root = btrfs_get_fs_root(tree_root->fs_info, &location, true);
+       if (IS_ERR(root)) {
+               ret = PTR_ERR(root);
+               goto out;
+       }
+       set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+       fs_info->data_reloc_root = root;
+
        location.objectid = BTRFS_QUOTA_TREE_OBJECTID;
        root = btrfs_read_tree_root(tree_root, &location);
        if (!IS_ERR(root)) {
index 1dd7b5310ffdfe9fd3648a1f54cf45ee8c896f77..58f56e01de0d80285a6e11b1d91263a19cf5b736 100644 (file)
@@ -3476,10 +3476,7 @@ struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info,
        u64 objectid;
        int err = 0;
 
-       root = read_fs_root(fs_info, BTRFS_DATA_RELOC_TREE_OBJECTID);
-       if (IS_ERR(root))
-               return ERR_CAST(root);
-
+       root = btrfs_grab_root(fs_info->data_reloc_root);
        trans = btrfs_start_transaction(root, 6);
        if (IS_ERR(trans)) {
                btrfs_put_root(root);
@@ -3871,13 +3868,10 @@ out:
 
        if (err == 0) {
                /* cleanup orphan inode in data relocation tree */
-               fs_root = read_fs_root(fs_info, BTRFS_DATA_RELOC_TREE_OBJECTID);
-               if (IS_ERR(fs_root)) {
-                       err = PTR_ERR(fs_root);
-               } else {
-                       err = btrfs_orphan_cleanup(fs_root);
-                       btrfs_put_root(fs_root);
-               }
+               fs_root = btrfs_grab_root(fs_info->data_reloc_root);
+               ASSERT(fs_root);
+               err = btrfs_orphan_cleanup(fs_root);
+               btrfs_put_root(fs_root);
        }
        return err;
 }