f2fs: fix to do build_stat prior to the recovery procedure
authorJaegeuk Kim <jaegeuk.kim@samsung.com>
Wed, 19 Feb 2014 09:23:32 +0000 (18:23 +0900)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Mon, 24 Feb 2014 07:00:39 +0000 (16:00 +0900)
At the end of the recovery procedure, write_checkpoint is called and updates
the cp count which is managed by f2fs stat.
But, previously build_stat() is called after the recovery procedure, which
results in:

BUG: unable to handle kernel NULL pointer dereference at 000000000000012c
IP: [<ffffffffa03b1030>] write_checkpoint+0x720/0xbc0 [f2fs]
Call Trace:
 [<ffffffff810a6b44>] ? mark_held_locks+0x74/0x140
 [<ffffffff8109a3e0>] ? __init_waitqueue_head+0x60/0x60
 [<ffffffffa03bf036>] recover_fsync_data+0x656/0xf20 [f2fs]
 [<ffffffff812ee3eb>] ? security_d_instantiate+0x1b/0x30
 [<ffffffffa03aeb4d>] f2fs_fill_super+0x94d/0xa00 [f2fs]
 [<ffffffff811a9825>] mount_bdev+0x1a5/0x1f0
 [<ffffffff8114915e>] ? __get_free_pages+0xe/0x40
 [<ffffffffa03ae200>] ? f2fs_remount+0x130/0x130 [f2fs]
 [<ffffffffa03aa575>] f2fs_mount+0x15/0x20 [f2fs]
 [<ffffffff811aa713>] mount_fs+0x43/0x1b0
 [<ffffffff811c7124>] vfs_kern_mount+0x74/0x160
 [<ffffffff811c5cb1>] ? __get_fs_type+0x51/0x60
 [<ffffffff811c9727>] do_mount+0x237/0xb50
 [<ffffffff811c936a>] ? copy_mount_options+0x3a/0x170

So, this patche changes the order of recovery_fsync_data() and
f2fs_build_stats().

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
fs/f2fs/super.c

index 1a85f83abd53262f9f1e7c5b71cb38919e85ab22..475560e5ee711a3bb92d76087c71a2b8c019dd47 100644 (file)
@@ -989,28 +989,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
                goto free_root_inode;
        }
 
-       /* recover fsynced data */
-       if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
-               err = recover_fsync_data(sbi);
-               if (err)
-                       f2fs_msg(sb, KERN_ERR,
-                               "Cannot recover all fsync data errno=%ld", err);
-       }
-
-       /*
-        * If filesystem is not mounted as read-only then
-        * do start the gc_thread.
-        */
-       if (!(sb->s_flags & MS_RDONLY)) {
-               /* After POR, we can run background GC thread.*/
-               err = start_gc_thread(sbi);
-               if (err)
-                       goto free_gc;
-       }
-
        err = f2fs_build_stats(sbi);
        if (err)
-               goto free_gc;
+               goto free_root_inode;
 
        if (f2fs_proc_root)
                sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
@@ -1032,17 +1013,36 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL,
                                                        "%s", sb->s_id);
        if (err)
-               goto fail;
+               goto free_proc;
 
+       /* recover fsynced data */
+       if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
+               err = recover_fsync_data(sbi);
+               if (err)
+                       f2fs_msg(sb, KERN_ERR,
+                               "Cannot recover all fsync data errno=%ld", err);
+       }
+
+       /*
+        * If filesystem is not mounted as read-only then
+        * do start the gc_thread.
+        */
+       if (!(sb->s_flags & MS_RDONLY)) {
+               /* After POR, we can run background GC thread.*/
+               err = start_gc_thread(sbi);
+               if (err)
+                       goto free_kobj;
+       }
        return 0;
-fail:
+
+free_kobj:
+       kobject_del(&sbi->s_kobj);
+free_proc:
        if (sbi->s_proc) {
                remove_proc_entry("segment_info", sbi->s_proc);
                remove_proc_entry(sb->s_id, f2fs_proc_root);
        }
        f2fs_destroy_stats(sbi);
-free_gc:
-       stop_gc_thread(sbi);
 free_root_inode:
        dput(sb->s_root);
        sb->s_root = NULL;