Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

f2fs: fix to bail out in get_new_segment()

------------[ cut here ]------------
WARNING: CPU: 3 PID: 579 at fs/f2fs/segment.c:2832 new_curseg+0x5e8/0x6dc
pc : new_curseg+0x5e8/0x6dc
Call trace:
new_curseg+0x5e8/0x6dc
f2fs_allocate_data_block+0xa54/0xe28
do_write_page+0x6c/0x194
f2fs_do_write_node_page+0x38/0x78
__write_node_page+0x248/0x6d4
f2fs_sync_node_pages+0x524/0x72c
f2fs_write_checkpoint+0x4bc/0x9b0
__checkpoint_and_complete_reqs+0x80/0x244
issue_checkpoint_thread+0x8c/0xec
kthread+0x114/0x1bc
ret_from_fork+0x10/0x20

get_new_segment() detects inconsistent status in between free_segmap
and free_secmap, let's record such error into super block, and bail
out get_new_segment() instead of continue using the segment.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Chao Yu and committed by
Jaegeuk Kim
bb5eb8a5 617e0491

+6 -1
+5 -1
fs/f2fs/segment.c
··· 2842 2842 } 2843 2843 got_it: 2844 2844 /* set it as dirty segment in free segmap */ 2845 - f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap)); 2845 + if (test_bit(segno, free_i->free_segmap)) { 2846 + ret = -EFSCORRUPTED; 2847 + f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_CORRUPTED_FREE_BITMAP); 2848 + goto out_unlock; 2849 + } 2846 2850 2847 2851 /* no free section in conventional device or conventional zone */ 2848 2852 if (new_sec && pinning &&
+1
include/linux/f2fs_fs.h
··· 78 78 STOP_CP_REASON_UPDATE_INODE, 79 79 STOP_CP_REASON_FLUSH_FAIL, 80 80 STOP_CP_REASON_NO_SEGMENT, 81 + STOP_CP_REASON_CORRUPTED_FREE_BITMAP, 81 82 STOP_CP_REASON_MAX, 82 83 }; 83 84