summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-11-04 03:19:03 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2019-01-30 17:44:23 -0500
commit9bc61ab18b1d41f26dc06b9e6d3c203e65f83fe6 (patch)
tree4aa7a18d6f2de4f147b5515d99e9fcae897c49a0 /fs/super.c
parent74e831221cfd79460ec11c1b641093863f0ef3ce (diff)
vfs: Introduce fs_context, switch vfs_kern_mount() to it.
Introduce a filesystem context concept to be used during superblock creation for mount and superblock reconfiguration for remount. This is allocated at the beginning of the mount procedure and into it is placed: (1) Filesystem type. (2) Namespaces. (3) Source/Device names (there may be multiple). (4) Superblock flags (SB_*). (5) Security details. (6) Filesystem-specific data, as set by the mount options. Accessor functions are then provided to set up a context, parameterise it from monolithic mount data (the data page passed to mount(2)) and tear it down again. A legacy wrapper is provided that implements what will be the basic operations, wrapping access to filesystems that aren't yet aware of the fs_context. Finally, vfs_kern_mount() is changed to make use of the fs_context and mount_fs() is replaced by vfs_get_tree(), called from vfs_kern_mount(). [AV -- add missing kstrdup()] [AV -- put_cred() can be unconditional - fc->cred can't be NULL] [AV -- take legacy_validate() contents into legacy_parse_monolithic()] [AV -- merge KERNEL_MOUNT and USER_MOUNT] [AV -- don't unlock superblock on success return from vfs_get_tree()] [AV -- kill 'reference' argument of init_fs_context()] Signed-off-by: David Howells <dhowells@redhat.com> Co-developed-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c50
1 files changed, 23 insertions, 27 deletions
diff --git a/fs/super.c b/fs/super.c
index 48e25eba8465..fc3887277ad1 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -35,6 +35,7 @@
35#include <linux/fsnotify.h> 35#include <linux/fsnotify.h>
36#include <linux/lockdep.h> 36#include <linux/lockdep.h>
37#include <linux/user_namespace.h> 37#include <linux/user_namespace.h>
38#include <linux/fs_context.h>
38#include <uapi/linux/mount.h> 39#include <uapi/linux/mount.h>
39#include "internal.h" 40#include "internal.h"
40 41
@@ -1241,27 +1242,24 @@ struct dentry *mount_single(struct file_system_type *fs_type,
1241} 1242}
1242EXPORT_SYMBOL(mount_single); 1243EXPORT_SYMBOL(mount_single);
1243 1244
1244struct dentry * 1245/**
1245mount_fs(struct file_system_type *type, int flags, const char *name, void *data) 1246 * vfs_get_tree - Get the mountable root
1247 * @fc: The superblock configuration context.
1248 *
1249 * The filesystem is invoked to get or create a superblock which can then later
1250 * be used for mounting. The filesystem places a pointer to the root to be
1251 * used for mounting in @fc->root.
1252 */
1253int vfs_get_tree(struct fs_context *fc)
1246{ 1254{
1247 struct dentry *root;
1248 struct super_block *sb; 1255 struct super_block *sb;
1249 int error = -ENOMEM; 1256 int error;
1250 void *sec_opts = NULL;
1251 1257
1252 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 1258 error = legacy_get_tree(fc);
1253 error = security_sb_eat_lsm_opts(data, &sec_opts); 1259 if (error < 0)
1254 if (error) 1260 return error;
1255 return ERR_PTR(error);
1256 }
1257 1261
1258 root = type->mount(type, flags, name, data); 1262 sb = fc->root->d_sb;
1259 if (IS_ERR(root)) {
1260 error = PTR_ERR(root);
1261 goto out_free_secdata;
1262 }
1263 sb = root->d_sb;
1264 BUG_ON(!sb);
1265 WARN_ON(!sb->s_bdi); 1263 WARN_ON(!sb->s_bdi);
1266 1264
1267 /* 1265 /*
@@ -1273,11 +1271,11 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
1273 smp_wmb(); 1271 smp_wmb();
1274 sb->s_flags |= SB_BORN; 1272 sb->s_flags |= SB_BORN;
1275 1273
1276 error = security_sb_set_mnt_opts(sb, sec_opts, 0, NULL); 1274 error = security_sb_set_mnt_opts(sb, fc->security, 0, NULL);
1277 if (error) 1275 if (error)
1278 goto out_sb; 1276 goto out_sb;
1279 1277
1280 if (!(flags & (MS_KERNMOUNT|MS_SUBMOUNT))) { 1278 if (!(fc->sb_flags & (MS_KERNMOUNT|MS_SUBMOUNT))) {
1281 error = security_sb_kern_mount(sb); 1279 error = security_sb_kern_mount(sb);
1282 if (error) 1280 if (error)
1283 goto out_sb; 1281 goto out_sb;
@@ -1290,18 +1288,16 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
1290 * violate this rule. 1288 * violate this rule.
1291 */ 1289 */
1292 WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " 1290 WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
1293 "negative value (%lld)\n", type->name, sb->s_maxbytes); 1291 "negative value (%lld)\n", fc->fs_type->name, sb->s_maxbytes);
1294 1292
1295 up_write(&sb->s_umount); 1293 return 0;
1296 security_free_mnt_opts(&sec_opts);
1297 return root;
1298out_sb: 1294out_sb:
1299 dput(root); 1295 dput(fc->root);
1296 fc->root = NULL;
1300 deactivate_locked_super(sb); 1297 deactivate_locked_super(sb);
1301out_free_secdata: 1298 return error;
1302 security_free_mnt_opts(&sec_opts);
1303 return ERR_PTR(error);
1304} 1299}
1300EXPORT_SYMBOL(vfs_get_tree);
1305 1301
1306/* 1302/*
1307 * Setup private BDI for given superblock. It gets automatically cleaned up 1303 * Setup private BDI for given superblock. It gets automatically cleaned up