diff --git a/fs/fsopen.c b/fs/fsopen.c
index a4e9d5a7ce2b..76656d0f4da3 100644
--- a/fs/fsopen.c
+++ b/fs/fsopen.c
@@ -52,22 +52,25 @@ static ssize_t fs_fs_read(struct file *file, char __user *_buf, size_t len, loff
 }
 
 /*
- * Userspace writes configuration data to the fd and we parse it here.  For the
- * moment, we assume a single option per write.  Each line written is of the form
+ * Userspace writes configuration data and commands to the fd and we parse it
+ * here.  For the moment, we assume a single option or command per write.  Each
+ * line written is of the form
  *
  *	<option_type><space><stuff...>
+ *	<command>
  *
  *	d /dev/sda1				-- Device name
  *	o noatime				-- Option without value
  *	o cell=grand.central.org		-- Option with value
- *	r /					-- Dir within device to mount
+ *	create					-- Create a superblock
+ *	update					-- Reconfigure a superblock
  */
 static ssize_t fs_fs_write(struct file *file,
 			   const char __user *_buf, size_t len, loff_t *pos)
 {
 	struct sb_config *sc = file->private_data;
 	struct inode *inode = file_inode(file);
-	char opt[2], *data;
+	char opt[8], *data;
 	ssize_t ret;
 
 	if (len < 3 || len > 4095)
@@ -79,11 +82,21 @@ static ssize_t fs_fs_write(struct file *file,
 	case 's':
 	case 'o':
 		break;
+	case 'c':
+	case 'u':
+		if (len != 6)
+			goto err_bad_cmd;
+		if (copy_from_user(opt, _buf, 6) != 0)
+			return -EFAULT;
+		if (memcmp(opt, "create", 6) == 0 ||
+		    memcmp(opt, "update", 6) == 0)
+			break;
+		goto err_bad_cmd;
 	default:
-		return sb_cfg_inval(sc, "VFS: Unsupported write spec");
+		goto err_bad_cmd;
 	}
 	if (opt[1] != ' ')
-		return sb_cfg_inval(sc, "VFS: Unsupported write spec");
+		goto err_bad_cmd;
 
 	data = memdup_user_nul(_buf + 2, len - 2);
 	if (IS_ERR(data))
@@ -96,10 +109,6 @@ static ssize_t fs_fs_write(struct file *file,
 	if (ret < 0)
 		goto err_free;
 
-	ret = -EBUSY;
-	if (sc->mounted)
-		goto err_unlock;
-
 	ret = -EINVAL;
 	switch (opt[0]) {
 	case 's':
@@ -115,6 +124,18 @@ static ssize_t fs_fs_write(struct file *file,
 			goto err_unlock;
 		break;
 
+	case 'c':
+		ret = vfs_create_super(sc);
+		if (ret < 0)
+			goto err_unlock;
+		break;
+
+	case 'u':
+		ret = vfs_reconfigure_super(sc);
+		if (ret < 0)
+			goto err_unlock;
+		break;
+
 	default:
 		goto err_unlock;
 	}
@@ -125,6 +146,8 @@ static ssize_t fs_fs_write(struct file *file,
 err_free:
 	kfree(data);
 	return ret;
+err_bad_cmd:
+	return sb_cfg_inval(sc, "VFS: Unsupported write spec");
 }
 
 const struct file_operations fs_fs_fops = {
diff --git a/fs/internal.h b/fs/internal.h
index 6ac2191cb59a..183f248fb819 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -89,8 +89,6 @@ extern struct file *get_empty_filp(void);
  */
 extern int do_remount_sb(struct super_block *, int, void *, int, struct sb_config *);
 extern bool trylock_super(struct super_block *sb);
-extern struct dentry *mount_fs(struct file_system_type *,
-			       int, const char *, void *);
 extern struct super_block *user_get_super(dev_t);
 
 /*
diff --git a/fs/libfs.c b/fs/libfs.c
index 2733d070b1ef..18f487c1247b 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -575,13 +575,27 @@ static DEFINE_SPINLOCK(pin_fs_lock);
 
 int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
 {
+	struct sb_config *sc;
 	struct vfsmount *mnt = NULL;
+	int ret;
+
 	spin_lock(&pin_fs_lock);
 	if (unlikely(!*mount)) {
 		spin_unlock(&pin_fs_lock);
-		mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, NULL);
+
+		sc = __vfs_new_sb_config(type, NULL, MS_KERNMOUNT, SB_CONFIG_FOR_NEW);
+		if (IS_ERR(sc))
+			return PTR_ERR(sc);
+
+		ret = vfs_create_super(sc);
+		if (ret < 0)
+			return ret;
+
+		mnt = vfs_kern_mount_sc(sc);
+		put_sb_config(sc);
 		if (IS_ERR(mnt))
 			return PTR_ERR(mnt);
+
 		spin_lock(&pin_fs_lock);
 		if (!*mount)
 			*mount = mnt;
diff --git a/fs/namespace.c b/fs/namespace.c
index 6d809f5705cd..d112142e9b05 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -967,55 +967,6 @@ static struct mount *skip_mnt_tree(struct mount *p)
 	return p;
 }
 
-struct vfsmount *
-vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
-{
-	struct mount *mnt;
-	struct dentry *root;
-
-	if (!type)
-		return ERR_PTR(-ENODEV);
-
-	mnt = alloc_vfsmnt(name);
-	if (!mnt)
-		return ERR_PTR(-ENOMEM);
-
-	if (flags & MS_KERNMOUNT)
-		mnt->mnt.mnt_flags = MNT_INTERNAL;
-
-	root = mount_fs(type, flags, name, data);
-	if (IS_ERR(root)) {
-		mnt_free_id(mnt);
-		free_vfsmnt(mnt);
-		return ERR_CAST(root);
-	}
-
-	mnt->mnt.mnt_root = root;
-	mnt->mnt.mnt_sb = root->d_sb;
-	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
-	mnt->mnt_parent = mnt;
-	lock_mount_hash();
-	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
-	unlock_mount_hash();
-	return &mnt->mnt;
-}
-EXPORT_SYMBOL_GPL(vfs_kern_mount);
-
-struct vfsmount *
-vfs_submount(const struct dentry *mountpoint, struct file_system_type *type,
-	     const char *name, void *data)
-{
-	/* Until it is worked out how to pass the user namespace
-	 * through from the parent mount to the submount don't support
-	 * unprivileged mounts with submounts.
-	 */
-	if (mountpoint->d_sb->s_user_ns != &init_user_ns)
-		return ERR_PTR(-EPERM);
-
-	return vfs_kern_mount(type, MS_SUBMOUNT, name, data);
-}
-EXPORT_SYMBOL_GPL(vfs_submount);
-
 static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 					int flag)
 {
@@ -2291,18 +2242,12 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
 static int parse_monolithic_mount_data(struct sb_config *sc, void *data)
 {
 	int (*monolithic_mount_data)(struct sb_config *, void *);
-	int ret;
 
 	monolithic_mount_data = sc->ops->monolithic_mount_data;
 	if (!monolithic_mount_data)
 		monolithic_mount_data = generic_monolithic_mount_data;
 
-	ret = monolithic_mount_data(sc, data);
-	if (ret < 0)
-		return ret;
-	if (sc->ops->validate)
-		return sc->ops->validate(sc);
-	return 0;
+	return monolithic_mount_data(sc, data);
 }
 
 /*
@@ -2466,29 +2411,6 @@ static int do_move_mount(struct path *path, const char *old_name)
 	return err;
 }
 
-static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
-{
-	int err;
-	const char *subtype = strchr(fstype, '.');
-	if (subtype) {
-		subtype++;
-		err = -EINVAL;
-		if (!subtype[0])
-			goto err;
-	} else
-		subtype = "";
-
-	mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
-	err = -ENOMEM;
-	if (!mnt->mnt_sb->s_subtype)
-		goto err;
-	return mnt;
-
- err:
-	mntput(mnt);
-	return ERR_PTR(err);
-}
-
 /*
  * add a mount into a namespace's mount tree
  */
@@ -2550,11 +2472,10 @@ static int do_new_mount_sc(struct sb_config *sc, struct path *mountpoint,
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
-	if ((sc->fs_type->fs_flags & FS_HAS_SUBTYPE) &&
-	    !mnt->mnt_sb->s_subtype) {
-		mnt = fs_set_subtype(mnt, sc->fs_type->name);
-		if (IS_ERR(mnt))
-			return PTR_ERR(mnt);
+	if (sc->subtype && !mnt->mnt_sb->s_subtype) {
+		mnt->mnt_sb->s_subtype = kstrdup(sc->subtype, GFP_KERNEL);
+		if (!mnt->mnt_sb->s_subtype)
+			return -ENOMEM;
 	}
 
 	ret = -EPERM;
@@ -2589,8 +2510,10 @@ static int do_new_mount(struct path *mountpoint, const char *fstype, int flags,
 		return -EINVAL;
 
 	sc = vfs_new_sb_config(fstype);
-	if (IS_ERR(sc))
-		return PTR_ERR(sc);
+	if (IS_ERR(sc)) {
+		err = PTR_ERR(sc);
+		goto err;
+	}
 	sc->ms_flags = flags;
 
 	err = -ENOMEM;
@@ -2602,6 +2525,10 @@ static int do_new_mount(struct path *mountpoint, const char *fstype, int flags,
 	if (err < 0)
 		goto err_sc;
 
+	err = vfs_create_super(sc);
+	if (err < 0)
+		goto err_sc;
+
 	err = do_new_mount_sc(sc, mountpoint, mnt_flags);
 	if (err)
 		goto err_sc;
@@ -2613,6 +2540,7 @@ static int do_new_mount(struct path *mountpoint, const char *fstype, int flags,
 	if (sc->error_msg)
 		pr_info("Mount failed: %s\n", sc->error_msg);
 	put_sb_config(sc);
+err:
 	return err;
 }
 
@@ -3146,53 +3074,83 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
 	return ret;
 }
 
-static struct dentry *__do_mount_sc(struct sb_config *sc)
+/**
+ * vfs_create_super - Create a superblock from a configuration.
+ * @sc: The superblock configuration context.
+ *
+ * The filesystem is invoked to try and create a superblock which can then
+ * later be used for mounting.  The filesystem places a pointer to the
+ * superblock in @sc->sb and to the filesystem root in @sc->root.
+ */
+int vfs_create_super(struct sb_config *sc)
 {
-	struct super_block *sb;
-	struct dentry *root;
 	int ret;
 
-	root = sc->ops->mount(sc);
-	if (IS_ERR(root))
-		return root;
+	if (sc->sb)
+		return -EBUSY;
+
+	if (sc->ops->validate) {
+		ret = sc->ops->validate(sc);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* We assume that the filesystem may transfer preallocated resources
+	 * from the configuration context to the superblock, thereby rendering
+	 * the config unusable for another attempt at creation if this one
+	 * fails.
+	 */
+	if (sc->degraded)
+		return sb_cfg_inval(sc, "VFS: The config is degraded");
+	sc->degraded = true;
+
+	ret = sc->ops->create_super(sc);
+	if (ret < 0)
+		return ret;
 
-	sb = root->d_sb;
-	BUG_ON(!sb);
-	WARN_ON(!sb->s_bdi);
-	sb->s_flags |= MS_BORN;
+	BUG_ON(!sc->sb);
+	WARN_ON(!sc->sb->s_bdi);
+	sc->sb->s_flags |= MS_BORN;
 
-	ret = security_sb_config_kern_mount(sc, sb);
+	ret = security_sb_create_super(sc);
 	if (ret < 0)
 		goto err_sb;
 
-	/*
-	 * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE
-	 * but s_maxbytes was an unsigned long long for many releases. Throw
+	/* Filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE
+	 * but s_maxbytes was an unsigned long long for many releases.  Throw
 	 * this warning for a little while to try and catch filesystems that
 	 * violate this rule.
 	 */
-	WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
-		"negative value (%lld)\n", sc->fs_type->name, sb->s_maxbytes);
+	WARN(sc->sb->s_maxbytes < 0,
+	     "%s set sb->s_maxbytes to negative value (%lld)\n",
+	     sc->fs_type->name, sc->sb->s_maxbytes);
 
-	up_write(&sb->s_umount);
-	return root;
+	up_write(&sc->sb->s_umount);
+	return 0;
 
 err_sb:
-	dput(root);
-	deactivate_locked_super(sb);
-	return ERR_PTR(ret);
+	dput(sc->root);
+	deactivate_locked_super(sc->sb);
+	sc->root = NULL;
+	sc->sb = NULL;
+	return ret;
 }
+EXPORT_SYMBOL(vfs_create_super);
 
+/**
+ * vfs_kern_mount_sc - Create a mount for a configured superblock
+ * sc: The configuration context with the superblock attached
+ *
+ * Create a mount to an already configured superblock.  If necessary, the
+ * caller should invoke vfs_create_super() before calling this.
+ */
 struct vfsmount *vfs_kern_mount_sc(struct sb_config *sc)
 {
-	struct dentry *root;
 	struct mount *mnt;
-	int ret;
 
-	if (sc->ops->validate) {
-		ret = sc->ops->validate(sc);
-		if (ret < 0)
-			return ERR_PTR(ret);
+	if (!sc->sb) {
+		pr_err("vfs_kern_mount_sc: No superblock attached to config\n");
+		return ERR_PTR(-EINVAL);
 	}
 
 	mnt = alloc_vfsmnt(sc->device ?: "none");
@@ -3202,24 +3160,65 @@ struct vfsmount *vfs_kern_mount_sc(struct sb_config *sc)
 	if (sc->ms_flags & MS_KERNMOUNT)
 		mnt->mnt.mnt_flags = MNT_INTERNAL;
 
-	root = __do_mount_sc(sc);
-	if (IS_ERR(root)) {
-		mnt_free_id(mnt);
-		free_vfsmnt(mnt);
-		return ERR_CAST(root);
-	}
-
-	mnt->mnt.mnt_root	= root;
-	mnt->mnt.mnt_sb		= root->d_sb;
+	atomic_inc(&sc->sb->s_active);
+	mnt->mnt.mnt_sb		= sc->sb;
+	mnt->mnt.mnt_root	= dget(sc->root);
 	mnt->mnt_mountpoint	= mnt->mnt.mnt_root;
 	mnt->mnt_parent		= mnt;
+
 	lock_mount_hash();
-	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
+	list_add_tail(&mnt->mnt_instance, &sc->sb->s_mounts);
 	unlock_mount_hash();
 	return &mnt->mnt;
 }
 EXPORT_SYMBOL_GPL(vfs_kern_mount_sc);
 
+struct vfsmount *vfs_kern_mount(struct file_system_type *type,
+				int flags, const char *name, void *data)
+{
+	struct sb_config *sc;
+	struct vfsmount *mnt;
+	int ret;
+
+	if (!type)
+		return ERR_PTR(-EINVAL);
+
+	sc = __vfs_new_sb_config(type, NULL, flags, SB_CONFIG_FOR_NEW);
+	if (IS_ERR(sc))
+		return ERR_CAST(sc);
+
+	if (name) {
+		ret = -ENOMEM;
+		sc->device = kstrdup(name, GFP_KERNEL);
+		if (!sc->device)
+			goto err_sc;
+	}
+
+	ret = parse_monolithic_mount_data(sc, data);
+	if (ret < 0)
+		goto err_sc;
+
+	ret = vfs_create_super(sc);
+	if (ret < 0)
+		goto err_sc;
+
+	mnt = vfs_kern_mount_sc(sc);
+	if (IS_ERR(mnt)) {
+		ret = PTR_ERR(mnt);
+		goto err_sc;
+	}
+
+	put_sb_config(sc);
+	return mnt;
+
+err_sc:
+	if (sc->error_msg)
+		pr_info("Kernmount failed: %s\n", sc->error_msg);
+	put_sb_config(sc);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(vfs_kern_mount);
+
 struct vfsmount *
 vfs_submount_sc(const struct dentry *mountpoint, struct sb_config *sc)
 {
@@ -3235,6 +3234,21 @@ vfs_submount_sc(const struct dentry *mountpoint, struct sb_config *sc)
 }
 EXPORT_SYMBOL_GPL(vfs_submount_sc);
 
+struct vfsmount *
+vfs_submount(const struct dentry *mountpoint, struct file_system_type *type,
+	     const char *name, void *data)
+{
+	/* Until it is worked out how to pass the user namespace
+	 * through from the parent mount to the submount don't support
+	 * unprivileged mounts with submounts.
+	 */
+	if (mountpoint->d_sb->s_user_ns != &init_user_ns)
+		return ERR_PTR(-EPERM);
+
+	return vfs_kern_mount(type, MS_SUBMOUNT, name, data);
+}
+EXPORT_SYMBOL_GPL(vfs_submount);
+
 /*
  * Mount a new, prepared superblock (specified by fs_fd) on the location
  * specified by dfd and dir_name.  dfd can be AT_FDCWD, a dir fd or a container
@@ -3263,17 +3277,14 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, int, dfd, const char __user *, dir_name)
 	    ((sc->ms_flags & MS_MANDLOCK) && !may_mandlock()))
 		goto err_fsfd;
 
-	/* Prevent further changes. */
+	/* There must be a valid superblock or we can't mount it */
 	inode = file_inode(f.file);
 	ret = inode_lock_killable(inode);
-	if (ret < 0)
-		goto err_fsfd;
-	ret = -EBUSY;
-	if (!sc->mounted) {
-		sc->mounted = true;
-		ret = 0;
+	if (ret == 0) {
+		if (!sc->sb)
+			ret = -EINVAL;
+		inode_unlock(inode);
 	}
-	inode_unlock(inode);
 	if (ret < 0)
 		goto err_fsfd;
 
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 391dafaf9182..92e9036d9c6a 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -66,68 +66,71 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
 }
 
 /*
- * get an NFS2/NFS3 root dentry from the root filehandle
+ * get an NFS2/NFS3 root dentry from the root filehandle.
  */
-struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
-			    const char *devname)
+int nfs_get_root(struct nfs_sb_config *cfg)
 {
-	struct nfs_server *server = NFS_SB(sb);
+	struct nfs_server *server = NFS_SB(cfg->sc.sb);
 	struct nfs_fsinfo fsinfo;
-	struct dentry *ret;
+	struct dentry *root;
 	struct inode *inode;
-	void *name = kstrdup(devname, GFP_KERNEL);
-	int error;
+	char *name;
+	int error = -ENOMEM;
 
+	name = kstrdup(cfg->sc.device, GFP_KERNEL);
 	if (!name)
-		return ERR_PTR(-ENOMEM);
-
+		goto out;
+	
 	/* get the actual root for this mount */
 	fsinfo.fattr = nfs_alloc_fattr();
-	if (fsinfo.fattr == NULL) {
-		kfree(name);
-		return ERR_PTR(-ENOMEM);
-	}
+	if (fsinfo.fattr == NULL)
+		goto out_name;
 
-	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+	error = server->nfs_client->rpc_ops->getroot(server, cfg->mntfh, &fsinfo);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
-		ret = ERR_PTR(error);
-		goto out;
+		nfs_cfg_error(cfg, "NFS: Couldn't getattr on root");
+		goto out_fattr;
 	}
 
-	inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL);
+	inode = nfs_fhget(cfg->sc.sb, cfg->mntfh, fsinfo.fattr, NULL);
 	if (IS_ERR(inode)) {
 		dprintk("nfs_get_root: get root inode failed\n");
-		ret = ERR_CAST(inode);
-		goto out;
+		error = PTR_ERR(inode);
+		nfs_cfg_error(cfg, "NFS: Couldn't get root inode");
+		goto out_fattr;
 	}
 
-	error = nfs_superblock_set_dummy_root(sb, inode);
-	if (error != 0) {
-		ret = ERR_PTR(error);
-		goto out;
-	}
+	error = nfs_superblock_set_dummy_root(cfg->sc.sb, inode);
+	if (error != 0)
+		goto out_fattr;
 
 	/* root dentries normally start off anonymous and get spliced in later
 	 * if the dentry tree reaches them; however if the dentry already
 	 * exists, we'll pick it up at this point and use it as the root
 	 */
-	ret = d_obtain_root(inode);
-	if (IS_ERR(ret)) {
+	root = d_obtain_root(inode);
+	if (IS_ERR(root)) {
 		dprintk("nfs_get_root: get root dentry failed\n");
-		goto out;
+		error = PTR_ERR(root);
+		nfs_cfg_error(cfg, "NFS: Couldn't get root dentry");
+		goto out_fattr;
 	}
 
-	security_d_instantiate(ret, inode);
-	spin_lock(&ret->d_lock);
-	if (IS_ROOT(ret) && !ret->d_fsdata &&
-	    !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
-		ret->d_fsdata = name;
+	security_d_instantiate(root, inode);
+	spin_lock(&root->d_lock);
+	if (IS_ROOT(root) && !root->d_fsdata &&
+	    !(root->d_flags & DCACHE_NFSFS_RENAMED)) {
+		root->d_fsdata = name;
 		name = NULL;
 	}
-	spin_unlock(&ret->d_lock);
-out:
-	kfree(name);
+	spin_unlock(&root->d_lock);
+	error = 0;
+
+out_fattr:
 	nfs_free_fattr(fsinfo.fattr);
-	return ret;
+out_name:
+	kfree(name);
+out:
+	return error;
 }
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index f6a1c4876c2b..892ef0364178 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -131,8 +131,7 @@ struct nfs_sb_config {
 	struct nfs_fh		*mntfh;
 	struct nfs_subversion	*nfs_mod;
 
-	int (*set_security)(struct super_block *, struct dentry *,
-			    struct nfs_sb_config *);
+	int (*set_security)(struct nfs_sb_config *);
 
 	/* Information for a cloned mount. */
 	struct nfs_clone_mount {
@@ -416,12 +415,12 @@ extern int nfs_wait_atomic_killable(atomic_t *p);
 extern const struct super_operations nfs_sops;
 extern struct file_system_type nfs_fs_type;
 bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
-struct dentry *nfs_try_mount(struct nfs_sb_config *);
-int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_sb_config *);
-int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_sb_config *);
-struct dentry *nfs_fs_mount_common(struct nfs_server *, struct nfs_sb_config *);
+int nfs_try_create_super(struct nfs_sb_config *);
+int nfs_set_sb_security(struct nfs_sb_config *);
+int nfs_clone_sb_security(struct nfs_sb_config *);
+int nfs_create_super_common(struct nfs_server *, struct nfs_sb_config *);
 void nfs_kill_super(struct super_block *);
-int nfs_fill_super(struct super_block *, struct sb_config *);
+int nfs_fill_super(struct sb_config *);
 
 extern struct rpc_stat nfs_rpcstat;
 
@@ -454,12 +453,9 @@ struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
 				 struct nfs_fattr *, rpc_authflavor_t);
 
 /* getroot.c */
-extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
-				   const char *);
+extern int nfs_get_root(struct nfs_sb_config *cfg);
 #if IS_ENABLED(CONFIG_NFS_V4)
-extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
-				    const char *);
-
+extern int nfs4_get_root(struct nfs_sb_config *cfg);
 extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool);
 #endif
 
diff --git a/fs/nfs/mount.c b/fs/nfs/mount.c
index 180e05e83633..a04dc298bc86 100644
--- a/fs/nfs/mount.c
+++ b/fs/nfs/mount.c
@@ -1274,20 +1274,20 @@ static int nfs_sb_config_validate(struct sb_config *sc)
 /*
  * Use the preparsed information in the mount context to effect a mount.
  */
-static struct dentry *nfs_ordinary_mount(struct nfs_sb_config *cfg)
+static int nfs_create_ordinary_super(struct nfs_sb_config *cfg)
 {
 	cfg->set_security = nfs_set_sb_security;
 
-	return cfg->nfs_mod->rpc_ops->try_mount(cfg);
+	return cfg->nfs_mod->rpc_ops->try_create_super(cfg);
 }
 
 /*
  * Clone an NFS2/3/4 server record on xdev traversal (FSID-change)
  */
-static struct dentry *nfs_xdev_mount(struct nfs_sb_config *cfg)
+static int nfs_create_xdev_super(struct nfs_sb_config *cfg)
 {
 	struct nfs_server *server;
-	struct dentry *mntroot = ERR_PTR(-ENOMEM);
+	int ret;
 
 	dprintk("--> nfs_xdev_mount()\n");
 
@@ -1300,52 +1300,50 @@ static struct dentry *nfs_xdev_mount(struct nfs_sb_config *cfg)
 						     cfg->selected_flavor);
 
 	if (IS_ERR(server))
-		mntroot = ERR_CAST(server);
+		ret = PTR_ERR(server);
 	else
-		mntroot = nfs_fs_mount_common(server, cfg);
+		ret = nfs_create_super_common(server, cfg);
 
-	dprintk("<-- nfs_xdev_mount() = %ld\n",
-			IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L);
-	return mntroot;
+	dprintk("<-- nfs_xdev_mount() = %d\n", ret);
+	return ret;
 }
 
 /*
- * Handle ordinary mounts inspired by the user and cross-FSID mounts.
+ * Create an NFS superblock by the appropriate method.
  */
-struct dentry *nfs_general_mount(struct nfs_sb_config *cfg)
-{
-	switch (cfg->mount_type) {
-	case NFS_MOUNT_ORDINARY:
-		return nfs_ordinary_mount(cfg);
-
-	case NFS_MOUNT_CROSS_DEV:
-		return nfs_xdev_mount(cfg);
-
-	default:
-		nfs_cfg_error(cfg, "NFS: Unknown mount type");
-		return ERR_PTR(-ENOTSUPP);
-	}
-}
-EXPORT_SYMBOL_GPL(nfs_general_mount);
-
-static struct dentry *nfs_fs_mount(struct sb_config *sc)
+static int nfs_create_super(struct sb_config *sc)
 {
 	struct nfs_sb_config *cfg = container_of(sc, struct nfs_sb_config, sc);
+	int ret;
 
 	if (!cfg->nfs_mod) {
 		pr_warn("Missing nfs_mod\n");
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 	if (!cfg->nfs_mod->rpc_ops) {
 		pr_warn("Missing rpc_ops\n");
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
-	if (!cfg->nfs_mod->rpc_ops->mount) {
-		pr_warn("Missing mount\n");
-		return ERR_PTR(-EINVAL);
+	if (!cfg->nfs_mod->rpc_ops->create_super) {
+		pr_warn("Missing create_super\n");
+		return -EINVAL;
 	}
 
-	return cfg->nfs_mod->rpc_ops->mount(cfg);
+	ret = cfg->nfs_mod->rpc_ops->create_super(cfg);
+	if (ret != 1)
+		return ret;
+
+	switch (cfg->mount_type) {
+	case NFS_MOUNT_ORDINARY:
+		return nfs_create_ordinary_super(cfg);
+
+	case NFS_MOUNT_CROSS_DEV:
+		return nfs_create_xdev_super(cfg);
+
+	default:
+		nfs_cfg_error(cfg, "NFS: Unknown mount type");
+		return -ENOTSUPP;
+	}
 }
 
 /*
@@ -1392,7 +1390,7 @@ static const struct sb_config_operations nfs_sb_config_ops = {
 	.parse_option		= nfs_sb_config_parse_option,
 	.monolithic_mount_data	= nfs_monolithic_mount_data,
 	.validate		= nfs_sb_config_validate,
-	.mount			= nfs_fs_mount,
+	.create_super		= nfs_create_super,
 	.fill_super		= nfs_fill_super,
 };
 
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 1e0349fc33ec..13ebaa5a6f03 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -922,9 +922,8 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
 	.file_inode_ops	= &nfs3_file_inode_operations,
 	.file_ops	= &nfs_file_operations,
 	.getroot	= nfs3_proc_get_root,
-	.mount		= nfs_general_mount,
 	.submount	= nfs_submount,
-	.try_mount	= nfs_try_mount,
+	.try_create_super = nfs_try_create_super,
 	.getattr	= nfs3_proc_getattr,
 	.setattr	= nfs3_proc_setattr,
 	.lookup		= nfs3_proc_lookup,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 05769b633b76..138ad1cf8d89 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -476,8 +476,8 @@ extern bool recover_lost_locks;
 #define NFS4_CLIENT_ID_UNIQ_LEN		(64)
 extern char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN];
 
-extern struct dentry *nfs4_try_mount(struct nfs_sb_config *);
-extern struct dentry *nfs4_mount(struct nfs_sb_config *);
+extern int nfs4_try_create_super(struct nfs_sb_config *);
+extern int nfs4_create_super(struct nfs_sb_config *);
 
 /* nfs4sysctl.c */
 #ifdef CONFIG_SYSCTL
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 32d8c10bc45e..46974e6231f1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -9318,9 +9318,9 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 	.file_inode_ops	= &nfs4_file_inode_operations,
 	.file_ops	= &nfs4_file_operations,
 	.getroot	= nfs4_proc_get_root,
-	.mount		= nfs4_mount,
+	.create_super	= nfs4_create_super,
 	.submount	= nfs4_submount,
-	.try_mount	= nfs4_try_mount,
+	.try_create_super = nfs4_try_create_super,
 	.getattr	= nfs4_proc_getattr,
 	.setattr	= nfs4_proc_setattr,
 	.lookup		= nfs4_proc_lookup,
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 7bc27a28d5da..70e5841f92b9 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -18,9 +18,9 @@
 
 static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc);
 static void nfs4_evict_inode(struct inode *inode);
-static struct dentry *nfs4_remote_mount(struct nfs_sb_config *cfg);
-static struct dentry *nfs4_referral_mount(struct nfs_sb_config *cfg);
-static struct dentry *nfs4_remote_referral_mount(struct nfs_sb_config *cfg);
+static int nfs4_remote_mount(struct nfs_sb_config *cfg);
+static int nfs4_referral_mount(struct nfs_sb_config *cfg);
+static int nfs4_remote_referral_mount(struct nfs_sb_config *cfg);
 
 static const struct super_operations nfs4_sops = {
 	.alloc_inode	= nfs_alloc_inode,
@@ -77,7 +77,7 @@ static void nfs4_evict_inode(struct inode *inode)
 /*
  * Get the superblock for the NFS4 root partition
  */
-static struct dentry *nfs4_remote_mount(struct nfs_sb_config *cfg)
+static int nfs4_remote_mount(struct nfs_sb_config *cfg)
 {
 	struct nfs_server *server;
 
@@ -86,9 +86,9 @@ static struct dentry *nfs4_remote_mount(struct nfs_sb_config *cfg)
 	/* Get a volume representation */
 	server = nfs4_create_server(cfg);
 	if (IS_ERR(server))
-		return ERR_CAST(server);
+		return PTR_ERR(server);
 
-	return nfs_fs_mount_common(server, cfg);
+	return nfs_create_super_common(server, cfg);
 }
 
 /*
@@ -104,6 +104,7 @@ static struct vfsmount *nfs_do_root_mount(struct nfs_sb_config *cfg,
 	struct vfsmount *root_mnt;
 	char *root_devname;
 	size_t len;
+	int ret;
 
 	root_sc = vfs_dup_sb_config(&cfg->sc);
 	if (IS_ERR(root_sc))
@@ -126,6 +127,10 @@ static struct vfsmount *nfs_do_root_mount(struct nfs_sb_config *cfg,
 		snprintf(root_devname, len, "%s:/", hostname);
 	root_cfg->sc.device = root_devname;
 
+	ret = vfs_create_super(&root_cfg->sc);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
 	root_mnt = vfs_kern_mount_sc(&root_cfg->sc);
 out_sc:
 	put_sb_config(root_sc);
@@ -219,12 +224,12 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
 	return dentry;
 }
 
-struct dentry *nfs4_try_mount(struct nfs_sb_config *cfg)
+int nfs4_try_create_super(struct nfs_sb_config *cfg)
 {
 	struct vfsmount *root_mnt;
-	struct dentry *res;
+	struct dentry *root;
 
-	dfprintk(MOUNT, "--> nfs4_try_mount()\n");
+	dfprintk(MOUNT, "--> nfs4_try_create_super()\n");
 
 	/* We create a mount for the server's root, walk to the requested
 	 * location and then create another mount for that.
@@ -232,19 +237,23 @@ struct dentry *nfs4_try_mount(struct nfs_sb_config *cfg)
 	root_mnt = nfs_do_root_mount(cfg, cfg->nfs_server.hostname,
 				     NFS4_MOUNT_REMOTE);
 	if (IS_ERR(root_mnt))
-		return ERR_CAST(root_mnt);
+		return PTR_ERR(root_mnt);
 
-	res = nfs_follow_remote_path(root_mnt, cfg->nfs_server.export_path);
-	if (IS_ERR(res))
+	root = nfs_follow_remote_path(root_mnt, cfg->nfs_server.export_path);
+	if (IS_ERR(root)) {
 		nfs_cfg_error(cfg, "NFS4: Couldn't follow remote path");
+		dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld [error]\n",
+			 PTR_ERR(root));
+		return PTR_ERR(root);
+	}
 
-	dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n",
-		 PTR_ERR_OR_ZERO(res),
-		 IS_ERR(res) ? " [error]" : "");
-	return res;
+	cfg->sc.sb = root->d_sb;  // Do we need a ref for this?
+	cfg->sc.root = root;
+	dfprintk(MOUNT, "<-- nfs4_try_create_super() = 0\n");
+	return 0;
 }
 
-static struct dentry *nfs4_remote_referral_mount(struct nfs_sb_config *cfg)
+static int nfs4_remote_referral_mount(struct nfs_sb_config *cfg)
 {
 	struct nfs_server *server;
 
@@ -253,40 +262,47 @@ static struct dentry *nfs4_remote_referral_mount(struct nfs_sb_config *cfg)
 	cfg->set_security = nfs_clone_sb_security;
 
 	if (!cfg->clone_data.cloned)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	/* create a new volume representation */
 	server = nfs4_create_referral_server(cfg);
 	if (IS_ERR(server))
-		return ERR_CAST(server);
+		return PTR_ERR(server);
 
-	return nfs_fs_mount_common(server, cfg);
+	return nfs_create_super_common(server, cfg);
 }
 
 /*
  * Create an NFS4 server record on referral traversal
  */
-static struct dentry *nfs4_referral_mount(struct nfs_sb_config *cfg)
+static int nfs4_referral_mount(struct nfs_sb_config *cfg)
 {
 	struct vfsmount *root_mnt;
-	struct dentry *res;
+	struct dentry *root;
 
 	dprintk("--> nfs4_referral_mount()\n");
 
 	root_mnt = nfs_do_root_mount(cfg, cfg->nfs_server.hostname,
 				     NFS4_MOUNT_REMOTE_REFERRAL);
 
-	res = nfs_follow_remote_path(root_mnt, cfg->nfs_server.export_path);
-	dprintk("<-- nfs4_referral_mount() = %d%s\n",
-		PTR_ERR_OR_ZERO(res),
-		IS_ERR(res) ? " [error]" : "");
-	return res;
+	root = nfs_follow_remote_path(root_mnt, cfg->nfs_server.export_path);
+	if (IS_ERR(root)) {
+		nfs_cfg_error(cfg, "NFS4: Couldn't follow remote path");
+		dfprintk(MOUNT, "<-- nfs4_referral_mount() = %ld [error]\n",
+			 PTR_ERR(root));
+		return PTR_ERR(root);
+	}
+
+	cfg->sc.sb = root->d_sb;  // Do we need a ref for this?
+	cfg->sc.root = root;
+	dfprintk(MOUNT, "<-- nfs4_referral_mount() = 0\n");
+	return 0;
 }
 
 /*
  * Handle special NFS4 mount types.
  */
-struct dentry *nfs4_mount(struct nfs_sb_config *cfg)
+int nfs4_create_super(struct nfs_sb_config *cfg)
 {
 	switch (cfg->mount_type) {
 	case NFS4_MOUNT_REMOTE:
@@ -299,7 +315,7 @@ struct dentry *nfs4_mount(struct nfs_sb_config *cfg)
 		return nfs4_remote_referral_mount(cfg);
 
 	default:
-		return nfs_general_mount(cfg);
+		return 1;
 	}
 }
 
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index edae9cd50412..23d567edd5cd 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -704,9 +704,8 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
 	.file_inode_ops	= &nfs_file_inode_operations,
 	.file_ops	= &nfs_file_operations,
 	.getroot	= nfs_proc_get_root,
-	.mount		= nfs_general_mount,
 	.submount	= nfs_submount,
-	.try_mount	= nfs_try_mount,
+	.try_create_super = nfs_try_create_super,
 	.getattr	= nfs_proc_getattr,
 	.setattr	= nfs_proc_setattr,
 	.lookup		= nfs_proc_lookup,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 354044fec350..45afb242852b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -855,7 +855,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_sb_config *cfg)
 	return cfg->nfs_mod->rpc_ops->create_server(cfg);
 }
 
-struct dentry *nfs_try_mount(struct nfs_sb_config *cfg)
+int nfs_try_create_super(struct nfs_sb_config *cfg)
 {
 	struct nfs_server *server;
 
@@ -866,12 +866,12 @@ struct dentry *nfs_try_mount(struct nfs_sb_config *cfg)
 
 	if (IS_ERR(server)) {
 		nfs_cfg_error(cfg, "NFS: Couldn't create server");
-		return ERR_CAST(server);
+		return PTR_ERR(server);
 	}
 
-	return nfs_fs_mount_common(server, cfg);
+	return nfs_create_super_common(server, cfg);
 }
-EXPORT_SYMBOL_GPL(nfs_try_mount);
+EXPORT_SYMBOL_GPL(nfs_try_create_super);
 
 
 #define NFS_REMOUNT_CMP_FLAGMASK ~(NFS_MOUNT_INTR \
@@ -997,10 +997,11 @@ static int nfs_clone_super(struct super_block *sb, struct sb_config *sc)
 /*
  * Finish setting up an NFS2/3 superblock
  */
-int nfs_fill_super(struct super_block *sb, struct sb_config *sc)
+int nfs_fill_super(struct sb_config *sc)
 {
 	struct nfs_sb_config *cfg =
 		container_of(sc, struct nfs_sb_config, sc);
+	struct super_block *sb = cfg->sc.sb;
 	struct nfs_server *server = NFS_SB(sb);
 	int ret;
 
@@ -1182,40 +1183,38 @@ static void nfs_get_cache_cookie(struct super_block *sb,
 }
 #endif
 
-int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
-			struct nfs_sb_config *cfg)
+int nfs_set_sb_security(struct nfs_sb_config *cfg)
 {
 	int error;
 	unsigned long kflags = 0, kflags_out = 0;
 
-	if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
+	if (NFS_SB(cfg->sc.sb)->caps & NFS_CAP_SECURITY_LABEL)
 		kflags |= SECURITY_LSM_NATIVE_LABELS;
 
-	error = security_sb_set_mnt_opts(s, cfg->sc.security,
+	error = security_sb_set_mnt_opts(cfg->sc.sb, cfg->sc.security,
 					 kflags, &kflags_out);
 	if (error)
 		goto err;
 
-	if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
-		!(kflags_out & SECURITY_LSM_NATIVE_LABELS))
-		NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
+	if (NFS_SB(cfg->sc.sb)->caps & NFS_CAP_SECURITY_LABEL &&
+	    !(kflags_out & SECURITY_LSM_NATIVE_LABELS))
+		NFS_SB(cfg->sc.sb)->caps &= ~NFS_CAP_SECURITY_LABEL;
 err:
 	return error;
 }
 EXPORT_SYMBOL_GPL(nfs_set_sb_security);
 
-int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
-			  struct nfs_sb_config *cfg)
+int nfs_clone_sb_security(struct nfs_sb_config *cfg)
 {
 	/* clone any lsm security options from the parent to the new sb */
-	if (d_inode(mntroot)->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops)
+	if (d_inode(cfg->sc.root)->i_op !=
+	    NFS_SB(cfg->sc.sb)->nfs_client->rpc_ops->dir_inode_ops)
 		return -ESTALE;
-	return security_sb_clone_mnt_opts(cfg->clone_data.sb, s);
+	return security_sb_clone_mnt_opts(cfg->clone_data.sb, cfg->sc.sb);
 }
 EXPORT_SYMBOL_GPL(nfs_clone_sb_security);
 
-struct dentry *nfs_fs_mount_common(struct nfs_server *server,
-				   struct nfs_sb_config *cfg)
+int nfs_create_super_common(struct nfs_server *server, struct nfs_sb_config *cfg)
 {
 	struct super_block *s;
 	struct dentry *mntroot = ERR_PTR(-ENOMEM);
@@ -1241,11 +1240,13 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
 	s = sget(cfg->nfs_mod->nfs_fs, compare_super, nfs_set_super, cfg->sc.ms_flags,
 		 &sb_mntdata);
 	if (IS_ERR(s)) {
-		mntroot = ERR_CAST(s);
+		error = PTR_ERR(s);
 		nfs_cfg_error(cfg, "NFS: Couldn't get superblock");
 		goto out_err_nosb;
 	}
 
+	cfg->sc.sb = s;
+
 	if (s->s_fs_info != server) {
 		nfs_free_server(server);
 		server = NULL;
@@ -1255,24 +1256,25 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
 
 	if (!s->s_root) {
 		/* initial superblock/root creation */
-		cfg->sc.ops->fill_super(s, &cfg->sc);
+		cfg->sc.ops->fill_super(&cfg->sc);
 		nfs_get_cache_cookie(s, cfg);
 	}
 
-	mntroot = nfs_get_root(s, cfg->mntfh, cfg->sc.device);
-	if (IS_ERR(mntroot)) {
+	error = nfs_get_root(cfg);
+	if (error < 0) {
 		nfs_cfg_error(cfg, "NFS: Couldn't get root dentry");
 		goto error_splat_super;
 	}
 
-	error = cfg->set_security(s, mntroot, cfg);
+	error = cfg->set_security(cfg);
 	if (error)
 		goto error_splat_root;
 
 	s->s_flags |= MS_ACTIVE;
+	error = 0;
 
 out:
-	return mntroot;
+	return error;
 
 out_err_nosb:
 	nfs_free_server(server);
@@ -1280,12 +1282,12 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
 
 error_splat_root:
 	dput(mntroot);
-	mntroot = ERR_PTR(error);
 error_splat_super:
-	deactivate_locked_super(s);
+	deactivate_locked_super(cfg->sc.sb);
+	cfg->sc.sb = NULL;
 	goto out;
 }
-EXPORT_SYMBOL_GPL(nfs_fs_mount_common);
+EXPORT_SYMBOL_GPL(nfs_create_super_common);
 
 /*
  * Destroy an NFS2/3 superblock
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 87d1a3ffec70..c3e1203641f1 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -94,9 +94,10 @@ static void proc_set_options(struct super_block *s,
 		pid_ns->hide_pid = ctx->hidepid;
 }
 
-static int proc_fill_super(struct super_block *s, struct sb_config *sc)
+static int proc_fill_super(struct sb_config *sc)
 {
-	struct pid_namespace *pid_ns = get_pid_ns(s->s_fs_info);
+	struct pid_namespace *pid_ns = get_pid_ns(sc->pid_ns);
+	struct super_block *s = sc->sb;
 	struct inode *root_inode;
 	int ret;
 
@@ -149,14 +150,14 @@ int proc_remount(struct super_block *sb, struct sb_config *sc)
 	return 0;
 }
 
-static struct dentry *proc_mount(struct sb_config *sc)
+static int proc_create_super(struct sb_config *sc)
 {
 	return mount_ns_sc(sc, sc->pid_ns);
 }
 
 static const struct sb_config_operations proc_sb_config_ops = {
 	.parse_option	= proc_parse_mount_option,
-	.mount		= proc_mount,
+	.create_super	= proc_create_super,
 	.fill_super	= proc_fill_super,
 };
 
@@ -285,6 +286,7 @@ int pid_ns_prepare_proc(struct pid_namespace *ns)
 {
 	struct sb_config *sc;
 	struct vfsmount *mnt;
+	int ret;
 
 	sc = __vfs_new_sb_config(&proc_fs_type, NULL, 0, SB_CONFIG_FOR_NEW);
 	if (IS_ERR(sc))
@@ -296,6 +298,12 @@ int pid_ns_prepare_proc(struct pid_namespace *ns)
 		sc->pid_ns = ns;
 	}
 
+	ret = vfs_create_super(sc);
+	if (ret < 0) {
+		put_sb_config(sc);
+		return ret;
+	}
+
 	mnt = kern_mount_data_sc(sc);
 	put_sb_config(sc);
 	if (IS_ERR(mnt))
diff --git a/fs/sb_config.c b/fs/sb_config.c
index 4429ac35161c..d07bade9ba07 100644
--- a/fs/sb_config.c
+++ b/fs/sb_config.c
@@ -127,9 +127,6 @@ int vfs_parse_mount_option(struct sb_config *sc, char *p)
 {
 	int ret;
 
-	if (sc->mounted)
-		return -EBUSY;
-
 	ret = vfs_parse_ms_mount_option(sc, p);
 	if (ret < 0)
 		return ret;
@@ -210,12 +207,13 @@ struct sb_config *__vfs_new_sb_config(struct file_system_type *fs_type,
 	sc->purpose	= purpose;
 	sc->ms_flags	= ms_flags;
 	sc->fs_type	= get_filesystem(fs_type);
-	sc->mnt_ns	= get_mnt_ns(current->nsproxy->mnt_ns);
 	sc->pid_ns	= get_pid_ns(task_active_pid_ns(current));
 	sc->net_ns	= get_net(current->nsproxy->net_ns);
 	sc->user_ns	= get_user_ns(current_user_ns());
 	sc->cred	= get_current_cred();
 
+	if (current->nsproxy->mnt_ns)
+		sc->mnt_ns	= get_mnt_ns(current->nsproxy->mnt_ns);
 
 	/* TODO: Make all filesystems support this unconditionally */
 	if (sc->fs_type->init_sb_config) {
@@ -329,13 +327,34 @@ struct sb_config *vfs_dup_sb_config(struct sb_config *src_sc)
 EXPORT_SYMBOL(vfs_dup_sb_config);
 
 /**
+ * vfs_reconfigure_super - Reconfigure a superblock.
+ * @sc: The configuration updates to apply
+ */
+int vfs_reconfigure_super(struct sb_config *sc)
+{
+	pr_notice("*** vfs_reconfigure_super()\n");
+
+	if (!sc->sb)
+		return -EINVAL;
+	return -ENOANO; // TODO
+}
+EXPORT_SYMBOL(vfs_reconfigure_super);
+
+/**
  * put_sb_config - Dispose of a superblock configuration context.
  * @sc: The context to dispose of.
  */
 void put_sb_config(struct sb_config *sc)
 {
+	dput(sc->root);
+	sc->root = NULL;
+	if (sc->sb)
+		deactivate_super(sc->sb);
+	sc->sb = NULL;
+
 	if (sc->ops && sc->ops->free)
 		sc->ops->free(sc);
+
 	security_sb_config_free(sc);
 	if (sc->mnt_ns)
 		put_mnt_ns(sc->mnt_ns);
@@ -346,6 +365,7 @@ void put_sb_config(struct sb_config *sc)
 	put_user_ns(sc->user_ns);
 	if (sc->cred)
 		put_cred(sc->cred);
+	kfree(sc->subtype);
 	put_filesystem(sc->fs_type);
 	kfree(sc->device);
 	kfree(sc);
@@ -447,9 +467,30 @@ static int legacy_validate(struct sb_config *sc)
 }
 
 /*
- * Perform a legacy mount.
+ * Determine the superblock subtype.
+ */
+static int legacy_set_subtype(struct sb_config *sc)
+{
+	const char *subtype = strchr(sc->fs_type->name, '.');
+
+	if (subtype) {
+		subtype++;
+		if (!subtype[0])
+			return -EINVAL;
+	} else {
+		subtype = "";
+	}
+
+	sc->subtype = kstrdup(subtype, GFP_KERNEL);
+	if (!sc->subtype)
+		return -ENOMEM;
+	return 0;
+}
+
+/*
+ * Create a superblock with the legacy mount command.
  */
-static struct dentry *legacy_mount(struct sb_config *sc)
+static int legacy_create_super(struct sb_config *sc)
 {
 	struct legacy_sb_config *cfg = container_of(sc, struct legacy_sb_config, sc);
 	struct super_block *sb;
@@ -457,22 +498,28 @@ static struct dentry *legacy_mount(struct sb_config *sc)
 	int ret;
 
 	root = cfg->sc.fs_type->mount(cfg->sc.fs_type, cfg->sc.ms_flags,
-				     cfg->sc.device, cfg->legacy_data);
+				      cfg->sc.device, cfg->legacy_data);
 	if (IS_ERR(root))
-		return ERR_CAST(root);
+		return PTR_ERR(root);
 
 	sb = root->d_sb;
 	BUG_ON(!sb);
-	ret = security_sb_kern_mount(sb, cfg->sc.ms_flags, cfg->secdata);
-	if (ret < 0)
-		goto err_sb;
 
-	return root;
+	if ((cfg->sc.fs_type->fs_flags & FS_HAS_SUBTYPE) &&
+	    !sc->subtype) {
+		ret = legacy_set_subtype(sc);
+		if (ret < 0)
+			goto err_sb;
+	}
+
+	cfg->sc.root = root;
+	cfg->sc.sb = sb;
+	return 0;
 
 err_sb:
 	dput(root);
 	deactivate_locked_super(sb);
-	return ERR_PTR(ret);
+	return ret;
 }
 
 static const struct sb_config_operations legacy_sb_config_ops = {
@@ -481,5 +528,5 @@ static const struct sb_config_operations legacy_sb_config_ops = {
 	.parse_option		= legacy_parse_option,
 	.monolithic_mount_data	= legacy_monolithic_mount_data,
 	.validate		= legacy_validate,
-	.mount			= legacy_mount,
+	.create_super		= legacy_create_super,
 };
diff --git a/fs/super.c b/fs/super.c
index 413a2a665f3d..e5c349d06b8d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1058,7 +1058,7 @@ struct dentry *mount_ns(struct file_system_type *fs_type,
 
 EXPORT_SYMBOL(mount_ns);
 
-struct dentry *mount_ns_sc(struct sb_config *sc, void *ns)
+int mount_ns_sc(struct sb_config *sc, void *ns)
 {
 	struct super_block *sb;
 
@@ -1067,25 +1067,30 @@ struct dentry *mount_ns_sc(struct sb_config *sc, void *ns)
 	 */
 	if (!(sc->ms_flags & MS_KERNMOUNT) &&
 	    !ns_capable(sc->user_ns, CAP_SYS_ADMIN))
-		return ERR_PTR(-EPERM);
+		return -EPERM;
 
 	sb = sget_userns(sc->fs_type, ns_test_super, ns_set_super,
 			 sc->ms_flags, sc->user_ns, ns);
 	if (IS_ERR(sb))
-		return ERR_CAST(sb);
+		return PTR_ERR(sb);
+	sc->sb = sb;
 
 	if (!sb->s_root) {
 		int err;
-		err = sc->ops->fill_super(sb, sc);
+		err = sc->ops->fill_super(sc);
 		if (err) {
 			deactivate_locked_super(sb);
-			return ERR_PTR(err);
+			return err;
 		}
 
 		sb->s_flags |= MS_ACTIVE;
 	}
 
-	return dget(sb->s_root);
+	if (!sc->root) {
+		sc->root = sb->s_root;
+		dget(sb->s_root);
+	}
+	return 0;
 }
 EXPORT_SYMBOL(mount_ns_sc);
 
@@ -1243,59 +1248,6 @@ struct dentry *mount_single(struct file_system_type *fs_type,
 }
 EXPORT_SYMBOL(mount_single);
 
-struct dentry *
-mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
-{
-	struct dentry *root;
-	struct super_block *sb;
-	char *secdata = NULL;
-	int error = -ENOMEM;
-
-	if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
-		secdata = alloc_secdata();
-		if (!secdata)
-			goto out;
-
-		error = security_sb_copy_data(data, secdata);
-		if (error)
-			goto out_free_secdata;
-	}
-
-	root = type->mount(type, flags, name, data);
-	if (IS_ERR(root)) {
-		error = PTR_ERR(root);
-		goto out_free_secdata;
-	}
-	sb = root->d_sb;
-	BUG_ON(!sb);
-	WARN_ON(!sb->s_bdi);
-	sb->s_flags |= MS_BORN;
-
-	error = security_sb_kern_mount(sb, flags, secdata);
-	if (error)
-		goto out_sb;
-
-	/*
-	 * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE
-	 * but s_maxbytes was an unsigned long long for many releases. Throw
-	 * this warning for a little while to try and catch filesystems that
-	 * violate this rule.
-	 */
-	WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
-		"negative value (%lld)\n", type->name, sb->s_maxbytes);
-
-	up_write(&sb->s_umount);
-	free_secdata(secdata);
-	return root;
-out_sb:
-	dput(root);
-	deactivate_locked_super(sb);
-out_free_secdata:
-	free_secdata(secdata);
-out:
-	return ERR_PTR(error);
-}
-
 /*
  * Setup private BDI for given superblock. It gets automatically cleaned up
  * in generic_shutdown_super().
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0a07b7449aa2..8e133e4dff95 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2048,7 +2048,7 @@ struct file_system_type {
 
 #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
 
-extern struct dentry *mount_ns_sc(struct sb_config *mc, void *ns);
+extern int mount_ns_sc(struct sb_config *mc, void *ns);
 extern struct dentry *mount_ns(struct file_system_type *fs_type,
 	int flags, void *data, void *ns, struct user_namespace *user_ns,
 	int (*fill_super)(struct super_block *, void *, int));
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index e8e473ce5ddd..b2180629d005 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -97,10 +97,11 @@
  *	filesystem.
  *	@sc indicates the superblock configuration context.
  *	@p indicates the option in "key[=val]" form.
- * @sb_config_kern_mount:
- *	Equivalent of sb_kern_mount, but with a superblock configuration context.
- *	@sc indicates the superblock configuration context.
- *	@src_sb indicates the new superblock.
+ * @sb_create_super:
+ *	Assign the security to a newly created superblock.
+ *	@sc indicates the superblock configuration context.  @sc->sb points to
+ *	the superblock and @sc->root to the root within the superblock to
+ *	actually mount.
  * @sb_config_mountpoint:
  *	Equivalent of sb_mount, but with an sb_config.
  *	@sc indicates the superblock configuration context.
@@ -1393,14 +1394,13 @@ union security_list_options {
 	int (*sb_config_dup)(struct sb_config *sc, struct sb_config *src_sc);
 	void (*sb_config_free)(struct sb_config *sc);
 	int (*sb_config_parse_option)(struct sb_config *sc, char *opt);
-	int (*sb_config_kern_mount)(struct sb_config *sc, struct super_block *sb);
+	int (*sb_create_super)(struct sb_config *sc);
 	int (*sb_config_mountpoint)(struct sb_config *sc, struct path *mountpoint);
 
 	int (*sb_alloc_security)(struct super_block *sb);
 	void (*sb_free_security)(struct super_block *sb);
 	int (*sb_copy_data)(char *orig, char *copy);
 	int (*sb_remount)(struct super_block *sb, void *data);
-	int (*sb_kern_mount)(struct super_block *sb, int flags, void *data);
 	int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs)(struct dentry *dentry);
 	int (*sb_mount)(const char *dev_name, const struct path *path,
@@ -1708,13 +1708,12 @@ struct security_hook_heads {
 	struct list_head sb_config_dup;
 	struct list_head sb_config_free;
 	struct list_head sb_config_parse_option;
-	struct list_head sb_config_kern_mount;
+	struct list_head sb_create_super;
 	struct list_head sb_config_mountpoint;
 	struct list_head sb_alloc_security;
 	struct list_head sb_free_security;
 	struct list_head sb_copy_data;
 	struct list_head sb_remount;
-	struct list_head sb_kern_mount;
 	struct list_head sb_show_options;
 	struct list_head sb_statfs;
 	struct list_head sb_mount;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9377afd5ecc8..8d7024274b2e 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1554,10 +1554,10 @@ struct nfs_rpc_ops {
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsinfo *);
-	struct dentry *(*mount)(struct nfs_sb_config *);
+	int	(*create_super)(struct nfs_sb_config *);
 	struct vfsmount *(*submount) (struct nfs_server *, struct dentry *,
 				      struct nfs_fh *, struct nfs_fattr *);
-	struct dentry *(*try_mount) (struct nfs_sb_config *);
+	int	(*try_create_super) (struct nfs_sb_config *);
 	int	(*getattr) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fattr *, struct nfs4_label *);
 	int	(*setattr) (struct dentry *, struct nfs_fattr *,
diff --git a/include/linux/sb_config.h b/include/linux/sb_config.h
index d479fd29f7d8..c8a9b7ba3bef 100644
--- a/include/linux/sb_config.h
+++ b/include/linux/sb_config.h
@@ -38,23 +38,29 @@ enum sb_config_purpose {
  * allocated is specified in struct file_system_type::sb_config_size and this
  * must include sufficient space for the sb_config struct.
  *
+ * Superblock creation fills in ->sb and ->root whereas reconfiguration begins
+ * with these already set.
+ *
  * See Documentation/filesystems/mounting.txt
  */
 struct sb_config {
 	const struct sb_config_operations *ops;
 	struct file_system_type	*fs_type;
+	struct super_block	*sb;		/* The created sb / sb to be reconfigured */
+	struct dentry		*root;		/* The root to mount (for new mount) */
 	struct user_namespace	*user_ns;	/* The user namespace for this mount */
 	struct mnt_namespace	*mnt_ns;	/* The mount namespace for this mount */
 	struct pid_namespace	*pid_ns;	/* The process ID namespace for this mount */
 	struct net		*net_ns;	/* The network namespace for this mount */
 	const struct cred	*cred;		/* The mounter's credentials */
 	char			*device;	/* The device name or mount target */
+	char			*subtype;	/* The subtype to set on the superblock */
 	void			*security;	/* The LSM context */
 	const char		*error_msg;	/* Error string to be read by read() */
 	unsigned int		ms_flags;	/* The superblock flags (MS_*) */
-	bool			mounted;	/* Set when mounted */
 	bool			sloppy;		/* Unrecognised options are okay */
 	bool			silent;
+	bool			degraded;	/* The config has been degraded and can't be reused */
 	enum sb_config_purpose 	purpose : 8;
 };
 
@@ -64,8 +70,8 @@ struct sb_config_operations {
 	int (*parse_option)(struct sb_config *sc, char *p);
 	int (*monolithic_mount_data)(struct sb_config *sc, void *data);
 	int (*validate)(struct sb_config *sc);
-	struct dentry *(*mount)(struct sb_config *sc);
-	int (*fill_super)(struct super_block *s, struct sb_config *sc);
+	int (*create_super)(struct sb_config *sc);
+	int (*fill_super)(struct sb_config *sc);
 };
 
 extern const struct file_operations fs_fs_fops;
@@ -80,6 +86,8 @@ extern struct sb_config *vfs_sb_reconfig(struct vfsmount *mnt,
 extern struct sb_config *vfs_dup_sb_config(struct sb_config *src);
 extern int vfs_parse_mount_option(struct sb_config *sc, char *data);
 extern int generic_monolithic_mount_data(struct sb_config *sc, void *data);
+extern int vfs_create_super(struct sb_config *sc);
+extern int vfs_reconfigure_super(struct sb_config *sc);
 extern void put_sb_config(struct sb_config *sc);
 
 static inline void sb_cfg_error(struct sb_config *sc, const char *msg)
diff --git a/include/linux/security.h b/include/linux/security.h
index f95dc555cf29..df166b94f15b 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -225,13 +225,12 @@ int security_sb_config_alloc(struct sb_config *sc, struct super_block *sb);
 int security_sb_config_dup(struct sb_config *sc, struct sb_config *src_sc);
 void security_sb_config_free(struct sb_config *sc);
 int security_sb_config_parse_option(struct sb_config *sc, char *opt);
-int security_sb_config_kern_mount(struct sb_config *sc, struct super_block *sb);
+int security_sb_create_super(struct sb_config *sc);
 int security_sb_config_mountpoint(struct sb_config *sc, struct path *mountpoint);
 int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_remount(struct super_block *sb, void *data);
-int security_sb_kern_mount(struct super_block *sb, int flags, void *data);
 int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(const char *dev_name, const struct path *path,
@@ -537,8 +536,7 @@ static inline int security_sb_config_parse_option(struct sb_config *sc, char *op
 {
 	return 0;
 }
-static inline int security_sb_config_kern_mount(struct sb_config *sc,
-						struct super_block *sb)
+static inline int security_sb_create_super(struct sb_config *sc)
 {
 	return 0;
 }
@@ -566,11 +564,6 @@ static inline int security_sb_remount(struct super_block *sb, void *data)
 	return 0;
 }
 
-static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
-{
-	return 0;
-}
-
 static inline int security_sb_show_options(struct seq_file *m,
 					   struct super_block *sb)
 {
diff --git a/security/security.c b/security/security.c
index 8b2b7e6b3112..d2b8ec031b57 100644
--- a/security/security.c
+++ b/security/security.c
@@ -329,9 +329,9 @@ int security_sb_config_parse_option(struct sb_config *sc, char *opt)
 	return call_int_hook(sb_config_parse_option, 0, sc, opt);
 }
 
-int security_sb_config_kern_mount(struct sb_config *sc, struct super_block *sb)
+int security_sb_create_super(struct sb_config *sc)
 {
-	return call_int_hook(sb_config_kern_mount, 0, sc, sb);
+	return call_int_hook(sb_create_super, 0, sc);
 }
 
 int security_sb_config_mountpoint(struct sb_config *sc, struct path *mountpoint)
@@ -360,11 +360,6 @@ int security_sb_remount(struct super_block *sb, void *data)
 	return call_int_hook(sb_remount, 0, sb, data);
 }
 
-int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
-{
-	return call_int_hook(sb_kern_mount, 0, sb, flags, data);
-}
-
 int security_sb_show_options(struct seq_file *m, struct super_block *sb)
 {
 	return call_int_hook(sb_show_options, 0, m, sb);
@@ -1694,8 +1689,7 @@ struct security_hook_heads security_hook_heads = {
 	.sb_config_free = LIST_HEAD_INIT(security_hook_heads.sb_config_free),
 	.sb_config_parse_option =
 		LIST_HEAD_INIT(security_hook_heads.sb_config_parse_option),
-	.sb_config_kern_mount =
-		LIST_HEAD_INIT(security_hook_heads.sb_config_kern_mount),
+	.sb_create_super = LIST_HEAD_INIT(security_hook_heads.sb_create_super),
 	.sb_config_mountpoint =
 		LIST_HEAD_INIT(security_hook_heads.sb_config_mountpoint),
 	.sb_alloc_security =
@@ -1704,8 +1698,6 @@ struct security_hook_heads security_hook_heads = {
 		LIST_HEAD_INIT(security_hook_heads.sb_free_security),
 	.sb_copy_data =	LIST_HEAD_INIT(security_hook_heads.sb_copy_data),
 	.sb_remount =	LIST_HEAD_INIT(security_hook_heads.sb_remount),
-	.sb_kern_mount =
-		LIST_HEAD_INIT(security_hook_heads.sb_kern_mount),
 	.sb_show_options =
 		LIST_HEAD_INIT(security_hook_heads.sb_show_options),
 	.sb_statfs =	LIST_HEAD_INIT(security_hook_heads.sb_statfs),
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e1bf18af72f5..f5b019d408dc 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2775,25 +2775,6 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
 	goto out_free_opts;
 }
 
-static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
-{
-	const struct cred *cred = current_cred();
-	struct common_audit_data ad;
-	int rc;
-
-	rc = superblock_doinit(sb, data);
-	if (rc)
-		return rc;
-
-	/* Allow all mounts performed by the kernel */
-	if (flags & MS_KERNMOUNT)
-		return 0;
-
-	ad.type = LSM_AUDIT_DATA_DENTRY;
-	ad.u.dentry = sb->s_root;
-	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
-}
-
 static int selinux_sb_statfs(struct dentry *dentry)
 {
 	const struct cred *cred = current_cred();
@@ -2967,14 +2948,13 @@ static int selinux_sb_config_parse_option(struct sb_config *sc, char *opt)
 	return sb_cfg_inval(sc, "SELinux: Incompatible mount options");
 }
 
-static int selinux_sb_config_kern_mount(struct sb_config *sc,
-					struct super_block *sb)
+static int selinux_sb_create_super(struct sb_config *sc)
 {
 	const struct cred *cred = current_cred();
 	struct common_audit_data ad;
 	int rc;
 
-	rc = selinux_set_mnt_opts(sb, sc->security, 0, NULL);
+	rc = selinux_set_mnt_opts(sc->sb, sc->security, 0, NULL);
 	if (rc)
 		return rc;
 
@@ -2983,8 +2963,8 @@ static int selinux_sb_config_kern_mount(struct sb_config *sc,
 		return 0;
 
 	ad.type = LSM_AUDIT_DATA_DENTRY;
-	ad.u.dentry = sb->s_root;
-	rc = superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
+	ad.u.dentry = sc->root;
+	rc = superblock_has_perm(cred, sc->sb, FILESYSTEM__MOUNT, &ad);
 	if (rc < 0)
 		sb_cfg_error(sc, "SELinux: Mount of superblock not permitted");
 	return rc;
@@ -6311,14 +6291,13 @@ static struct security_hook_list selinux_hooks[] = {
 	LSM_HOOK_INIT(sb_config_dup, selinux_sb_config_dup),
 	LSM_HOOK_INIT(sb_config_free, selinux_sb_config_free),
 	LSM_HOOK_INIT(sb_config_parse_option, selinux_sb_config_parse_option),
-	LSM_HOOK_INIT(sb_config_kern_mount, selinux_sb_config_kern_mount),
+	LSM_HOOK_INIT(sb_create_super, selinux_sb_create_super),
 	LSM_HOOK_INIT(sb_config_mountpoint, selinux_sb_config_mountpoint),
 
 	LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
 	LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
 	LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
 	LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
-	LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
 	LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
 	LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
 	LSM_HOOK_INIT(sb_mount, selinux_mount),
