diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-02-19 04:23:32 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-02-24 02:00:39 -0500 |
commit | 6437d1b0adb46f29aafcbf10950a89211028ca09 (patch) | |
tree | 3596b9ba5000ed637de0d557478886f494ee9dc0 | |
parent | 8618b881e9fd0e1817ff5cb7befadd3240d54830 (diff) |
f2fs: fix to do build_stat prior to the recovery procedure
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>
-rw-r--r-- | fs/f2fs/super.c | 48 |
1 files changed, 24 insertions, 24 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1a85f83abd53..475560e5ee71 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -989,28 +989,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
989 | goto free_root_inode; | 989 | goto free_root_inode; |
990 | } | 990 | } |
991 | 991 | ||
992 | /* recover fsynced data */ | ||
993 | if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { | ||
994 | err = recover_fsync_data(sbi); | ||
995 | if (err) | ||
996 | f2fs_msg(sb, KERN_ERR, | ||
997 | "Cannot recover all fsync data errno=%ld", err); | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * If filesystem is not mounted as read-only then | ||
1002 | * do start the gc_thread. | ||
1003 | */ | ||
1004 | if (!(sb->s_flags & MS_RDONLY)) { | ||
1005 | /* After POR, we can run background GC thread.*/ | ||
1006 | err = start_gc_thread(sbi); | ||
1007 | if (err) | ||
1008 | goto free_gc; | ||
1009 | } | ||
1010 | |||
1011 | err = f2fs_build_stats(sbi); | 992 | err = f2fs_build_stats(sbi); |
1012 | if (err) | 993 | if (err) |
1013 | goto free_gc; | 994 | goto free_root_inode; |
1014 | 995 | ||
1015 | if (f2fs_proc_root) | 996 | if (f2fs_proc_root) |
1016 | sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); | 997 | 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) | |||
1032 | err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL, | 1013 | err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL, |
1033 | "%s", sb->s_id); | 1014 | "%s", sb->s_id); |
1034 | if (err) | 1015 | if (err) |
1035 | goto fail; | 1016 | goto free_proc; |
1036 | 1017 | ||
1018 | /* recover fsynced data */ | ||
1019 | if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { | ||
1020 | err = recover_fsync_data(sbi); | ||
1021 | if (err) | ||
1022 | f2fs_msg(sb, KERN_ERR, | ||
1023 | "Cannot recover all fsync data errno=%ld", err); | ||
1024 | } | ||
1025 | |||
1026 | /* | ||
1027 | * If filesystem is not mounted as read-only then | ||
1028 | * do start the gc_thread. | ||
1029 | */ | ||
1030 | if (!(sb->s_flags & MS_RDONLY)) { | ||
1031 | /* After POR, we can run background GC thread.*/ | ||
1032 | err = start_gc_thread(sbi); | ||
1033 | if (err) | ||
1034 | goto free_kobj; | ||
1035 | } | ||
1037 | return 0; | 1036 | return 0; |
1038 | fail: | 1037 | |
1038 | free_kobj: | ||
1039 | kobject_del(&sbi->s_kobj); | ||
1040 | free_proc: | ||
1039 | if (sbi->s_proc) { | 1041 | if (sbi->s_proc) { |
1040 | remove_proc_entry("segment_info", sbi->s_proc); | 1042 | remove_proc_entry("segment_info", sbi->s_proc); |
1041 | remove_proc_entry(sb->s_id, f2fs_proc_root); | 1043 | remove_proc_entry(sb->s_id, f2fs_proc_root); |
1042 | } | 1044 | } |
1043 | f2fs_destroy_stats(sbi); | 1045 | f2fs_destroy_stats(sbi); |
1044 | free_gc: | ||
1045 | stop_gc_thread(sbi); | ||
1046 | free_root_inode: | 1046 | free_root_inode: |
1047 | dput(sb->s_root); | 1047 | dput(sb->s_root); |
1048 | sb->s_root = NULL; | 1048 | sb->s_root = NULL; |