Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f291889 authored by Al Viro's avatar Al Viro
Browse files

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: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 9bc61ab1
Loading
Loading
Loading
Loading
+52 −24
Original line number Original line Diff line number Diff line
@@ -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);


+3 −0
Original line number Original line Diff line number Diff line
@@ -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);