forked from Minki/linux
vfs: Add a single-or-reconfig keying to vfs_get_super()
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. [Fix by Eric Biggers folded in] Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
0f07100410
commit
43ce4c1fea
35
fs/super.c
35
fs/super.c
@ -1160,9 +1160,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:
|
||||
@ -1180,18 +1182,29 @@ 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) {
|
||||
dput(fc->root);
|
||||
fc->root = NULL;
|
||||
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);
|
||||
|
||||
@ -1211,6 +1224,14 @@ int get_tree_single(struct fs_context *fc,
|
||||
}
|
||||
EXPORT_SYMBOL(get_tree_single);
|
||||
|
||||
int get_tree_single_reconf(struct fs_context *fc,
|
||||
int (*fill_super)(struct super_block *sb,
|
||||
struct fs_context *fc))
|
||||
{
|
||||
return vfs_get_super(fc, vfs_get_single_reconf_super, fill_super);
|
||||
}
|
||||
EXPORT_SYMBOL(get_tree_single_reconf);
|
||||
|
||||
int get_tree_keyed(struct fs_context *fc,
|
||||
int (*fill_super)(struct super_block *sb,
|
||||
struct fs_context *fc),
|
||||
|
@ -141,6 +141,7 @@ extern void put_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 */
|
||||
};
|
||||
@ -155,6 +156,9 @@ extern int get_tree_nodev(struct fs_context *fc,
|
||||
extern int get_tree_single(struct fs_context *fc,
|
||||
int (*fill_super)(struct super_block *sb,
|
||||
struct fs_context *fc));
|
||||
extern int get_tree_single_reconf(struct fs_context *fc,
|
||||
int (*fill_super)(struct super_block *sb,
|
||||
struct fs_context *fc));
|
||||
extern int get_tree_keyed(struct fs_context *fc,
|
||||
int (*fill_super)(struct super_block *sb,
|
||||
struct fs_context *fc),
|
||||
|
Loading…
Reference in New Issue
Block a user