Message ID | 20200812163654.17080-7-marcos@mpdesouza.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: convert to fscontext | expand |
On Wed, Aug 12, 2020 at 01:36:52PM -0300, Marcos Paulo de Souza wrote: > From: Marcos Paulo de Souza <mpdesouza@suse.com> > > This function will be used by the following patches to mount the root fs > before mounting a subvolume. > > Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com> > --- > fs/btrfs/super.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > > diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c > index 6b70fb73a1ea..5bbf4b947125 100644 > --- a/fs/btrfs/super.c > +++ b/fs/btrfs/super.c > @@ -2419,6 +2419,47 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, > return ERR_PTR(error); > } > > +/* > + * Duplicate the current fc and prepare for mounting the root. > + * btrfs_get_tree will be called recursively, but then will check for the > + * ctx->root being set and call btrfs_root_get_tree. This sounds like the adding back recursive mount with -o subvol= that was removed. > + */ > +static int btrfs_mount_root_fc(struct fs_context *fc, unsigned int rdonly) > +{ > + struct btrfs_fs_context *ctx, *root_ctx; > + struct fs_context *root_fc; > + struct vfsmount *root_mnt; > + int ret; > + > + root_fc = vfs_dup_fs_context(fc); > + if (IS_ERR(root_fc)) > + return PTR_ERR(root_fc); > + > + root_fc->sb_flags &= ~SB_RDONLY; > + root_fc->sb_flags |= rdonly | SB_NOSEC; > + root_ctx = root_fc->fs_private; > + root_ctx->root_mnt = NULL; > + root_ctx->root = true; > + > + /* > + * fc_mount will call btrfs_get_tree again, and by checking ctx->root > + * being true it'll call btrfs_root_get_tree to avoid infinite recursion. > + */ Can this race somehow? If there are several parallel mounts called eg. for a set of system subvolumes. > + root_mnt = fc_mount(root_fc); > + if (IS_ERR(root_mnt)) { > + ret = PTR_ERR(root_mnt); > + goto error_fc; > + } > + > + ctx = fc->fs_private; > + ctx->root_mnt = root_mnt; > + ret = 0; > + > +error_fc: > + put_fs_context(root_fc); > + return ret; > +} > + > /* > * Mount function which is called by VFS layer. > * > -- > 2.28.0
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 6b70fb73a1ea..5bbf4b947125 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2419,6 +2419,47 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, return ERR_PTR(error); } +/* + * Duplicate the current fc and prepare for mounting the root. + * btrfs_get_tree will be called recursively, but then will check for the + * ctx->root being set and call btrfs_root_get_tree. + */ +static int btrfs_mount_root_fc(struct fs_context *fc, unsigned int rdonly) +{ + struct btrfs_fs_context *ctx, *root_ctx; + struct fs_context *root_fc; + struct vfsmount *root_mnt; + int ret; + + root_fc = vfs_dup_fs_context(fc); + if (IS_ERR(root_fc)) + return PTR_ERR(root_fc); + + root_fc->sb_flags &= ~SB_RDONLY; + root_fc->sb_flags |= rdonly | SB_NOSEC; + root_ctx = root_fc->fs_private; + root_ctx->root_mnt = NULL; + root_ctx->root = true; + + /* + * fc_mount will call btrfs_get_tree again, and by checking ctx->root + * being true it'll call btrfs_root_get_tree to avoid infinite recursion. + */ + root_mnt = fc_mount(root_fc); + if (IS_ERR(root_mnt)) { + ret = PTR_ERR(root_mnt); + goto error_fc; + } + + ctx = fc->fs_private; + ctx->root_mnt = root_mnt; + ret = 0; + +error_fc: + put_fs_context(root_fc); + return ret; +} + /* * Mount function which is called by VFS layer. *