Commit 35ea448b authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

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: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ae818824
Loading
Loading
Loading
Loading
+3 −24
Original line number Diff line number Diff line
@@ -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 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)

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);
}