aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-05-08 03:25:43 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:01 -0400
commit79c0b2df79eb56fc71e54c75cd7fb3acf84370f9 (patch)
treef19be816fef3565b7f9cc746786e29fee0ac62e6
parent880afc4d76af452267174b5989943f081c1db2c0 (diff)
add filesystem subtype support
There's a slight problem with filesystem type representation in fuse based filesystems. From the kernel's view, there are just two filesystem types: fuse and fuseblk. From the user's view there are lots of different filesystem types. The user is not even much concerned if the filesystem is fuse based or not. So there's a conflict of interest in how this should be represented in fstab, mtab and /proc/mounts. The current scheme is to encode the real filesystem type in the mount source. So an sshfs mount looks like this: sshfs#user@server:/ /mnt/server fuse rw,nosuid,nodev,... This url-ish syntax works OK for sshfs and similar filesystems. However for block device based filesystems (ntfs-3g, zfs) it doesn't work, since the kernel expects the mount source to be a real device name. A possibly better scheme would be to encode the real type in the type field as "type.subtype". So fuse mounts would look like this: /dev/hda1 /mnt/windows fuseblk.ntfs-3g rw,... user@server:/ /mnt/server fuse.sshfs rw,nosuid,nodev,... This patch adds the necessary code to the kernel so that this can be correctly displayed in /proc/mounts. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-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);