summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2025-06-12 15:14:35 +0930
committerDavid Sterba <dsterba@suse.com>2025-07-22 00:06:19 +0200
commit35ea448b75f3bdb825e6a19fd8db2a147bee0ab7 (patch)
treed8326fe5e74e2471dc8946c7eb7251dfe4993e67
parentae818824a203958b326fd0a29e57aaeb166f1fbe (diff)
downloadlinux-stable-35ea448b75f3bdb825e6a19fd8db2a147bee0ab7.tar.gz
linux-stable-35ea448b75f3bdb825e6a19fd8db2a147bee0ab7.zip
btrfs: get rid of re-entering of btrfs_get_tree()
[EXISTING PROBLEM] Currently btrfs mount is split into two parts: - btrfs_get_tree_subvol() Which sets up the very basic fs_info, and eventually calls mount_subvol() to mount the target subvolume. - btrfs_get_tree_super() This is the part doing super block allocation and if there is no existing super block, do the real open_ctree() to open the fs. However currently we're doing this in a complex re-entering way: vfs_get_tree() |- btrfs_get_tree() |- btrfs_get_tree_subvol() |- vfs_get_tree() | |- btrfs_get_tree() | |- btrfs_get_tree_super() |- mount_subvol() This is definitely not that easy to grasp. [ENHANCEMENT] The function vfs_get_tree() is only doing the following work: - Call get_tree() call back - Call super_wake() - Call security_sb_set_mnt_opts() In our case, super_wake() can be skipped, as after btrfs_get_tree_subvol() finishes, vfs_get_tree() will call super_wake() on the super block we got anyway. The same applies to security_sb_set_mnt_opts(), as long as we do not free the security from our original fc in btrfs_get_tree_subvol(), the first vfs_get_tree() call will handle the security correctly. So here we only need to: - Replace vfs_get_tree() call with btrfs_get_tree_super() - Keep the existing fc->security for vfs_get_tree() to handle the security This will remove the re-entering behavior and make thing much easier to follow. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/super.c27
1 files changed, 3 insertions, 24 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index b9e08a59da4e..d977d2da985e 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2046,15 +2046,7 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
*/
dup_fc->s_fs_info = fs_info;
- /*
- * We'll do the security settings in our btrfs_get_tree_super() mount
- * loop, they were duplicated into dup_fc, we can drop the originals
- * here.
- */
- security_free_mnt_opts(&fc->security);
- fc->security = NULL;
-
- ret = vfs_get_tree(dup_fc);
+ ret = btrfs_get_tree_super(dup_fc);
if (ret)
goto error;
@@ -2086,21 +2078,8 @@ error:
static int btrfs_get_tree(struct fs_context *fc)
{
- /*
- * Since we use mount_subtree to mount the default/specified subvol, we
- * have to do mounts in two steps.
- *
- * First pass through we call btrfs_get_tree_subvol(), this is just a
- * wrapper around fc_mount() to call back into here again, and this time
- * we'll call btrfs_get_tree_super(). This will do the open_ctree() and
- * everything to open the devices and file system. Then we return back
- * with a fully constructed vfsmount in btrfs_get_tree_subvol(), and
- * from there we can do our mount_subvol() call, which will lookup
- * whichever subvol we're mounting and setup this fc with the
- * appropriate dentry for the subvol.
- */
- if (fc->s_fs_info)
- return btrfs_get_tree_super(fc);
+ ASSERT(fc->s_fs_info == NULL);
+
return btrfs_get_tree_subvol(fc);
}