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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
int flags, const char *name,
|
||||
void *data)
|
||||
{
|
||||
struct fs_context *fc;
|
||||
struct mount *mnt;
|
||||
struct vfsmount *mnt;
|
||||
int ret = 0;
|
||||
|
||||
if (!type)
|
||||
|
@ -964,31 +1011,12 @@ struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
|||
if (!ret)
|
||||
ret = parse_monolithic_mount_data(fc, data);
|
||||
if (!ret)
|
||||
ret = vfs_get_tree(fc);
|
||||
if (ret) {
|
||||
put_fs_context(fc);
|
||||
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);
|
||||
}
|
||||
mnt = fc_mount(fc);
|
||||
else
|
||||
mnt = ERR_PTR(ret);
|
||||
|
||||
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);
|
||||
return &mnt->mnt;
|
||||
return mnt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_kern_mount);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ struct super_block;
|
|||
struct vfsmount;
|
||||
struct dentry;
|
||||
struct mnt_namespace;
|
||||
struct fs_context;
|
||||
|
||||
#define MNT_NOSUID 0x01
|
||||
#define MNT_NODEV 0x02
|
||||
|
@ -88,6 +89,8 @@ struct path;
|
|||
extern struct vfsmount *clone_private_mount(const struct path *path);
|
||||
|
||||
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,
|
||||
int flags, const char *name,
|
||||
void *data);
|
||||
|
|
Loading…
Reference in New Issue