diff options
| author | Qu Wenruo <wqu@suse.com> | 2025-06-12 15:14:35 +0930 |
|---|---|---|
| committer | David Sterba <dsterba@suse.com> | 2025-07-22 00:06:19 +0200 |
| commit | 35ea448b75f3bdb825e6a19fd8db2a147bee0ab7 (patch) | |
| tree | d8326fe5e74e2471dc8946c7eb7251dfe4993e67 | |
| parent | ae818824a203958b326fd0a29e57aaeb166f1fbe (diff) | |
| download | linux-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.c | 27 |
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); } |
