[GFS2] soft lockup detected in databuf_lo_before_commit
[sfrench/cifs-2.6.git] / fs / super.c
index 8341e4e1d7380f49ce590a428456b12c88e11fed..fc8ebedc6bed1aa901e24ebf8e34fd397cc6361e 100644 (file)
@@ -107,6 +107,7 @@ out:
 static inline void destroy_super(struct super_block *s)
 {
        security_sb_free(s);
+       kfree(s->s_subtype);
        kfree(s);
 }
 
@@ -883,6 +884,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        error = type->get_sb(type, flags, name, data, mnt);
        if (error < 0)
                goto out_free_secdata;
+       BUG_ON(!mnt->mnt_sb);
 
        error = security_sb_kern_mount(mnt->mnt_sb, secdata);
        if (error)
@@ -907,6 +909,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 +940,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;
 }