Skip to content

Commit 042be0f

Browse files
chaseyuJaegeuk Kim
authored and
Jaegeuk Kim
committed
f2fs: fix to do sanity check with current segment number
https://bugzilla.kernel.org/show_bug.cgi?id=200219 Reproduction way: - mount image - run poc code - umount image F2FS-fs (loop1): Bitmap was wrongly set, blk:15364 ------------[ cut here ]------------ kernel BUG at /home/yuchao/git/devf2fs/segment.c:2061! invalid opcode: 0000 [#1] PREEMPT SMP CPU: 2 PID: 17686 Comm: umount Tainted: G W O 4.18.0-rc2+ #39 Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 EIP: update_sit_entry+0x459/0x4e0 [f2fs] Code: e8 1c b5 fd ff 0f 0b 0f 0b 8b 45 e4 c7 44 24 08 9c 7a 6c f8 c7 44 24 04 bc 4a 6c f8 89 44 24 0c 8b 06 89 04 24 e8 f7 b4 fd ff <0f> 0b 8b 45 e4 0f b6 d2 89 54 24 10 c7 44 24 08 60 7a 6c f8 c7 44 EAX: 00000032 EBX: 000000f8 ECX: 00000002 EDX: 00000001 ESI: d7177000 EDI: f520fe68 EBP: d6477c6c ESP: d6477c34 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010282 CR0: 80050033 CR2: b7fbe000 CR3: 2a99b3c0 CR4: 000406f0 Call Trace: f2fs_allocate_data_block+0x124/0x580 [f2fs] do_write_page+0x78/0x150 [f2fs] f2fs_do_write_node_page+0x25/0xa0 [f2fs] __write_node_page+0x2bf/0x550 [f2fs] f2fs_sync_node_pages+0x60e/0x6d0 [f2fs] ? sync_inode_metadata+0x2f/0x40 ? f2fs_write_checkpoint+0x28f/0x7d0 [f2fs] ? up_write+0x1e/0x80 f2fs_write_checkpoint+0x2a9/0x7d0 [f2fs] ? mark_held_locks+0x5d/0x80 ? _raw_spin_unlock_irq+0x27/0x50 kill_f2fs_super+0x68/0x90 [f2fs] deactivate_locked_super+0x3d/0x70 deactivate_super+0x40/0x60 cleanup_mnt+0x39/0x70 __cleanup_mnt+0x10/0x20 task_work_run+0x81/0xa0 exit_to_usermode_loop+0x59/0xa7 do_fast_syscall_32+0x1f5/0x22c entry_SYSENTER_32+0x53/0x86 EIP: 0xb7f95c51 Code: c1 1e f7 ff ff 89 e5 8b 55 08 85 d2 8b 81 64 cd ff ff 74 02 89 02 5d c3 8b 0c 24 c3 8b 1c 24 c3 90 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 90 90 90 8d 76 00 58 b8 77 00 00 00 cd 80 90 8d 76 EAX: 00000000 EBX: 0871ab90 ECX: bfb2cd00 EDX: 00000000 ESI: 00000000 EDI: 0871ab90 EBP: 0871ab90 ESP: bfb2cd7c DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b EFLAGS: 00000246 Modules linked in: f2fs(O) crc32_generic bnep rfcomm bluetooth ecdh_generic snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq pcbc joydev aesni_intel snd_seq_device aes_i586 snd_timer crypto_simd snd cryptd soundcore mac_hid serio_raw video i2c_piix4 parport_pc ppdev lp parport hid_generic psmouse usbhid hid e1000 [last unloaded: f2fs] ---[ end trace d423f83982cfcdc5 ]--- The reason is, different log headers using the same segment, once one log's next block address is used by another log, it will cause panic as above. Main area: 24 segs, 24 secs 24 zones - COLD data: 0, 0, 0 - WARM data: 1, 1, 1 - HOT data: 20, 20, 20 - Dir dnode: 22, 22, 22 - File dnode: 22, 22, 22 - Indir nodes: 21, 21, 21 So this patch adds sanity check to detect such condition to avoid this issue. Signed-off-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 4a70e25 commit 042be0f

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

fs/f2fs/super.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2325,7 +2325,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
23252325
unsigned int segment_count_main;
23262326
unsigned int cp_pack_start_sum, cp_payload;
23272327
block_t user_block_count;
2328-
int i;
2328+
int i, j;
23292329

23302330
total = le32_to_cpu(raw_super->segment_count);
23312331
fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
@@ -2366,11 +2366,43 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
23662366
if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
23672367
le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
23682368
return 1;
2369+
for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
2370+
if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
2371+
le32_to_cpu(ckpt->cur_node_segno[j])) {
2372+
f2fs_msg(sbi->sb, KERN_ERR,
2373+
"Node segment (%u, %u) has the same "
2374+
"segno: %u", i, j,
2375+
le32_to_cpu(ckpt->cur_node_segno[i]));
2376+
return 1;
2377+
}
2378+
}
23692379
}
23702380
for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
23712381
if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
23722382
le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
23732383
return 1;
2384+
for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
2385+
if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
2386+
le32_to_cpu(ckpt->cur_data_segno[j])) {
2387+
f2fs_msg(sbi->sb, KERN_ERR,
2388+
"Data segment (%u, %u) has the same "
2389+
"segno: %u", i, j,
2390+
le32_to_cpu(ckpt->cur_data_segno[i]));
2391+
return 1;
2392+
}
2393+
}
2394+
}
2395+
for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
2396+
for (j = i; j < NR_CURSEG_DATA_TYPE; j++) {
2397+
if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
2398+
le32_to_cpu(ckpt->cur_data_segno[j])) {
2399+
f2fs_msg(sbi->sb, KERN_ERR,
2400+
"Data segment (%u) and Data segment (%u)"
2401+
" has the same segno: %u", i, j,
2402+
le32_to_cpu(ckpt->cur_node_segno[i]));
2403+
return 1;
2404+
}
2405+
}
23742406
}
23752407

23762408
sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);

0 commit comments

Comments
 (0)