OSDN Git Service

btrfs: hold a ref on the root in btrfs_recover_relocation
authorJosef Bacik <josef@toxicpanda.com>
Fri, 24 Jan 2020 14:32:44 +0000 (09:32 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 23 Mar 2020 16:01:30 +0000 (17:01 +0100)
We look up the fs root in various places in here when recovering from a
crashed relcoation.  Make sure we hold a ref on the root whenever we
look them up.

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/relocation.c

index a257147..f0d8177 100644 (file)
@@ -4647,6 +4647,12 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                                        err = ret;
                                        goto out;
                                }
+                       } else {
+                               if (!btrfs_grab_fs_root(fs_root)) {
+                                       err = -ENOENT;
+                                       goto out;
+                               }
+                               btrfs_put_fs_root(fs_root);
                        }
                }
 
@@ -4696,10 +4702,15 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                        list_add_tail(&reloc_root->root_list, &reloc_roots);
                        goto out_free;
                }
+               if (!btrfs_grab_fs_root(fs_root)) {
+                       err = -ENOENT;
+                       goto out_free;
+               }
 
                err = __add_reloc_root(reloc_root);
                BUG_ON(err < 0); /* -ENOMEM or logic error */
                fs_root->reloc_root = reloc_root;
+               btrfs_put_fs_root(fs_root);
        }
 
        err = btrfs_commit_transaction(trans);
@@ -4731,10 +4742,14 @@ 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))
+               if (IS_ERR(fs_root)) {
                        err = PTR_ERR(fs_root);
-               else
-                       err = btrfs_orphan_cleanup(fs_root);
+               } else {
+                       if (btrfs_grab_fs_root(fs_root)) {
+                               err = btrfs_orphan_cleanup(fs_root);
+                               btrfs_put_fs_root(fs_root);
+                       }
+               }
        }
        return err;
 }