]>
Commit | Line | Data |
---|---|---|
38edc49d SLM |
1 | From a53f0ad2910b948796a113899b4d2b0afb2933c2 Mon Sep 17 00:00:00 2001 |
2 | From: Chao Yu <yuchao0@huawei.com> | |
3 | Date: Thu, 6 Sep 2018 20:34:12 +0800 | |
4 | Subject: f2fs: fix to do sanity check with current segment number | |
5 | ||
6 | [ Upstream commit 042be0f849e5fc24116d0afecfaf926eed5cac63 ] | |
7 | ||
8 | https://bugzilla.kernel.org/show_bug.cgi?id=200219 | |
9 | ||
10 | Reproduction way: | |
11 | - mount image | |
12 | - run poc code | |
13 | - umount image | |
14 | ||
15 | F2FS-fs (loop1): Bitmap was wrongly set, blk:15364 | |
16 | ------------[ cut here ]------------ | |
17 | kernel BUG at /home/yuchao/git/devf2fs/segment.c:2061! | |
18 | invalid opcode: 0000 [#1] PREEMPT SMP | |
19 | CPU: 2 PID: 17686 Comm: umount Tainted: G W O 4.18.0-rc2+ #39 | |
20 | Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 | |
21 | EIP: update_sit_entry+0x459/0x4e0 [f2fs] | |
22 | 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 | |
23 | EAX: 00000032 EBX: 000000f8 ECX: 00000002 EDX: 00000001 | |
24 | ESI: d7177000 EDI: f520fe68 EBP: d6477c6c ESP: d6477c34 | |
25 | DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010282 | |
26 | CR0: 80050033 CR2: b7fbe000 CR3: 2a99b3c0 CR4: 000406f0 | |
27 | Call Trace: | |
28 | f2fs_allocate_data_block+0x124/0x580 [f2fs] | |
29 | do_write_page+0x78/0x150 [f2fs] | |
30 | f2fs_do_write_node_page+0x25/0xa0 [f2fs] | |
31 | __write_node_page+0x2bf/0x550 [f2fs] | |
32 | f2fs_sync_node_pages+0x60e/0x6d0 [f2fs] | |
33 | ? sync_inode_metadata+0x2f/0x40 | |
34 | ? f2fs_write_checkpoint+0x28f/0x7d0 [f2fs] | |
35 | ? up_write+0x1e/0x80 | |
36 | f2fs_write_checkpoint+0x2a9/0x7d0 [f2fs] | |
37 | ? mark_held_locks+0x5d/0x80 | |
38 | ? _raw_spin_unlock_irq+0x27/0x50 | |
39 | kill_f2fs_super+0x68/0x90 [f2fs] | |
40 | deactivate_locked_super+0x3d/0x70 | |
41 | deactivate_super+0x40/0x60 | |
42 | cleanup_mnt+0x39/0x70 | |
43 | __cleanup_mnt+0x10/0x20 | |
44 | task_work_run+0x81/0xa0 | |
45 | exit_to_usermode_loop+0x59/0xa7 | |
46 | do_fast_syscall_32+0x1f5/0x22c | |
47 | entry_SYSENTER_32+0x53/0x86 | |
48 | EIP: 0xb7f95c51 | |
49 | 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 | |
50 | EAX: 00000000 EBX: 0871ab90 ECX: bfb2cd00 EDX: 00000000 | |
51 | ESI: 00000000 EDI: 0871ab90 EBP: 0871ab90 ESP: bfb2cd7c | |
52 | DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b EFLAGS: 00000246 | |
53 | 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] | |
54 | ---[ end trace d423f83982cfcdc5 ]--- | |
55 | ||
56 | The reason is, different log headers using the same segment, once | |
57 | one log's next block address is used by another log, it will cause | |
58 | panic as above. | |
59 | ||
60 | Main area: 24 segs, 24 secs 24 zones | |
61 | - COLD data: 0, 0, 0 | |
62 | - WARM data: 1, 1, 1 | |
63 | - HOT data: 20, 20, 20 | |
64 | - Dir dnode: 22, 22, 22 | |
65 | - File dnode: 22, 22, 22 | |
66 | - Indir nodes: 21, 21, 21 | |
67 | ||
68 | So this patch adds sanity check to detect such condition to avoid | |
69 | this issue. | |
70 | ||
71 | Signed-off-by: Chao Yu <yuchao0@huawei.com> | |
72 | ||
73 | Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> | |
74 | ||
75 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
76 | --- | |
77 | fs/f2fs/super.c | 34 +++++++++++++++++++++++++++++++++- | |
78 | 1 file changed, 33 insertions(+), 1 deletion(-) | |
79 | ||
80 | diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c | |
81 | index dbd7adff8b5a..bd0dfaecfac3 100644 | |
82 | --- a/fs/f2fs/super.c | |
83 | +++ b/fs/f2fs/super.c | |
84 | @@ -1143,7 +1143,7 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi) | |
85 | unsigned int segment_count_main; | |
86 | unsigned int cp_pack_start_sum, cp_payload; | |
87 | block_t user_block_count; | |
88 | - int i; | |
89 | + int i, j; | |
90 | ||
91 | total = le32_to_cpu(raw_super->segment_count); | |
92 | fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); | |
93 | @@ -1184,11 +1184,43 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi) | |
94 | if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || | |
95 | le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) | |
96 | return 1; | |
97 | + for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) { | |
98 | + if (le32_to_cpu(ckpt->cur_node_segno[i]) == | |
99 | + le32_to_cpu(ckpt->cur_node_segno[j])) { | |
100 | + f2fs_msg(sbi->sb, KERN_ERR, | |
101 | + "Node segment (%u, %u) has the same " | |
102 | + "segno: %u", i, j, | |
103 | + le32_to_cpu(ckpt->cur_node_segno[i])); | |
104 | + return 1; | |
105 | + } | |
106 | + } | |
107 | } | |
108 | for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { | |
109 | if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || | |
110 | le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) | |
111 | return 1; | |
112 | + for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) { | |
113 | + if (le32_to_cpu(ckpt->cur_data_segno[i]) == | |
114 | + le32_to_cpu(ckpt->cur_data_segno[j])) { | |
115 | + f2fs_msg(sbi->sb, KERN_ERR, | |
116 | + "Data segment (%u, %u) has the same " | |
117 | + "segno: %u", i, j, | |
118 | + le32_to_cpu(ckpt->cur_data_segno[i])); | |
119 | + return 1; | |
120 | + } | |
121 | + } | |
122 | + } | |
123 | + for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { | |
124 | + for (j = i; j < NR_CURSEG_DATA_TYPE; j++) { | |
125 | + if (le32_to_cpu(ckpt->cur_node_segno[i]) == | |
126 | + le32_to_cpu(ckpt->cur_data_segno[j])) { | |
127 | + f2fs_msg(sbi->sb, KERN_ERR, | |
128 | + "Data segment (%u) and Data segment (%u)" | |
129 | + " has the same segno: %u", i, j, | |
130 | + le32_to_cpu(ckpt->cur_node_segno[i])); | |
131 | + return 1; | |
132 | + } | |
133 | + } | |
134 | } | |
135 | ||
136 | sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize); | |
137 | -- | |
138 | 2.19.1 | |
139 |