mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
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:
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 *);
|
int (*test)(struct super_block *, struct fs_context *);
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
|
int err;
|
||||||
|
|
||||||
switch (keying) {
|
switch (keying) {
|
||||||
case vfs_get_single_super:
|
case vfs_get_single_super:
|
||||||
|
case vfs_get_single_reconf_super:
|
||||||
test = test_single_super;
|
test = test_single_super;
|
||||||
break;
|
break;
|
||||||
case vfs_get_keyed_super:
|
case vfs_get_keyed_super:
|
||||||
@@ -1180,18 +1182,29 @@ int vfs_get_super(struct fs_context *fc,
|
|||||||
return PTR_ERR(sb);
|
return PTR_ERR(sb);
|
||||||
|
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
int err = fill_super(sb, fc);
|
err = fill_super(sb, fc);
|
||||||
if (err) {
|
if (err)
|
||||||
deactivate_locked_super(sb);
|
goto error;
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb->s_flags |= SB_ACTIVE;
|
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;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
deactivate_locked_super(sb);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vfs_get_super);
|
EXPORT_SYMBOL(vfs_get_super);
|
||||||
|
|
||||||
@@ -1211,6 +1224,14 @@ int get_tree_single(struct fs_context *fc,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(get_tree_single);
|
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 get_tree_keyed(struct fs_context *fc,
|
||||||
int (*fill_super)(struct super_block *sb,
|
int (*fill_super)(struct super_block *sb,
|
||||||
struct fs_context *fc),
|
struct fs_context *fc),
|
||||||
|
@@ -141,6 +141,7 @@ extern void put_fs_context(struct fs_context *fc);
|
|||||||
*/
|
*/
|
||||||
enum vfs_get_super_keying {
|
enum vfs_get_super_keying {
|
||||||
vfs_get_single_super, /* Only one such superblock may exist */
|
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_keyed_super, /* Superblocks with different s_fs_info keys may exist */
|
||||||
vfs_get_independent_super, /* Multiple independent superblocks 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,
|
extern int get_tree_single(struct fs_context *fc,
|
||||||
int (*fill_super)(struct super_block *sb,
|
int (*fill_super)(struct super_block *sb,
|
||||||
struct fs_context *fc));
|
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,
|
extern int get_tree_keyed(struct fs_context *fc,
|
||||||
int (*fill_super)(struct super_block *sb,
|
int (*fill_super)(struct super_block *sb,
|
||||||
struct fs_context *fc),
|
struct fs_context *fc),
|
||||||
|
Reference in New Issue
Block a user