diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-04-15 00:57:55 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-05-06 21:21:54 -0400 |
commit | 1e87a78d95ecea7a989349860feb42db3e4b7db5 (patch) | |
tree | 77e8a24c621760c18ee7cf599ad93fd92744032f /fs/f2fs/checkpoint.c | |
parent | b270ad6f0aedd27bdc689fc15f26bc650a59b12b (diff) |
f2fs: avoid to conduct roll-forward due to the remained garbage blocks
The f2fs always scans the next chain of direct node blocks.
But some garbage blocks are able to be remained due to no discard support or
SSR triggers.
This occasionally wreaks recovering wrong inodes that were used or BUG_ONs
due to reallocating node ids as follows.
When mount this f2fs image:
http://linuxtesting.org/downloads/f2fs_fault_image.zip
BUG_ON is triggered in f2fs driver (messages below are generated on
kernel 3.13.2; for other kernels output is similar):
kernel BUG at fs/f2fs/node.c:215!
Call Trace:
[<ffffffffa032ebad>] recover_inode_page+0x1fd/0x3e0 [f2fs]
[<ffffffff811446e7>] ? __lock_page+0x67/0x70
[<ffffffff81089990>] ? autoremove_wake_function+0x50/0x50
[<ffffffffa0337788>] recover_fsync_data+0x1398/0x15d0 [f2fs]
[<ffffffff812b9e5c>] ? selinux_d_instantiate+0x1c/0x20
[<ffffffff811cb20b>] ? d_instantiate+0x5b/0x80
[<ffffffffa0321044>] f2fs_fill_super+0xb04/0xbf0 [f2fs]
[<ffffffff811b861e>] ? mount_bdev+0x7e/0x210
[<ffffffff811b8769>] mount_bdev+0x1c9/0x210
[<ffffffffa0320540>] ? validate_superblock+0x210/0x210 [f2fs]
[<ffffffffa031cf8d>] f2fs_mount+0x1d/0x30 [f2fs]
[<ffffffff811b9497>] mount_fs+0x47/0x1c0
[<ffffffff81166e00>] ? __alloc_percpu+0x10/0x20
[<ffffffff811d4032>] vfs_kern_mount+0x72/0x110
[<ffffffff811d6763>] do_mount+0x493/0x910
[<ffffffff811615cb>] ? strndup_user+0x5b/0x80
[<ffffffff811d6c70>] SyS_mount+0x90/0xe0
[<ffffffff8166f8d9>] system_call_fastpath+0x16/0x1b
Found by Linux File System Verification project (linuxtesting.org).
Reported-by: Andrey Tsyvarev <tsyvarev@ispras.ru>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/checkpoint.c')
-rw-r--r-- | fs/f2fs/checkpoint.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 4aa521aa9bc3..890e23d208a8 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -762,6 +762,12 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
762 | void *kaddr; | 762 | void *kaddr; |
763 | int i; | 763 | int i; |
764 | 764 | ||
765 | /* | ||
766 | * This avoids to conduct wrong roll-forward operations and uses | ||
767 | * metapages, so should be called prior to sync_meta_pages below. | ||
768 | */ | ||
769 | discard_next_dnode(sbi); | ||
770 | |||
765 | /* Flush all the NAT/SIT pages */ | 771 | /* Flush all the NAT/SIT pages */ |
766 | while (get_pages(sbi, F2FS_DIRTY_META)) | 772 | while (get_pages(sbi, F2FS_DIRTY_META)) |
767 | sync_meta_pages(sbi, META, LONG_MAX); | 773 | sync_meta_pages(sbi, META, LONG_MAX); |