btrfs: hold a ref on fs roots while they're in the radix tree
authorJosef Bacik <josef@toxicpanda.com>
Fri, 24 Jan 2020 14:32:27 +0000 (09:32 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 23 Mar 2020 16:01:27 +0000 (17:01 +0100)
If the root is sitting in the radix tree, we should probably have a ref
for the radix tree.  Grab a ref on the root when we insert it, and drop
it when it gets deleted.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c

index 67e7b0ccdea0a32dccb527a6b074968eba41ce00..43af9f9b8583041b7e2762a96ed44fdb84bf00b2 100644 (file)
@@ -1513,8 +1513,10 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
        ret = radix_tree_insert(&fs_info->fs_roots_radix,
                                (unsigned long)root->root_key.objectid,
                                root);
-       if (ret == 0)
+       if (ret == 0) {
+               btrfs_grab_fs_root(root);
                set_bit(BTRFS_ROOT_IN_RADIX, &root->state);
+       }
        spin_unlock(&fs_info->fs_roots_radix_lock);
        radix_tree_preload_end();
 
@@ -3817,6 +3819,8 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
        spin_lock(&fs_info->fs_roots_radix_lock);
        radix_tree_delete(&fs_info->fs_roots_radix,
                          (unsigned long)root->root_key.objectid);
+       if (test_and_clear_bit(BTRFS_ROOT_IN_RADIX, &root->state))
+               btrfs_put_fs_root(root);
        spin_unlock(&fs_info->fs_roots_radix_lock);
 
        if (btrfs_root_refs(&root->root_item) == 0)