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 f3d15de44b15..17191546d527 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -12,6 +12,7 @@
12#include <linux/lglock.h> 12#include <linux/lglock.h>
13 13
14struct super_block; 14struct super_block;
15struct file_system_type;
15struct linux_binprm; 16struct linux_binprm;
16struct path; 17struct path;
17 18
@@ -61,8 +62,6 @@ extern int check_unsafe_exec(struct linux_binprm *);
61extern int copy_mount_options(const void __user *, unsigned long *); 62extern int copy_mount_options(const void __user *, unsigned long *);
62extern int copy_mount_string(const void __user *, char **); 63extern int copy_mount_string(const void __user *, char **);
63 64
64extern void free_vfsmnt(struct vfsmount *);
65extern struct vfsmount *alloc_vfsmnt(const char *);
66extern unsigned int mnt_get_count(struct vfsmount *mnt); 65extern unsigned int mnt_get_count(struct vfsmount *mnt);
67extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); 66extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
68extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, 67extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
@@ -99,6 +98,8 @@ extern struct file *get_empty_filp(void);
99extern int do_remount_sb(struct super_block *, int, void *, int); 98extern int do_remount_sb(struct super_block *, int, void *, int);
100extern void __put_super(struct super_block *sb); 99extern void __put_super(struct super_block *sb);
101extern void put_super(struct super_block *sb); 100extern void put_super(struct super_block *sb);
101extern struct dentry *mount_fs(struct file_system_type *,
102 int, const char *, void *);
102 103
103/* 104/*
104 * open.c 105 * open.c
diff --git a/fs/namespace.c b/fs/namespace.c
index a2a01a104ab0..453529f72dff 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -196,7 +196,7 @@ unsigned int mnt_get_count(struct vfsmount *mnt)
196#endif 196#endif
197} 197}
198 198
199struct vfsmount *alloc_vfsmnt(const char *name) 199static struct vfsmount *alloc_vfsmnt(const char *name)
200{ 200{
201 struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); 201 struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
202 if (mnt) { 202 if (mnt) {
@@ -466,7 +466,7 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt)
466 br_write_unlock(vfsmount_lock); 466 br_write_unlock(vfsmount_lock);
467} 467}
468 468
469void free_vfsmnt(struct vfsmount *mnt) 469static void free_vfsmnt(struct vfsmount *mnt)
470{ 470{
471 kfree(mnt->mnt_devname); 471 kfree(mnt->mnt_devname);
472 mnt_free_id(mnt); 472 mnt_free_id(mnt);
@@ -670,6 +670,36 @@ static struct vfsmount *skip_mnt_tree(struct vfsmount *p)
670 return p; 670 return p;
671} 671}
672 672
673struct vfsmount *
674vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
675{
676 struct vfsmount *mnt;
677 struct dentry *root;
678
679 if (!type)
680 return ERR_PTR(-ENODEV);
681
682 mnt = alloc_vfsmnt(name);
683 if (!mnt)
684 return ERR_PTR(-ENOMEM);
685
686 if (flags & MS_KERNMOUNT)
687 mnt->mnt_flags = MNT_INTERNAL;
688
689 root = mount_fs(type, flags, name, data);
690 if (IS_ERR(root)) {
691 free_vfsmnt(mnt);
692 return ERR_CAST(root);
693 }
694
695 mnt->mnt_root = root;
696 mnt->mnt_sb = root->d_sb;
697 mnt->mnt_mountpoint = mnt->mnt_root;
698 mnt->mnt_parent = mnt;
699 return mnt;
700}
701EXPORT_SYMBOL_GPL(vfs_kern_mount);
702
673static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, 703static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
674 int flag) 704 int flag)
675{ 705{
@@ -1905,7 +1935,81 @@ out:
1905 return err; 1935 return err;
1906} 1936}
1907 1937
1908static int do_add_mount(struct vfsmount *, struct path *, int); 1938static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
1939{
1940 int err;
1941 const char *subtype = strchr(fstype, '.');
1942 if (subtype) {
1943 subtype++;
1944 err = -EINVAL;
1945 if (!subtype[0])
1946 goto err;
1947 } else
1948 subtype = "";
1949
1950 mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
1951 err = -ENOMEM;
1952 if (!mnt->mnt_sb->s_subtype)
1953 goto err;
1954 return mnt;
1955
1956 err:
1957 mntput(mnt);
1958 return ERR_PTR(err);
1959}
1960
1961struct vfsmount *
1962do_kern_mount(const char *fstype, int flags, const char *name, void *data)
1963{
1964 struct file_system_type *type = get_fs_type(fstype);
1965 struct vfsmount *mnt;
1966 if (!type)
1967 return ERR_PTR(-ENODEV);
1968 mnt = vfs_kern_mount(type, flags, name, data);
1969 if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
1970 !mnt->mnt_sb->s_subtype)
1971 mnt = fs_set_subtype(mnt, fstype);
1972 put_filesystem(type);
1973 return mnt;
1974}
1975EXPORT_SYMBOL_GPL(do_kern_mount);
1976
1977/*
1978 * add a mount into a namespace's mount tree
1979 */
1980static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
1981{
1982 int err;
1983
1984 mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
1985
1986 down_write(&namespace_sem);
1987 /* Something was mounted here while we slept */
1988 err = follow_down(path, true);
1989 if (err < 0)
1990 goto unlock;
1991
1992 err = -EINVAL;
1993 if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
1994 goto unlock;
1995
1996 /* Refuse the same filesystem on the same mount point */
1997 err = -EBUSY;
1998 if (path->mnt->mnt_sb == newmnt->mnt_sb &&
1999 path->mnt->mnt_root == path->dentry)
2000 goto unlock;
2001
2002 err = -EINVAL;
2003 if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
2004 goto unlock;
2005
2006 newmnt->mnt_flags = mnt_flags;
2007 err = graft_tree(newmnt, path);
2008
2009unlock:
2010 up_write(&namespace_sem);
2011 return err;
2012}
1909 2013
1910/* 2014/*
1911 * create a new mount for userspace and request it to be added into the 2015 * create a new mount for userspace and request it to be added into the
@@ -1965,43 +2069,6 @@ fail:
1965 return err; 2069 return err;
1966} 2070}
1967 2071
1968/*
1969 * add a mount into a namespace's mount tree
1970 */
1971static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
1972{
1973 int err;
1974
1975 mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
1976
1977 down_write(&namespace_sem);
1978 /* Something was mounted here while we slept */
1979 err = follow_down(path, true);
1980 if (err < 0)
1981 goto unlock;
1982
1983 err = -EINVAL;
1984 if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
1985 goto unlock;
1986
1987 /* Refuse the same filesystem on the same mount point */
1988 err = -EBUSY;
1989 if (path->mnt->mnt_sb == newmnt->mnt_sb &&
1990 path->mnt->mnt_root == path->dentry)
1991 goto unlock;
1992
1993 err = -EINVAL;
1994 if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
1995 goto unlock;
1996
1997 newmnt->mnt_flags = mnt_flags;
1998 err = graft_tree(newmnt, path);
1999
2000unlock:
2001 up_write(&namespace_sem);
2002 return err;
2003}
2004
2005/** 2072/**
2006 * mnt_set_expiry - Put a mount on an expiration list 2073 * mnt_set_expiry - Put a mount on an expiration list
2007 * @mnt: The mount to list. 2074 * @mnt: The mount to list.
@@ -2660,3 +2727,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
2660 kfree(ns); 2727 kfree(ns);
2661} 2728}
2662EXPORT_SYMBOL(put_mnt_ns); 2729EXPORT_SYMBOL(put_mnt_ns);
2730
2731struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
2732{
2733 return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
2734}
2735EXPORT_SYMBOL_GPL(kern_mount_data);
diff --git a/fs/super.c b/fs/super.c
index 4bae0ef6110e..e84864908264 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -910,29 +910,18 @@ struct dentry *mount_single(struct file_system_type *fs_type,
910} 910}
911EXPORT_SYMBOL(mount_single); 911EXPORT_SYMBOL(mount_single);
912 912
913struct vfsmount * 913struct dentry *
914vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) 914mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
915{ 915{
916 struct vfsmount *mnt;
917 struct dentry *root; 916 struct dentry *root;
917 struct super_block *sb;
918 char *secdata = NULL; 918 char *secdata = NULL;
919 int error; 919 int error = -ENOMEM;
920
921 if (!type)
922 return ERR_PTR(-ENODEV);
923
924 error = -ENOMEM;
925 mnt = alloc_vfsmnt(name);
926 if (!mnt)
927 goto out;
928
929 if (flags & MS_KERNMOUNT)
930 mnt->mnt_flags = MNT_INTERNAL;
931 920
932 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 921 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
933 secdata = alloc_secdata(); 922 secdata = alloc_secdata();
934 if (!secdata) 923 if (!secdata)
935 goto out_mnt; 924 goto out;
936 925
937 error = security_sb_copy_data(data, secdata); 926 error = security_sb_copy_data(data, secdata);
938 if (error) 927 if (error)
@@ -944,13 +933,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
944 error = PTR_ERR(root); 933 error = PTR_ERR(root);
945 goto out_free_secdata; 934 goto out_free_secdata;
946 } 935 }
947 mnt->mnt_root = root; 936 sb = root->d_sb;
948 mnt->mnt_sb = root->d_sb; 937 BUG_ON(!sb);
949 BUG_ON(!mnt->mnt_sb); 938 WARN_ON(!sb->s_bdi);
950 WARN_ON(!mnt->mnt_sb->s_bdi); 939 sb->s_flags |= MS_BORN;
951 mnt->mnt_sb->s_flags |= MS_BORN;
952 940
953 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); 941 error = security_sb_kern_mount(sb, flags, secdata);
954 if (error) 942 if (error)
955 goto out_sb; 943 goto out_sb;
956 944
@@ -961,27 +949,21 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
961 * violate this rule. This warning should be either removed or 949 * violate this rule. This warning should be either removed or
962 * converted to a BUG() in 2.6.34. 950 * converted to a BUG() in 2.6.34.
963 */ 951 */
964 WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " 952 WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
965 "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); 953 "negative value (%lld)\n", type->name, sb->s_maxbytes);
966 954
967 mnt->mnt_mountpoint = mnt->mnt_root; 955 up_write(&sb->s_umount);
968 mnt->mnt_parent = mnt;
969 up_write(&mnt->mnt_sb->s_umount);
970 free_secdata(secdata); 956 free_secdata(secdata);
971 return mnt; 957 return root;
972out_sb: 958out_sb:
973 dput(mnt->mnt_root); 959 dput(root);
974 deactivate_locked_super(mnt->mnt_sb); 960 deactivate_locked_super(sb);
975out_free_secdata: 961out_free_secdata:
976 free_secdata(secdata); 962 free_secdata(secdata);
977out_mnt:
978 free_vfsmnt(mnt);
979out: 963out:
980 return ERR_PTR(error); 964 return ERR_PTR(error);
981} 965}
982 966
983EXPORT_SYMBOL_GPL(vfs_kern_mount);
984
985/** 967/**
986 * freeze_super - lock the filesystem and force it into a consistent state 968 * freeze_super - lock the filesystem and force it into a consistent state
987 * @sb: the super to lock 969 * @sb: the super to lock
@@ -1071,49 +1053,3 @@ out:
1071 return 0; 1053 return 0;
1072} 1054}
1073EXPORT_SYMBOL(thaw_super); 1055EXPORT_SYMBOL(thaw_super);
1074
1075static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
1076{
1077 int err;
1078 const char *subtype = strchr(fstype, '.');
1079 if (subtype) {
1080 subtype++;
1081 err = -EINVAL;
1082 if (!subtype[0])
1083 goto err;
1084 } else
1085 subtype = "";
1086
1087 mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
1088 err = -ENOMEM;
1089 if (!mnt->mnt_sb->s_subtype)
1090 goto err;
1091 return mnt;
1092
1093 err:
1094 mntput(mnt);
1095 return ERR_PTR(err);
1096}
1097
1098struct vfsmount *
1099do_kern_mount(const char *fstype, int flags, const char *name, void *data)
1100{
1101 struct file_system_type *type = get_fs_type(fstype);
1102 struct vfsmount *mnt;
1103 if (!type)
1104 return ERR_PTR(-ENODEV);
1105 mnt = vfs_kern_mount(type, flags, name, data);
1106 if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
1107 !mnt->mnt_sb->s_subtype)
1108 mnt = fs_set_subtype(mnt, fstype);
1109 put_filesystem(type);
1110 return mnt;
1111}
1112EXPORT_SYMBOL_GPL(do_kern_mount);
1113
1114struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
1115{
1116 return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
1117}
1118
1119EXPORT_SYMBOL_GPL(kern_mount_data);