Add an additional keying mode to vfs_get_super() to indicate that only a single superblock should exist in the system, and that, if it does, further mounts should invoke reconfiguration upon it. This allows mount_single() to be replaced. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- fs/super.c | 24 +++++++++++++++++------- include/linux/fs_context.h | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/fs/super.c b/fs/super.c index 6cb57ad31e6f..60c9caeae3c7 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1175,9 +1175,11 @@ int vfs_get_super(struct fs_context *fc, { int (*test)(struct super_block *, struct fs_context *); struct super_block *sb; + int err; switch (keying) { case vfs_get_single_super: + case vfs_get_single_reconf_super: test = test_single_super; break; case vfs_get_keyed_super: @@ -1195,18 +1197,26 @@ int vfs_get_super(struct fs_context *fc, return PTR_ERR(sb); if (!sb->s_root) { - int err = fill_super(sb, fc); - if (err) { - deactivate_locked_super(sb); - return err; - } + err = fill_super(sb, fc); + if (err) + goto error; sb->s_flags |= SB_ACTIVE; + fc->root = dget(sb->s_root); + } else { + fc->root = dget(sb->s_root); + if (keying == vfs_get_single_reconf_super) { + err = reconfigure_super(fc); + if (err < 0) + goto error; + } } - BUG_ON(fc->root); - fc->root = dget(sb->s_root); return 0; + +error: + deactivate_locked_super(sb); + return err; } EXPORT_SYMBOL(vfs_get_super); diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h index 7c7eefb35cc3..3b1da9b2db91 100644 --- a/include/linux/fs_context.h +++ b/include/linux/fs_context.h @@ -138,6 +138,7 @@ extern int vfs_init_pseudo_fs_context(struct fs_context *fc, */ enum vfs_get_super_keying { vfs_get_single_super, /* Only one such superblock may exist */ + vfs_get_single_reconf_super, /* As above, but reconfigure if it exists */ vfs_get_keyed_super, /* Superblocks with different s_fs_info keys may exist */ vfs_get_independent_super, /* Multiple independent superblocks may exist */ };