aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/filesystems.c21
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--fs/namespace.c4
-rw-r--r--fs/super.c27
-rw-r--r--include/linux/fs.h7
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
44static struct file_system_type **find_filesystem(const char *name) 44static 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)
215struct file_system_type *get_fs_type(const char *name) 217struct 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,
636static struct file_system_type fuse_fs_type = { 636static 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,
652static struct file_system_type fuseblk_fs_type = { 653static 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:
107static inline void destroy_super(struct super_block *s) 107static 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
908EXPORT_SYMBOL_GPL(vfs_kern_mount); 909EXPORT_SYMBOL_GPL(vfs_kern_mount);
909 910
911static 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
910struct vfsmount * 934struct vfsmount *
911do_kern_mount(const char *fstype, int flags, const char *name, void *data) 935do_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
966extern struct timespec current_fs_time(struct super_block *sb); 973extern struct timespec current_fs_time(struct super_block *sb);