diff options
-rw-r--r-- | fs/filesystems.c | 21 | ||||
-rw-r--r-- | fs/fuse/inode.c | 2 | ||||
-rw-r--r-- | fs/namespace.c | 4 | ||||
-rw-r--r-- | fs/super.c | 27 | ||||
-rw-r--r-- | include/linux/fs.h | 7 |
5 files changed, 55 insertions, 6 deletions
diff --git a/fs/filesystems.c b/fs/filesystems.c index 7a4f61aa05f8..f37f87262837 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
@@ -41,11 +41,12 @@ void put_filesystem(struct file_system_type *fs) | |||
41 | module_put(fs->owner); | 41 | module_put(fs->owner); |
42 | } | 42 | } |
43 | 43 | ||
44 | static struct file_system_type **find_filesystem(const char *name) | 44 | static struct file_system_type **find_filesystem(const char *name, unsigned len) |
45 | { | 45 | { |
46 | struct file_system_type **p; | 46 | struct file_system_type **p; |
47 | for (p=&file_systems; *p; p=&(*p)->next) | 47 | for (p=&file_systems; *p; p=&(*p)->next) |
48 | if (strcmp((*p)->name,name) == 0) | 48 | if (strlen((*p)->name) == len && |
49 | strncmp((*p)->name, name, len) == 0) | ||
49 | break; | 50 | break; |
50 | return p; | 51 | return p; |
51 | } | 52 | } |
@@ -68,11 +69,12 @@ int register_filesystem(struct file_system_type * fs) | |||
68 | int res = 0; | 69 | int res = 0; |
69 | struct file_system_type ** p; | 70 | struct file_system_type ** p; |
70 | 71 | ||
72 | BUG_ON(strchr(fs->name, '.')); | ||
71 | if (fs->next) | 73 | if (fs->next) |
72 | return -EBUSY; | 74 | return -EBUSY; |
73 | INIT_LIST_HEAD(&fs->fs_supers); | 75 | INIT_LIST_HEAD(&fs->fs_supers); |
74 | write_lock(&file_systems_lock); | 76 | write_lock(&file_systems_lock); |
75 | p = find_filesystem(fs->name); | 77 | p = find_filesystem(fs->name, strlen(fs->name)); |
76 | if (*p) | 78 | if (*p) |
77 | res = -EBUSY; | 79 | res = -EBUSY; |
78 | else | 80 | else |
@@ -215,19 +217,26 @@ int get_filesystem_list(char * buf) | |||
215 | struct file_system_type *get_fs_type(const char *name) | 217 | struct file_system_type *get_fs_type(const char *name) |
216 | { | 218 | { |
217 | struct file_system_type *fs; | 219 | struct file_system_type *fs; |
220 | const char *dot = strchr(name, '.'); | ||
221 | unsigned len = dot ? dot - name : strlen(name); | ||
218 | 222 | ||
219 | read_lock(&file_systems_lock); | 223 | read_lock(&file_systems_lock); |
220 | fs = *(find_filesystem(name)); | 224 | fs = *(find_filesystem(name, len)); |
221 | if (fs && !try_module_get(fs->owner)) | 225 | if (fs && !try_module_get(fs->owner)) |
222 | fs = NULL; | 226 | fs = NULL; |
223 | read_unlock(&file_systems_lock); | 227 | read_unlock(&file_systems_lock); |
224 | if (!fs && (request_module("%s", name) == 0)) { | 228 | if (!fs && (request_module("%.*s", len, name) == 0)) { |
225 | read_lock(&file_systems_lock); | 229 | read_lock(&file_systems_lock); |
226 | fs = *(find_filesystem(name)); | 230 | fs = *(find_filesystem(name, len)); |
227 | if (fs && !try_module_get(fs->owner)) | 231 | if (fs && !try_module_get(fs->owner)) |
228 | fs = NULL; | 232 | fs = NULL; |
229 | read_unlock(&file_systems_lock); | 233 | read_unlock(&file_systems_lock); |
230 | } | 234 | } |
235 | |||
236 | if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { | ||
237 | put_filesystem(fs); | ||
238 | fs = NULL; | ||
239 | } | ||
231 | return fs; | 240 | return fs; |
232 | } | 241 | } |
233 | 242 | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d8003be56e05..1397018ff476 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -636,6 +636,7 @@ static int fuse_get_sb(struct file_system_type *fs_type, | |||
636 | static struct file_system_type fuse_fs_type = { | 636 | static struct file_system_type fuse_fs_type = { |
637 | .owner = THIS_MODULE, | 637 | .owner = THIS_MODULE, |
638 | .name = "fuse", | 638 | .name = "fuse", |
639 | .fs_flags = FS_HAS_SUBTYPE, | ||
639 | .get_sb = fuse_get_sb, | 640 | .get_sb = fuse_get_sb, |
640 | .kill_sb = kill_anon_super, | 641 | .kill_sb = kill_anon_super, |
641 | }; | 642 | }; |
@@ -652,6 +653,7 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type, | |||
652 | static struct file_system_type fuseblk_fs_type = { | 653 | static struct file_system_type fuseblk_fs_type = { |
653 | .owner = THIS_MODULE, | 654 | .owner = THIS_MODULE, |
654 | .name = "fuseblk", | 655 | .name = "fuseblk", |
656 | .fs_flags = FS_HAS_SUBTYPE, | ||
655 | .get_sb = fuse_get_sb_blk, | 657 | .get_sb = fuse_get_sb_blk, |
656 | .kill_sb = kill_block_super, | 658 | .kill_sb = kill_block_super, |
657 | .fs_flags = FS_REQUIRES_DEV, | 659 | .fs_flags = FS_REQUIRES_DEV, |
diff --git a/fs/namespace.c b/fs/namespace.c index be5e56bfb73e..c5b88100d914 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -377,6 +377,10 @@ static int show_vfsmnt(struct seq_file *m, void *v) | |||
377 | seq_path(m, mnt, mnt->mnt_root, " \t\n\\"); | 377 | seq_path(m, mnt, mnt->mnt_root, " \t\n\\"); |
378 | seq_putc(m, ' '); | 378 | seq_putc(m, ' '); |
379 | mangle(m, mnt->mnt_sb->s_type->name); | 379 | mangle(m, mnt->mnt_sb->s_type->name); |
380 | if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) { | ||
381 | seq_putc(m, '.'); | ||
382 | mangle(m, mnt->mnt_sb->s_subtype); | ||
383 | } | ||
380 | seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw"); | 384 | seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw"); |
381 | for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { | 385 | for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { |
382 | if (mnt->mnt_sb->s_flags & fs_infop->flag) | 386 | if (mnt->mnt_sb->s_flags & fs_infop->flag) |
diff --git a/fs/super.c b/fs/super.c index 8341e4e1d738..5260d620c555 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -107,6 +107,7 @@ out: | |||
107 | static inline void destroy_super(struct super_block *s) | 107 | static inline void destroy_super(struct super_block *s) |
108 | { | 108 | { |
109 | security_sb_free(s); | 109 | security_sb_free(s); |
110 | kfree(s->s_subtype); | ||
110 | kfree(s); | 111 | kfree(s); |
111 | } | 112 | } |
112 | 113 | ||
@@ -907,6 +908,29 @@ out: | |||
907 | 908 | ||
908 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 909 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |
909 | 910 | ||
911 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) | ||
912 | { | ||
913 | int err; | ||
914 | const char *subtype = strchr(fstype, '.'); | ||
915 | if (subtype) { | ||
916 | subtype++; | ||
917 | err = -EINVAL; | ||
918 | if (!subtype[0]) | ||
919 | goto err; | ||
920 | } else | ||
921 | subtype = ""; | ||
922 | |||
923 | mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL); | ||
924 | err = -ENOMEM; | ||
925 | if (!mnt->mnt_sb->s_subtype) | ||
926 | goto err; | ||
927 | return mnt; | ||
928 | |||
929 | err: | ||
930 | mntput(mnt); | ||
931 | return ERR_PTR(err); | ||
932 | } | ||
933 | |||
910 | struct vfsmount * | 934 | struct vfsmount * |
911 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | 935 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) |
912 | { | 936 | { |
@@ -915,6 +939,9 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) | |||
915 | if (!type) | 939 | if (!type) |
916 | return ERR_PTR(-ENODEV); | 940 | return ERR_PTR(-ENODEV); |
917 | mnt = vfs_kern_mount(type, flags, name, data); | 941 | mnt = vfs_kern_mount(type, flags, name, data); |
942 | if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && | ||
943 | !mnt->mnt_sb->s_subtype) | ||
944 | mnt = fs_set_subtype(mnt, fstype); | ||
918 | put_filesystem(type); | 945 | put_filesystem(type); |
919 | return mnt; | 946 | return mnt; |
920 | } | 947 | } |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 986b5d5d369f..527a09a82297 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -92,6 +92,7 @@ extern int dir_notify_enable; | |||
92 | /* public flags for file_system_type */ | 92 | /* public flags for file_system_type */ |
93 | #define FS_REQUIRES_DEV 1 | 93 | #define FS_REQUIRES_DEV 1 |
94 | #define FS_BINARY_MOUNTDATA 2 | 94 | #define FS_BINARY_MOUNTDATA 2 |
95 | #define FS_HAS_SUBTYPE 4 | ||
95 | #define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ | 96 | #define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ |
96 | #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() | 97 | #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() |
97 | * during rename() internally. | 98 | * during rename() internally. |
@@ -961,6 +962,12 @@ struct super_block { | |||
961 | /* Granularity of c/m/atime in ns. | 962 | /* Granularity of c/m/atime in ns. |
962 | Cannot be worse than a second */ | 963 | Cannot be worse than a second */ |
963 | u32 s_time_gran; | 964 | u32 s_time_gran; |
965 | |||
966 | /* | ||
967 | * Filesystem subtype. If non-empty the filesystem type field | ||
968 | * in /proc/mounts will be "type.subtype" | ||
969 | */ | ||
970 | char *s_subtype; | ||
964 | }; | 971 | }; |
965 | 972 | ||
966 | extern struct timespec current_fs_time(struct super_block *sb); | 973 | extern struct timespec current_fs_time(struct super_block *sb); |