Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / gfs2 / ops_fstype.c
index 6c906078f657024c6f17c663b413a97de643e8b0..e5af9dc420ef0c3f1d9a40034b7a63b5791c04f0 100644 (file)
@@ -1118,20 +1118,33 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
        }
 
        error = init_names(sdp, silent);
-       if (error)
-               goto fail;
+       if (error) {
+               /* In this case, we haven't initialized sysfs, so we have to
+                  manually free the sdp. */
+               free_percpu(sdp->sd_lkstats);
+               kfree(sdp);
+               sb->s_fs_info = NULL;
+               return error;
+       }
 
        snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s", sdp->sd_table_name);
 
-       gfs2_create_debugfs_file(sdp);
-
        error = gfs2_sys_fs_add(sdp);
+       /*
+        * If we hit an error here, gfs2_sys_fs_add will have called function
+        * kobject_put which causes the sysfs usage count to go to zero, which
+        * causes sysfs to call function gfs2_sbd_release, which frees sdp.
+        * Subsequent error paths here will call gfs2_sys_fs_del, which also
+        * kobject_put to free sdp.
+        */
        if (error)
-               goto fail;
+               return error;
+
+       gfs2_create_debugfs_file(sdp);
 
        error = gfs2_lm_mount(sdp, silent);
        if (error)
-               goto fail_sys;
+               goto fail_debug;
 
        error = init_locking(sdp, &mount_gh, DO);
        if (error)
@@ -1215,12 +1228,12 @@ fail_locking:
 fail_lm:
        gfs2_gl_hash_clear(sdp);
        gfs2_lm_unmount(sdp);
-fail_sys:
-       gfs2_sys_fs_del(sdp);
-fail:
+fail_debug:
        gfs2_delete_debugfs_file(sdp);
        free_percpu(sdp->sd_lkstats);
-       kfree(sdp);
+       /* gfs2_sys_fs_del must be the last thing we do, since it causes
+        * sysfs to call function gfs2_sbd_release, which frees sdp. */
+       gfs2_sys_fs_del(sdp);
        sb->s_fs_info = NULL;
        return error;
 }
@@ -1389,10 +1402,9 @@ static void gfs2_kill_sb(struct super_block *sb)
        sdp->sd_root_dir = NULL;
        sdp->sd_master_dir = NULL;
        shrink_dcache_sb(sb);
-       kill_block_super(sb);
        gfs2_delete_debugfs_file(sdp);
        free_percpu(sdp->sd_lkstats);
-       kfree(sdp);
+       kill_block_super(sb);
 }
 
 struct file_system_type gfs2_fs_type = {