diff mbox series

[v2] btrfs: hold a ref on the root in get_subvol_name_from_objectid

Message ID 20200206152426.6312-1-josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series [v2] btrfs: hold a ref on the root in get_subvol_name_from_objectid | expand

Commit Message

Josef Bacik Feb. 6, 2020, 3:24 p.m. UTC
We lookup the name of a subvol which means we'll cross into different
roots.  Hold a ref while we're doing the look ups in the fs_root we're
searching.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
v1->v2:
- Moved the btrfs_put_fs_root() to err, but this requires making sure that
  fs_root == NULL in all the cases we won't have a valid fs_root to drop a ref
  on.

 fs/btrfs/super.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index fa74caf39165..96bc10da5ff2 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1028,7 +1028,7 @@  static char *get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
 					   u64 subvol_objectid)
 {
 	struct btrfs_root *root = fs_info->tree_root;
-	struct btrfs_root *fs_root;
+	struct btrfs_root *fs_root = NULL;
 	struct btrfs_root_ref *root_ref;
 	struct btrfs_inode_ref *inode_ref;
 	struct btrfs_key key;
@@ -1099,6 +1099,12 @@  static char *get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
 		fs_root = btrfs_get_fs_root(fs_info, &key, true);
 		if (IS_ERR(fs_root)) {
 			ret = PTR_ERR(fs_root);
+			fs_root = NULL;
+			goto err;
+		}
+		if (!btrfs_grab_fs_root(fs_root)) {
+			ret = -ENOENT;
+			fs_root = NULL;
 			goto err;
 		}
 
@@ -1143,6 +1149,8 @@  static char *get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
 			ptr[0] = '/';
 			btrfs_release_path(path);
 		}
+		btrfs_put_fs_root(fs_root);
+		fs_root = NULL;
 	}
 
 	btrfs_free_path(path);
@@ -1155,6 +1163,7 @@  static char *get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
 	return name;
 
 err:
+	btrfs_put_fs_root(fs_root);
 	btrfs_free_path(path);
 	kfree(name);
 	return ERR_PTR(ret);