fsck.f2fs -d1 <device>

[fix_section_type:3036] wrong sit->type (4) in DATA secno:1 segno:2
[fix_section_type:3036] wrong sit->type (4) in DATA secno:5 segno:11

fsck.f2fs -f <device>

[FIX] (fix_section_type:3040)  --> Fix wrong sit->type (4 -> 2) in DATA secno 
(1), segno (2)
[FIX] (fix_section_type:3050)  --> Fix wrong sit->type in DATA secno (1), 
totally 1 empty segment(s)
[FIX] (fix_section_type:3040)  --> Fix wrong sit->type (4 -> 2) in DATA secno 
(5), segno (11)
[FIX] (fix_section_type:3050)  --> Fix wrong sit->type in DATA secno (5), 
totally 1 empty segment(s)

Now it can only fix wrong sit->type of segment from NODE to DATA in a DATA
section, such inconsistent image can be generated by recovery.

For fuzzed image which contains below inconsistent sit->type, we can support
to detect and repair later:
1) empty NODE segment in DATA section (FIXED w/ current patch)
2) empty DATA segment in NODE section
3) valid segments w/ different temperature in DATA section
4) valid segments w/ different temperature in NODE section
5) valid segments w/ different sit->type in section

Cc: Daeho Jeong <[email protected]>
Signed-off-by: Chao Yu <[email protected]>
---
v2:
- fix printed log
 fsck/f2fs.h | 13 ++++++++
 fsck/fsck.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 5e7eb63..e4e5d0c 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -572,6 +572,19 @@ static inline int IS_CUR_SEGNO(struct f2fs_sb_info *sbi, 
u32 segno)
        return 0;
 }
 
+static inline int IS_CUR_SECNO(struct f2fs_sb_info *sbi, u32 secno)
+{
+       int i;
+
+       for (i = 0; i < NO_CHECK_TYPE; i++) {
+               struct curseg_info *curseg = CURSEG_I(sbi, i);
+
+               if (secno == GET_SEC_FROM_SEG(sbi, curseg->segno))
+                       return 1;
+       }
+       return 0;
+}
+
 static inline u64 BLKOFF_FROM_MAIN(struct f2fs_sb_info *sbi, u64 blk_addr)
 {
        ASSERT(blk_addr >= SM_I(sbi)->main_blkaddr);
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 1230d7b..4fca4dd 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -3012,6 +3012,97 @@ int check_sit_types(struct f2fs_sb_info *sbi)
        }
        return err;
 }
+enum type_fix   {
+       TYPE_DATA,              /* fix sit->type of empty node segment to data 
*/
+       TYPE_NODE,              /* fix sit->type of empty data segment to node 
*/
+       TYPE_DATA_TEMP,         /* fix inconsistent sit->type temperature of 
data segment */
+       TYPE_NODE_TEMP,         /* fix inconsistent sit->type temperature of 
node segment */
+       TYPE_MIGRATE,           /* migrate node segments in mixed section */
+};
+static bool fix_section_type(struct f2fs_sb_info *sbi, unsigned int secno,
+                               unsigned char type, enum type_fix type_fix)
+{
+       unsigned int segno = secno * sbi->segs_per_sec;
+       unsigned int end_segno = segno + sbi->segs_per_sec;
+       unsigned int empty = 0;
+       bool fixed = false;
+
+       for (; segno < end_segno; segno++) {
+               struct seg_entry *se = get_seg_entry(sbi, segno);
+
+               if (type_fix == TYPE_DATA) {
+                       if (se->valid_blocks)
+                               continue;
+                       DBG(1, "wrong sit->type (%d) in DATA secno:%d 
segno:%d\n",
+                               se->type, secno, segno);
+                       if (!c.fix_on)
+                               continue;
+                       FIX_MSG("Fix wrong sit->type (%d -> %d) in DATA secno 
(%u), segno (%d)",
+                               se->type, type, secno, segno);
+                       se->type = type;
+                       empty++;
+                       fixed = true;
+                       continue;
+               }
+       }
+
+       if (fixed && type_fix == TYPE_DATA)
+               FIX_MSG("Fix wrong sit->type in DATA secno (%u), totally %d 
empty segment(s)",
+                       secno, empty);
+
+       return fixed;
+}
+
+static bool check_large_section_types(struct f2fs_sb_info *sbi)
+{
+       unsigned int secno;
+       bool fixed = false;
+
+       if (sbi->segs_per_sec <= 1)
+               return 0;
+
+       for (secno = 0; secno < sbi->total_sections; secno++) {
+               struct seg_entry *se;
+               unsigned int segno = secno * sbi->segs_per_sec;
+               unsigned int end_segno = segno + sbi->segs_per_sec;
+               unsigned short data_seg = 0;
+               unsigned short node_seg = 0;
+               unsigned short empty_data_seg = 0;
+               unsigned short empty_node_seg = 0;
+               unsigned char data_type = NO_CHECK_TYPE;
+
+               if (IS_CUR_SECNO(sbi, secno))
+                       continue;
+
+               for (; segno < end_segno; segno++) {
+                       se = get_seg_entry(sbi, segno);
+                       if (IS_DATASEG(se->type)) {
+                               if (se->valid_blocks) {
+                                       data_seg++;
+                                       data_type = se->type;
+                               } else {
+                                       empty_data_seg++;
+                               }
+                       } else {
+                               if (se->valid_blocks)
+                                       node_seg++;
+                               else
+                                       empty_node_seg++;
+                       }
+               }
+
+               /* skip free section */
+               if (!data_seg && !node_seg)
+                       continue;
+
+               /* data section, fix sit->type of empty node segment to data */
+               if (data_seg && !node_seg && empty_node_seg) {
+                       if (fix_section_type(sbi, secno, data_type, TYPE_DATA))
+                               fixed = true;
+               }
+       }
+       return fixed;
+}
 
 static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi)
 {
@@ -3834,6 +3925,9 @@ int fsck_verify(struct f2fs_sb_info *sbi)
        if (check_sit_types(sbi) != 0)
                force = 1;
 
+       if (check_large_section_types(sbi))
+               force = 1;
+
        printf("[FSCK] other corrupted bugs                          ");
        if (c.bug_on == 0) {
                printf(" [Ok..]\n");
-- 
2.49.0



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to