diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 166 |
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 | } |
839 | EXPORT_SYMBOL(mount_bdev); | 845 | EXPORT_SYMBOL(mount_bdev); |
840 | 846 | ||
841 | int 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 | |||
856 | EXPORT_SYMBOL(get_sb_bdev); | ||
857 | |||
858 | void kill_block_super(struct super_block *sb) | 847 | void 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 | } |
893 | EXPORT_SYMBOL(mount_nodev); | 882 | EXPORT_SYMBOL(mount_nodev); |
894 | 883 | ||
895 | int 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 | } | ||
909 | EXPORT_SYMBOL(get_sb_nodev); | ||
910 | |||
911 | static int compare_single(struct super_block *s, void *p) | 884 | static 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 | } |
939 | EXPORT_SYMBOL(mount_single); | 912 | EXPORT_SYMBOL(mount_single); |
940 | 913 | ||
941 | int get_sb_single(struct file_system_type *fs_type, | 914 | struct dentry * |
942 | int flags, void *data, | 915 | mount_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 | |||
955 | EXPORT_SYMBOL(get_sb_single); | ||
956 | |||
957 | struct vfsmount * | ||
958 | vfs_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; |
1022 | out_sb: | 960 | out_sb: |
1023 | dput(mnt->mnt_root); | 961 | dput(root); |
1024 | deactivate_locked_super(mnt->mnt_sb); | 962 | deactivate_locked_super(sb); |
1025 | out_free_secdata: | 963 | out_free_secdata: |
1026 | free_secdata(secdata); | 964 | free_secdata(secdata); |
1027 | out_mnt: | ||
1028 | free_vfsmnt(mnt); | ||
1029 | out: | 965 | out: |
1030 | return ERR_PTR(error); | 966 | return ERR_PTR(error); |
1031 | } | 967 | } |
1032 | 968 | ||
1033 | EXPORT_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 | } |
1123 | EXPORT_SYMBOL(thaw_super); | 1057 | EXPORT_SYMBOL(thaw_super); |
1124 | |||
1125 | static 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 | |||
1148 | struct vfsmount * | ||
1149 | do_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 | } | ||
1162 | EXPORT_SYMBOL_GPL(do_kern_mount); | ||
1163 | |||
1164 | struct 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 | |||
1169 | EXPORT_SYMBOL_GPL(kern_mount_data); | ||