new helpers: vfs_create_mount(), fc_mount()
Create a new helper, vfs_create_mount(), that creates a detached vfsmount object from an fs_context that has a superblock attached to it. Almost all uses will be paired with immediately preceding vfs_get_tree(); add a helper for such combination. Switch vfs_kern_mount() to use this. NOTE: mild behaviour change; passing NULL as 'device name' to something like procfs will change /proc/*/mountstats - "device none" instead on "no device". That is consistent with /proc/mounts et.al. [do'h - EXPORT_SYMBOL_GPL slipped in by mistake; removed] [AV -- remove confused comment from vfs_create_mount()] [AV -- removed the second argument] Reviewed-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
9bc61ab18b
commit
8f2918898e
|
@ -941,12 +941,59 @@ static struct mount *skip_mnt_tree(struct mount *p)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vfs_create_mount - Create a mount for a configured superblock
|
||||||
|
* @fc: The configuration context with the superblock attached
|
||||||
|
*
|
||||||
|
* Create a mount to an already configured superblock. If necessary, the
|
||||||
|
* caller should invoke vfs_get_tree() before calling this.
|
||||||
|
*
|
||||||
|
* Note that this does not attach the mount to anything.
|
||||||
|
*/
|
||||||
|
struct vfsmount *vfs_create_mount(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
struct mount *mnt;
|
||||||
|
|
||||||
|
if (!fc->root)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
mnt = alloc_vfsmnt(fc->source ?: "none");
|
||||||
|
if (!mnt)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
if (fc->sb_flags & SB_KERNMOUNT)
|
||||||
|
mnt->mnt.mnt_flags = MNT_INTERNAL;
|
||||||
|
|
||||||
|
atomic_inc(&fc->root->d_sb->s_active);
|
||||||
|
mnt->mnt.mnt_sb = fc->root->d_sb;
|
||||||
|
mnt->mnt.mnt_root = dget(fc->root);
|
||||||
|
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||||
|
mnt->mnt_parent = mnt;
|
||||||
|
|
||||||
|
lock_mount_hash();
|
||||||
|
list_add_tail(&mnt->mnt_instance, &mnt->mnt.mnt_sb->s_mounts);
|
||||||
|
unlock_mount_hash();
|
||||||
|
return &mnt->mnt;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(vfs_create_mount);
|
||||||
|
|
||||||
|
struct vfsmount *fc_mount(struct fs_context *fc)
|
||||||
|
{
|
||||||
|
int err = vfs_get_tree(fc);
|
||||||
|
if (!err) {
|
||||||
|
up_write(&fc->root->d_sb->s_umount);
|
||||||
|
return vfs_create_mount(fc);
|
||||||
|
}
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(fc_mount);
|
||||||
|
|
||||||
struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
||||||
int flags, const char *name,
|
int flags, const char *name,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct fs_context *fc;
|
struct fs_context *fc;
|
||||||
struct mount *mnt;
|
struct vfsmount *mnt;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
|
@ -964,31 +1011,12 @@ struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = parse_monolithic_mount_data(fc, data);
|
ret = parse_monolithic_mount_data(fc, data);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = vfs_get_tree(fc);
|
mnt = fc_mount(fc);
|
||||||
if (ret) {
|
else
|
||||||
put_fs_context(fc);
|
mnt = ERR_PTR(ret);
|
||||||
return ERR_PTR(ret);
|
|
||||||
}
|
|
||||||
up_write(&fc->root->d_sb->s_umount);
|
|
||||||
mnt = alloc_vfsmnt(name);
|
|
||||||
if (!mnt) {
|
|
||||||
put_fs_context(fc);
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SB_KERNMOUNT)
|
|
||||||
mnt->mnt.mnt_flags = MNT_INTERNAL;
|
|
||||||
|
|
||||||
atomic_inc(&fc->root->d_sb->s_active);
|
|
||||||
mnt->mnt.mnt_root = dget(fc->root);
|
|
||||||
mnt->mnt.mnt_sb = fc->root->d_sb;
|
|
||||||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
|
||||||
mnt->mnt_parent = mnt;
|
|
||||||
lock_mount_hash();
|
|
||||||
list_add_tail(&mnt->mnt_instance, &fc->root->d_sb->s_mounts);
|
|
||||||
unlock_mount_hash();
|
|
||||||
put_fs_context(fc);
|
put_fs_context(fc);
|
||||||
return &mnt->mnt;
|
return mnt;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vfs_kern_mount);
|
EXPORT_SYMBOL_GPL(vfs_kern_mount);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct super_block;
|
||||||
struct vfsmount;
|
struct vfsmount;
|
||||||
struct dentry;
|
struct dentry;
|
||||||
struct mnt_namespace;
|
struct mnt_namespace;
|
||||||
|
struct fs_context;
|
||||||
|
|
||||||
#define MNT_NOSUID 0x01
|
#define MNT_NOSUID 0x01
|
||||||
#define MNT_NODEV 0x02
|
#define MNT_NODEV 0x02
|
||||||
|
@ -88,6 +89,8 @@ struct path;
|
||||||
extern struct vfsmount *clone_private_mount(const struct path *path);
|
extern struct vfsmount *clone_private_mount(const struct path *path);
|
||||||
|
|
||||||
struct file_system_type;
|
struct file_system_type;
|
||||||
|
extern struct vfsmount *fc_mount(struct fs_context *fc);
|
||||||
|
extern struct vfsmount *vfs_create_mount(struct fs_context *fc);
|
||||||
extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
||||||
int flags, const char *name,
|
int flags, const char *name,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
Loading…
Reference in New Issue