summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-03-21 05:22:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2019-09-05 14:34:23 -0400
commit43ce4c1feadbc84c772518a2d1974f6ba1b15089 (patch)
treee3bc42b51b6c0ca84b4a7c99f676999ed0bf892f /fs/super.c
parent0f071004109d9c8de7023b9a64fa2ba3fa87cbed (diff)
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>
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/fs/super.c b/fs/super.c
index da223b4cfbca..beaf076d9733 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1160,9 +1160,11 @@ int vfs_get_super(struct fs_context *fc,
1160{ 1160{
1161 int (*test)(struct super_block *, struct fs_context *); 1161 int (*test)(struct super_block *, struct fs_context *);
1162 struct super_block *sb; 1162 struct super_block *sb;
1163 int err;
1163 1164
1164 switch (keying) { 1165 switch (keying) {
1165 case vfs_get_single_super: 1166 case vfs_get_single_super:
1167 case vfs_get_single_reconf_super:
1166 test = test_single_super; 1168 test = test_single_super;
1167 break; 1169 break;
1168 case vfs_get_keyed_super: 1170 case vfs_get_keyed_super:
@@ -1180,18 +1182,29 @@ int vfs_get_super(struct fs_context *fc,
1180 return PTR_ERR(sb); 1182 return PTR_ERR(sb);
1181 1183
1182 if (!sb->s_root) { 1184 if (!sb->s_root) {
1183 int err = fill_super(sb, fc); 1185 err = fill_super(sb, fc);
1184 if (err) { 1186 if (err)
1185 deactivate_locked_super(sb); 1187 goto error;
1186 return err;
1187 }
1188 1188
1189 sb->s_flags |= SB_ACTIVE; 1189 sb->s_flags |= SB_ACTIVE;
1190 fc->root = dget(sb->s_root);
1191 } else {
1192 fc->root = dget(sb->s_root);
1193 if (keying == vfs_get_single_reconf_super) {
1194 err = reconfigure_super(fc);
1195 if (err < 0) {
1196 dput(fc->root);
1197 fc->root = NULL;
1198 goto error;
1199 }
1200 }
1190 } 1201 }
1191 1202
1192 BUG_ON(fc->root);
1193 fc->root = dget(sb->s_root);
1194 return 0; 1203 return 0;
1204
1205error:
1206 deactivate_locked_super(sb);
1207 return err;
1195} 1208}
1196EXPORT_SYMBOL(vfs_get_super); 1209EXPORT_SYMBOL(vfs_get_super);
1197 1210
@@ -1211,6 +1224,14 @@ int get_tree_single(struct fs_context *fc,
1211} 1224}
1212EXPORT_SYMBOL(get_tree_single); 1225EXPORT_SYMBOL(get_tree_single);
1213 1226
1227int get_tree_single_reconf(struct fs_context *fc,
1228 int (*fill_super)(struct super_block *sb,
1229 struct fs_context *fc))
1230{
1231 return vfs_get_super(fc, vfs_get_single_reconf_super, fill_super);
1232}
1233EXPORT_SYMBOL(get_tree_single_reconf);
1234
1214int get_tree_keyed(struct fs_context *fc, 1235int get_tree_keyed(struct fs_context *fc,
1215 int (*fill_super)(struct super_block *sb, 1236 int (*fill_super)(struct super_block *sb,
1216 struct fs_context *fc), 1237 struct fs_context *fc),