Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=79c0b2df79eb56fc71e54c75cd7fb3acf84370f9
Commit:     79c0b2df79eb56fc71e54c75cd7fb3acf84370f9
Parent:     880afc4d76af452267174b5989943f081c1db2c0
Author:     Miklos Szeredi <[EMAIL PROTECTED]>
AuthorDate: Tue May 8 00:25:43 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue May 8 11:15:01 2007 -0700

    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:
    
      [EMAIL PROTECTED]:/   /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,...
      [EMAIL PROTECTED]:/   /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 <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/filesystems.c   |   21 +++++++++++++++------
 fs/fuse/inode.c    |    2 ++
 fs/namespace.c     |    4 ++++
 fs/super.c         |   27 +++++++++++++++++++++++++++
 include/linux/fs.h |    7 +++++++
 5 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/fs/filesystems.c b/fs/filesystems.c
index 7a4f61a..f37f872 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -41,11 +41,12 @@ void put_filesystem(struct file_system_type *fs)
        module_put(fs->owner);
 }
 
-static struct file_system_type **find_filesystem(const char *name)
+static struct file_system_type **find_filesystem(const char *name, unsigned 
len)
 {
        struct file_system_type **p;
        for (p=&file_systems; *p; p=&(*p)->next)
-               if (strcmp((*p)->name,name) == 0)
+               if (strlen((*p)->name) == len &&
+                   strncmp((*p)->name, name, len) == 0)
                        break;
        return p;
 }
@@ -68,11 +69,12 @@ int register_filesystem(struct file_system_type * fs)
        int res = 0;
        struct file_system_type ** p;
 
+       BUG_ON(strchr(fs->name, '.'));
        if (fs->next)
                return -EBUSY;
        INIT_LIST_HEAD(&fs->fs_supers);
        write_lock(&file_systems_lock);
-       p = find_filesystem(fs->name);
+       p = find_filesystem(fs->name, strlen(fs->name));
        if (*p)
                res = -EBUSY;
        else
@@ -215,19 +217,26 @@ int get_filesystem_list(char * buf)
 struct file_system_type *get_fs_type(const char *name)
 {
        struct file_system_type *fs;
+       const char *dot = strchr(name, '.');
+       unsigned len = dot ? dot - name : strlen(name);
 
        read_lock(&file_systems_lock);
-       fs = *(find_filesystem(name));
+       fs = *(find_filesystem(name, len));
        if (fs && !try_module_get(fs->owner))
                fs = NULL;
        read_unlock(&file_systems_lock);
-       if (!fs && (request_module("%s", name) == 0)) {
+       if (!fs && (request_module("%.*s", len, name) == 0)) {
                read_lock(&file_systems_lock);
-               fs = *(find_filesystem(name));
+               fs = *(find_filesystem(name, len));
                if (fs && !try_module_get(fs->owner))
                        fs = NULL;
                read_unlock(&file_systems_lock);
        }
+
+       if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
+               put_filesystem(fs);
+               fs = NULL;
+       }
        return fs;
 }
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index d8003be..1397018 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,
 static struct file_system_type fuse_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fuse",
+       .fs_flags       = FS_HAS_SUBTYPE,
        .get_sb         = fuse_get_sb,
        .kill_sb        = kill_anon_super,
 };
@@ -652,6 +653,7 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type,
 static struct file_system_type fuseblk_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fuseblk",
+       .fs_flags       = FS_HAS_SUBTYPE,
        .get_sb         = fuse_get_sb_blk,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
diff --git a/fs/namespace.c b/fs/namespace.c
index be5e56b..c5b8810 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -377,6 +377,10 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
        seq_putc(m, ' ');
        mangle(m, mnt->mnt_sb->s_type->name);
+       if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) {
+               seq_putc(m, '.');
+               mangle(m, mnt->mnt_sb->s_subtype);
+       }
        seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
        for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
                if (mnt->mnt_sb->s_flags & fs_infop->flag)
diff --git a/fs/super.c b/fs/super.c
index 8341e4e..5260d62 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -107,6 +107,7 @@ out:
 static inline void destroy_super(struct super_block *s)
 {
        security_sb_free(s);
+       kfree(s->s_subtype);
        kfree(s);
 }
 
@@ -907,6 +908,29 @@ out:
 
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
 
+static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char 
*fstype)
+{
+       int err;
+       const char *subtype = strchr(fstype, '.');
+       if (subtype) {
+               subtype++;
+               err = -EINVAL;
+               if (!subtype[0])
+                       goto err;
+       } else
+               subtype = "";
+
+       mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
+       err = -ENOMEM;
+       if (!mnt->mnt_sb->s_subtype)
+               goto err;
+       return mnt;
+
+ err:
+       mntput(mnt);
+       return ERR_PTR(err);
+}
+
 struct vfsmount *
 do_kern_mount(const char *fstype, int flags, const char *name, void *data)
 {
@@ -915,6 +939,9 @@ do_kern_mount(const char *fstype, int flags, const char 
*name, void *data)
        if (!type)
                return ERR_PTR(-ENODEV);
        mnt = vfs_kern_mount(type, flags, name, data);
+       if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
+           !mnt->mnt_sb->s_subtype)
+               mnt = fs_set_subtype(mnt, fstype);
        put_filesystem(type);
        return mnt;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 986b5d5..527a09a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -92,6 +92,7 @@ extern int dir_notify_enable;
 /* public flags for file_system_type */
 #define FS_REQUIRES_DEV 1 
 #define FS_BINARY_MOUNTDATA 2
+#define FS_HAS_SUBTYPE 4
 #define FS_REVAL_DOT   16384   /* Check the paths ".", ".." for staleness */
 #define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move()
                                         * during rename() internally.
@@ -961,6 +962,12 @@ struct super_block {
        /* Granularity of c/m/atime in ns.
           Cannot be worse than a second */
        u32                s_time_gran;
+
+       /*
+        * Filesystem subtype.  If non-empty the filesystem type field
+        * in /proc/mounts will be "type.subtype"
+        */
+       char *s_subtype;
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to