aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/internal.h5
-rw-r--r--fs/namespace.c153
-rw-r--r--fs/super.c96
3 files changed, 132 insertions, 122 deletions
diff --git a/fs/internal.h b/fs/internal.h
index f3d15de..1719154 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -12,6 +12,7 @@
#include <linux/lglock.h>
struct super_block;
+struct file_system_type;
struct linux_binprm;
struct path;
@@ -61,8 +62,6 @@ extern int check_unsafe_exec(struct linux_binprm *);
extern int copy_mount_options(const void __user *, unsigned long *);
extern int copy_mount_string(const void __user *, char **);
-extern void free_vfsmnt(struct vfsmount *);
-extern struct vfsmount *alloc_vfsmnt(const char *);
extern unsigned int mnt_get_count(struct vfsmount *mnt);
extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
@@ -99,6 +98,8 @@ extern struct file *get_empty_filp(void);
extern int do_remount_sb(struct super_block *, int, void *, int);
extern void __put_super(struct super_block *sb);
extern void put_super(struct super_block *sb);
+extern struct dentry *mount_fs(struct file_system_type *,
+ int, const char *, void *);
/*
* open.c
diff --git a/fs/namespace.c b/fs/namespace.c
index a2a01a1..453529f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -196,7 +196,7 @@ unsigned int mnt_get_count(struct vfsmount *mnt)
#endif
}
-struct vfsmount *alloc_vfsmnt(const char *name)
+static struct vfsmount *alloc_vfsmnt(const char *name)
{
struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
if (mnt) {
@@ -466,7 +466,7 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt)
br_write_unlock(vfsmount_lock);
}
-void free_vfsmnt(struct vfsmount *mnt)
+static void free_vfsmnt(struct vfsmount *mnt)
{
kfree(mnt->mnt_devname);
mnt_free_id(mnt);
@@ -670,6 +670,36 @@ static struct vfsmount *skip_mnt_tree(struct vfsmount *p)
return p;
}
+struct vfsmount *
+vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
+{
+ struct vfsmount *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_flags = MNT_INTERNAL;
+
+ root = mount_fs(type, flags, name, data);
+ if (IS_ERR(root)) {
+ free_vfsmnt(mnt);
+ return ERR_CAST(root);
+ }
+
+ mnt->mnt_root = root;
+ mnt->mnt_sb = root->d_sb;
+ mnt->mnt_mountpoint = mnt->mnt_root;
+ mnt->mnt_parent = mnt;
+ return mnt;
+}
+EXPORT_SYMBOL_GPL(vfs_kern_mount);
+
static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
int flag)
{
@@ -1905,7 +1935,81 @@ out:
return err;
}
-static int do_add_mount(struct vfsmount *, struct path *, int);
+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);
+}
+
+struct vfsmount *
+do_kern_mount(const char *fstype, int flags, const char *name, void *data)
+{
+ struct file_system_type *type = get_fs_type(fstype);
+ struct vfsmount *mnt;
+ if (!type)
+ return ERR_PTR(-ENODEV);
+ mnt = vfs_kern_mount(type, flags, name, data);
+ if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
+ !mnt->mnt_sb->s_subtype)
+ mnt = fs_set_subtype(mnt, fstype);
+ put_filesystem(type);
+ return mnt;
+}
+EXPORT_SYMBOL_GPL(do_kern_mount);
+
+/*
+ * add a mount into a namespace's mount tree
+ */
+static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
+{
+ int err;
+
+ mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
+
+ down_write(&namespace_sem);
+ /* Something was mounted here while we slept */
+ err = follow_down(path, true);
+ if (err < 0)
+ goto unlock;
+
+ err = -EINVAL;
+ if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
+ goto unlock;
+
+ /* Refuse the same filesystem on the same mount point */
+ err = -EBUSY;
+ if (path->mnt->mnt_sb == newmnt->mnt_sb &&
+ path->mnt->mnt_root == path->dentry)
+ goto unlock;
+
+ err = -EINVAL;
+ if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
+ goto unlock;
+
+ newmnt->mnt_flags = mnt_flags;
+ err = graft_tree(newmnt, path);
+
+unlock:
+ up_write(&namespace_sem);
+ return err;
+}
/*
* create a new mount for userspace and request it to be added into the
@@ -1965,43 +2069,6 @@ fail:
return err;
}
-/*
- * add a mount into a namespace's mount tree
- */
-static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
-{
- int err;
-
- mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
-
- down_write(&namespace_sem);
- /* Something was mounted here while we slept */
- err = follow_down(path, true);
- if (err < 0)
- goto unlock;
-
- err = -EINVAL;
- if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
- goto unlock;
-
- /* Refuse the same filesystem on the same mount point */
- err = -EBUSY;
- if (path->mnt->mnt_sb == newmnt->mnt_sb &&
- path->mnt->mnt_root == path->dentry)
- goto unlock;
-
- err = -EINVAL;
- if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
- goto unlock;
-
- newmnt->mnt_flags = mnt_flags;
- err = graft_tree(newmnt, path);
-
-unlock:
- up_write(&namespace_sem);
- return err;
-}
-
/**
* mnt_set_expiry - Put a mount on an expiration list
* @mnt: The mount to list.
@@ -2660,3 +2727,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
kfree(ns);
}
EXPORT_SYMBOL(put_mnt_ns);
+
+struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
+{
+ return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+}
+EXPORT_SYMBOL_GPL(kern_mount_data);
diff --git a/fs/super.c b/fs/super.c
index 4bae0ef..e848649 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -910,29 +910,18 @@ struct dentry *mount_single(struct file_system_type *fs_type,
}
EXPORT_SYMBOL(mount_single);
-struct vfsmount *
-vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
+struct dentry *
+mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
- struct vfsmount *mnt;
struct dentry *root;
+ struct super_block *sb;
char *secdata = NULL;
- int error;
-
- if (!type)
- return ERR_PTR(-ENODEV);
-
- error = -ENOMEM;
- mnt = alloc_vfsmnt(name);
- if (!mnt)
- goto out;
-
- if (flags & MS_KERNMOUNT)
- mnt->mnt_flags = MNT_INTERNAL;
+ int error = -ENOMEM;
if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
secdata = alloc_secdata();
if (!secdata)
- goto out_mnt;
+ goto out;
error = security_sb_copy_data(data, secdata);
if (error)
@@ -944,13 +933,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
error = PTR_ERR(root);
goto out_free_secdata;
}
- mnt->mnt_root = root;
- mnt->mnt_sb = root->d_sb;
- BUG_ON(!mnt->mnt_sb);
- WARN_ON(!mnt->mnt_sb->s_bdi);
- mnt->mnt_sb->s_flags |= MS_BORN;
+ sb = root->d_sb;
+ BUG_ON(!sb);
+ WARN_ON(!sb->s_bdi);
+ sb->s_flags |= MS_BORN;
- error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
+ error = security_sb_kern_mount(sb, flags, secdata);
if (error)
goto out_sb;
@@ -961,27 +949,21 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
* violate this rule. This warning should be either removed or
* converted to a BUG() in 2.6.34.
*/
- WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
- "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes);
+ WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
+ "negative value (%lld)\n", type->name, sb->s_maxbytes);
- mnt->mnt_mountpoint = mnt->mnt_root;
- mnt->mnt_parent = mnt;
- up_write(&mnt->mnt_sb->s_umount);
+ up_write(&sb->s_umount);
free_secdata(secdata);
- return mnt;
+ return root;
out_sb:
- dput(mnt->mnt_root);
- deactivate_locked_super(mnt->mnt_sb);
+ dput(root);
+ deactivate_locked_super(sb);
out_free_secdata:
free_secdata(secdata);
-out_mnt:
- free_vfsmnt(mnt);
out:
return ERR_PTR(error);
}
-EXPORT_SYMBOL_GPL(vfs_kern_mount);
-
/**
* freeze_super - lock the filesystem and force it into a consistent state
* @sb: the super to lock
@@ -1071,49 +1053,3 @@ out:
return 0;
}
EXPORT_SYMBOL(thaw_super);
-
-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);
-}
-
-struct vfsmount *
-do_kern_mount(const char *fstype, int flags, const char *name, void *data)
-{
- struct file_system_type *type = get_fs_type(fstype);
- struct vfsmount *mnt;
- if (!type)
- return ERR_PTR(-ENODEV);
- mnt = vfs_kern_mount(type, flags, name, data);
- if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
- !mnt->mnt_sb->s_subtype)
- mnt = fs_set_subtype(mnt, fstype);
- put_filesystem(type);
- return mnt;
-}
-EXPORT_SYMBOL_GPL(do_kern_mount);
-
-struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
-{
- return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
-}
-
-EXPORT_SYMBOL_GPL(kern_mount_data);