aboutsummaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c166
1 files changed, 27 insertions, 139 deletions
diff --git a/fs/super.c b/fs/super.c
index 74e149efed81..8a06881b1920 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -71,6 +71,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
71#else 71#else
72 INIT_LIST_HEAD(&s->s_files); 72 INIT_LIST_HEAD(&s->s_files);
73#endif 73#endif
74 s->s_bdi = &default_backing_dev_info;
74 INIT_LIST_HEAD(&s->s_instances); 75 INIT_LIST_HEAD(&s->s_instances);
75 INIT_HLIST_BL_HEAD(&s->s_anon); 76 INIT_HLIST_BL_HEAD(&s->s_anon);
76 INIT_LIST_HEAD(&s->s_inodes); 77 INIT_LIST_HEAD(&s->s_inodes);
@@ -177,6 +178,11 @@ void deactivate_locked_super(struct super_block *s)
177 struct file_system_type *fs = s->s_type; 178 struct file_system_type *fs = s->s_type;
178 if (atomic_dec_and_test(&s->s_active)) { 179 if (atomic_dec_and_test(&s->s_active)) {
179 fs->kill_sb(s); 180 fs->kill_sb(s);
181 /*
182 * We need to call rcu_barrier so all the delayed rcu free
183 * inodes are flushed before we release the fs module.
184 */
185 rcu_barrier();
180 put_filesystem(fs); 186 put_filesystem(fs);
181 put_super(s); 187 put_super(s);
182 } else { 188 } else {
@@ -838,23 +844,6 @@ error:
838} 844}
839EXPORT_SYMBOL(mount_bdev); 845EXPORT_SYMBOL(mount_bdev);
840 846
841int get_sb_bdev(struct file_system_type *fs_type,
842 int flags, const char *dev_name, void *data,
843 int (*fill_super)(struct super_block *, void *, int),
844 struct vfsmount *mnt)
845{
846 struct dentry *root;
847
848 root = mount_bdev(fs_type, flags, dev_name, data, fill_super);
849 if (IS_ERR(root))
850 return PTR_ERR(root);
851 mnt->mnt_root = root;
852 mnt->mnt_sb = root->d_sb;
853 return 0;
854}
855
856EXPORT_SYMBOL(get_sb_bdev);
857
858void kill_block_super(struct super_block *sb) 847void kill_block_super(struct super_block *sb)
859{ 848{
860 struct block_device *bdev = sb->s_bdev; 849 struct block_device *bdev = sb->s_bdev;
@@ -892,22 +881,6 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
892} 881}
893EXPORT_SYMBOL(mount_nodev); 882EXPORT_SYMBOL(mount_nodev);
894 883
895int get_sb_nodev(struct file_system_type *fs_type,
896 int flags, void *data,
897 int (*fill_super)(struct super_block *, void *, int),
898 struct vfsmount *mnt)
899{
900 struct dentry *root;
901
902 root = mount_nodev(fs_type, flags, data, fill_super);
903 if (IS_ERR(root))
904 return PTR_ERR(root);
905 mnt->mnt_root = root;
906 mnt->mnt_sb = root->d_sb;
907 return 0;
908}
909EXPORT_SYMBOL(get_sb_nodev);
910
911static int compare_single(struct super_block *s, void *p) 884static int compare_single(struct super_block *s, void *p)
912{ 885{
913 return 1; 886 return 1;
@@ -938,69 +911,36 @@ struct dentry *mount_single(struct file_system_type *fs_type,
938} 911}
939EXPORT_SYMBOL(mount_single); 912EXPORT_SYMBOL(mount_single);
940 913
941int get_sb_single(struct file_system_type *fs_type, 914struct dentry *
942 int flags, void *data, 915mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
943 int (*fill_super)(struct super_block *, void *, int),
944 struct vfsmount *mnt)
945{
946 struct dentry *root;
947 root = mount_single(fs_type, flags, data, fill_super);
948 if (IS_ERR(root))
949 return PTR_ERR(root);
950 mnt->mnt_root = root;
951 mnt->mnt_sb = root->d_sb;
952 return 0;
953}
954
955EXPORT_SYMBOL(get_sb_single);
956
957struct vfsmount *
958vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
959{ 916{
960 struct vfsmount *mnt;
961 struct dentry *root; 917 struct dentry *root;
918 struct super_block *sb;
962 char *secdata = NULL; 919 char *secdata = NULL;
963 int error; 920 int error = -ENOMEM;
964
965 if (!type)
966 return ERR_PTR(-ENODEV);
967
968 error = -ENOMEM;
969 mnt = alloc_vfsmnt(name);
970 if (!mnt)
971 goto out;
972
973 if (flags & MS_KERNMOUNT)
974 mnt->mnt_flags = MNT_INTERNAL;
975 921
976 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 922 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
977 secdata = alloc_secdata(); 923 secdata = alloc_secdata();
978 if (!secdata) 924 if (!secdata)
979 goto out_mnt; 925 goto out;
980 926
981 error = security_sb_copy_data(data, secdata); 927 error = security_sb_copy_data(data, secdata);
982 if (error) 928 if (error)
983 goto out_free_secdata; 929 goto out_free_secdata;
984 } 930 }
985 931
986 if (type->mount) { 932 root = type->mount(type, flags, name, data);
987 root = type->mount(type, flags, name, data); 933 if (IS_ERR(root)) {
988 if (IS_ERR(root)) { 934 error = PTR_ERR(root);
989 error = PTR_ERR(root); 935 goto out_free_secdata;
990 goto out_free_secdata;
991 }
992 mnt->mnt_root = root;
993 mnt->mnt_sb = root->d_sb;
994 } else {
995 error = type->get_sb(type, flags, name, data, mnt);
996 if (error < 0)
997 goto out_free_secdata;
998 } 936 }
999 BUG_ON(!mnt->mnt_sb); 937 sb = root->d_sb;
1000 WARN_ON(!mnt->mnt_sb->s_bdi); 938 BUG_ON(!sb);
1001 mnt->mnt_sb->s_flags |= MS_BORN; 939 WARN_ON(!sb->s_bdi);
940 WARN_ON(sb->s_bdi == &default_backing_dev_info);
941 sb->s_flags |= MS_BORN;
1002 942
1003 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); 943 error = security_sb_kern_mount(sb, flags, secdata);
1004 if (error) 944 if (error)
1005 goto out_sb; 945 goto out_sb;
1006 946
@@ -1011,27 +951,21 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
1011 * violate this rule. This warning should be either removed or 951 * violate this rule. This warning should be either removed or
1012 * converted to a BUG() in 2.6.34. 952 * converted to a BUG() in 2.6.34.
1013 */ 953 */
1014 WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " 954 WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
1015 "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); 955 "negative value (%lld)\n", type->name, sb->s_maxbytes);
1016 956
1017 mnt->mnt_mountpoint = mnt->mnt_root; 957 up_write(&sb->s_umount);
1018 mnt->mnt_parent = mnt;
1019 up_write(&mnt->mnt_sb->s_umount);
1020 free_secdata(secdata); 958 free_secdata(secdata);
1021 return mnt; 959 return root;
1022out_sb: 960out_sb:
1023 dput(mnt->mnt_root); 961 dput(root);
1024 deactivate_locked_super(mnt->mnt_sb); 962 deactivate_locked_super(sb);
1025out_free_secdata: 963out_free_secdata:
1026 free_secdata(secdata); 964 free_secdata(secdata);
1027out_mnt:
1028 free_vfsmnt(mnt);
1029out: 965out:
1030 return ERR_PTR(error); 966 return ERR_PTR(error);
1031} 967}
1032 968
1033EXPORT_SYMBOL_GPL(vfs_kern_mount);
1034
1035/** 969/**
1036 * freeze_super - lock the filesystem and force it into a consistent state 970 * freeze_super - lock the filesystem and force it into a consistent state
1037 * @sb: the super to lock 971 * @sb: the super to lock
@@ -1121,49 +1055,3 @@ out:
1121 return 0; 1055 return 0;
1122} 1056}
1123EXPORT_SYMBOL(thaw_super); 1057EXPORT_SYMBOL(thaw_super);
1124
1125static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
1126{
1127 int err;
1128 const char *subtype = strchr(fstype, '.');
1129 if (subtype) {
1130 subtype++;
1131 err = -EINVAL;
1132 if (!subtype[0])
1133 goto err;
1134 } else
1135 subtype = "";
1136
1137 mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
1138 err = -ENOMEM;
1139 if (!mnt->mnt_sb->s_subtype)
1140 goto err;
1141 return mnt;
1142
1143 err:
1144 mntput(mnt);
1145 return ERR_PTR(err);
1146}
1147
1148struct vfsmount *
1149do_kern_mount(const char *fstype, int flags, const char *name, void *data)
1150{
1151 struct file_system_type *type = get_fs_type(fstype);
1152 struct vfsmount *mnt;
1153 if (!type)
1154 return ERR_PTR(-ENODEV);
1155 mnt = vfs_kern_mount(type, flags, name, data);
1156 if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
1157 !mnt->mnt_sb->s_subtype)
1158 mnt = fs_set_subtype(mnt, fstype);
1159 put_filesystem(type);
1160 return mnt;
1161}
1162EXPORT_SYMBOL_GPL(do_kern_mount);
1163
1164struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
1165{
1166 return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
1167}
1168
1169EXPORT_SYMBOL_GPL(kern_mount_data);