mirror of https://gitee.com/openkylin/linux.git
teach vfs_get_tree() to handle subtype, switch do_new_mount() to it
Roll the handling of subtypes into do_new_mount() and vfs_get_tree(). The former determines any subtype string and hangs it off the fs_context; the latter applies it. Make do_new_mount() create, parameterise and commit an fs_context and create a mount for itself rather than calling vfs_kern_mount(). [AV -- missing kstrdup()] [AV -- ... and no kstrdup() if we get to setting ->s_submount - we simply transfer it from fc, leaving NULL behind] [AV -- constify ->s_submount, while we are at it] Reviewed-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
8f2918898e
commit
a0c9a8b8fd
|
@ -2479,29 +2479,6 @@ static int do_move_mount(struct path *path, const char *old_name)
|
||||||
return err;
|
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
|
* add a mount into a namespace's mount tree
|
||||||
*/
|
*/
|
||||||
|
@ -2557,7 +2534,9 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
|
||||||
{
|
{
|
||||||
struct file_system_type *type;
|
struct file_system_type *type;
|
||||||
struct vfsmount *mnt;
|
struct vfsmount *mnt;
|
||||||
int err;
|
struct fs_context *fc;
|
||||||
|
const char *subtype = NULL;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
if (!fstype)
|
if (!fstype)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2566,23 +2545,59 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
|
||||||
if (!type)
|
if (!type)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mnt = vfs_kern_mount(type, sb_flags, name, data);
|
if (type->fs_flags & FS_HAS_SUBTYPE) {
|
||||||
if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
|
subtype = strchr(fstype, '.');
|
||||||
!mnt->mnt_sb->s_subtype)
|
if (subtype) {
|
||||||
mnt = fs_set_subtype(mnt, fstype);
|
subtype++;
|
||||||
|
if (!*subtype) {
|
||||||
|
put_filesystem(type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
subtype = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fc = fs_context_for_mount(type, sb_flags);
|
||||||
put_filesystem(type);
|
put_filesystem(type);
|
||||||
if (IS_ERR(mnt))
|
if (IS_ERR(fc))
|
||||||
return PTR_ERR(mnt);
|
return PTR_ERR(fc);
|
||||||
|
|
||||||
|
if (subtype) {
|
||||||
|
fc->subtype = kstrdup(subtype, GFP_KERNEL);
|
||||||
|
if (!fc->subtype)
|
||||||
|
err = -ENOMEM;
|
||||||
|
}
|
||||||
|
if (!err && name) {
|
||||||
|
fc->source = kstrdup(name, GFP_KERNEL);
|
||||||
|
if (!fc->source)
|
||||||
|
err = -ENOMEM;
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
err = parse_monolithic_mount_data(fc, data);
|
||||||
|
if (!err)
|
||||||
|
err = vfs_get_tree(fc);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
up_write(&fc->root->d_sb->s_umount);
|
||||||
|
mnt = vfs_create_mount(fc);
|
||||||
|
if (IS_ERR(mnt)) {
|
||||||
|
err = PTR_ERR(mnt);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (mount_too_revealing(mnt, &mnt_flags)) {
|
if (mount_too_revealing(mnt, &mnt_flags)) {
|
||||||
mntput(mnt);
|
mntput(mnt);
|
||||||
return -EPERM;
|
err = -EPERM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = do_add_mount(real_mount(mnt), path, mnt_flags);
|
err = do_add_mount(real_mount(mnt), path, mnt_flags);
|
||||||
if (err)
|
if (err)
|
||||||
mntput(mnt);
|
mntput(mnt);
|
||||||
|
out:
|
||||||
|
put_fs_context(fc);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1262,6 +1262,11 @@ int vfs_get_tree(struct fs_context *fc)
|
||||||
sb = fc->root->d_sb;
|
sb = fc->root->d_sb;
|
||||||
WARN_ON(!sb->s_bdi);
|
WARN_ON(!sb->s_bdi);
|
||||||
|
|
||||||
|
if (fc->subtype && !sb->s_subtype) {
|
||||||
|
sb->s_subtype = fc->subtype;
|
||||||
|
fc->subtype = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write barrier is for super_cache_count(). We place it before setting
|
* Write barrier is for super_cache_count(). We place it before setting
|
||||||
* SB_BORN as the data dependency between the two functions is the
|
* SB_BORN as the data dependency between the two functions is the
|
||||||
|
|
|
@ -1447,7 +1447,7 @@ struct super_block {
|
||||||
* Filesystem subtype. If non-empty the filesystem type field
|
* Filesystem subtype. If non-empty the filesystem type field
|
||||||
* in /proc/mounts will be "type.subtype"
|
* in /proc/mounts will be "type.subtype"
|
||||||
*/
|
*/
|
||||||
char *s_subtype;
|
const char *s_subtype;
|
||||||
|
|
||||||
const struct dentry_operations *s_d_op; /* default d_op for dentries */
|
const struct dentry_operations *s_d_op; /* default d_op for dentries */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue