Skip to content

Commit 73d7508

Browse files
chaseyuJaegeuk Kim
authored andcommitted
fsck.f2fs: support to fix inconsistent sit->type of segments in large section
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 <daehojeong@google.com> Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent f5e13ff commit 73d7508

2 files changed

Lines changed: 107 additions & 0 deletions

File tree

fsck/f2fs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,19 @@ static inline int IS_CUR_SEGNO(struct f2fs_sb_info *sbi, u32 segno)
572572
return 0;
573573
}
574574

575+
static inline int IS_CUR_SECNO(struct f2fs_sb_info *sbi, u32 secno)
576+
{
577+
int i;
578+
579+
for (i = 0; i < NO_CHECK_TYPE; i++) {
580+
struct curseg_info *curseg = CURSEG_I(sbi, i);
581+
582+
if (secno == GET_SEC_FROM_SEG(sbi, curseg->segno))
583+
return 1;
584+
}
585+
return 0;
586+
}
587+
575588
static inline u64 BLKOFF_FROM_MAIN(struct f2fs_sb_info *sbi, u64 blk_addr)
576589
{
577590
ASSERT(blk_addr >= SM_I(sbi)->main_blkaddr);

fsck/fsck.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,6 +3012,97 @@ int check_sit_types(struct f2fs_sb_info *sbi)
30123012
}
30133013
return err;
30143014
}
3015+
enum type_fix {
3016+
TYPE_DATA, /* fix sit->type of empty node segment to data */
3017+
TYPE_NODE, /* fix sit->type of empty data segment to node */
3018+
TYPE_DATA_TEMP, /* fix inconsistent sit->type temperature of data segment */
3019+
TYPE_NODE_TEMP, /* fix inconsistent sit->type temperature of node segment */
3020+
TYPE_MIGRATE, /* migrate node segments in mixed section */
3021+
};
3022+
static bool fix_section_type(struct f2fs_sb_info *sbi, unsigned int secno,
3023+
unsigned char type, enum type_fix type_fix)
3024+
{
3025+
unsigned int segno = secno * sbi->segs_per_sec;
3026+
unsigned int end_segno = segno + sbi->segs_per_sec;
3027+
unsigned int empty = 0;
3028+
bool fixed = false;
3029+
3030+
for (; segno < end_segno; segno++) {
3031+
struct seg_entry *se = get_seg_entry(sbi, segno);
3032+
3033+
if (type_fix == TYPE_DATA) {
3034+
if (se->valid_blocks)
3035+
continue;
3036+
DBG(1, "wrong sit->type (%d) in DATA secno:%d segno:%d\n",
3037+
se->type, secno, segno);
3038+
if (!c.fix_on)
3039+
continue;
3040+
FIX_MSG("Fix wrong sit->type (%d -> %d) in DATA secno (%u), segno (%d)",
3041+
se->type, type, secno, segno);
3042+
se->type = type;
3043+
empty++;
3044+
fixed = true;
3045+
continue;
3046+
}
3047+
}
3048+
3049+
if (fixed && type_fix == TYPE_DATA)
3050+
FIX_MSG("Fix wrong sit->type in DATA secno (%u), totally %d empty segment(s)",
3051+
secno, empty);
3052+
3053+
return fixed;
3054+
}
3055+
3056+
static bool check_large_section_types(struct f2fs_sb_info *sbi)
3057+
{
3058+
unsigned int secno;
3059+
bool fixed = false;
3060+
3061+
if (sbi->segs_per_sec <= 1)
3062+
return 0;
3063+
3064+
for (secno = 0; secno < sbi->total_sections; secno++) {
3065+
struct seg_entry *se;
3066+
unsigned int segno = secno * sbi->segs_per_sec;
3067+
unsigned int end_segno = segno + sbi->segs_per_sec;
3068+
unsigned short data_seg = 0;
3069+
unsigned short node_seg = 0;
3070+
unsigned short empty_data_seg = 0;
3071+
unsigned short empty_node_seg = 0;
3072+
unsigned char data_type = NO_CHECK_TYPE;
3073+
3074+
if (IS_CUR_SECNO(sbi, secno))
3075+
continue;
3076+
3077+
for (; segno < end_segno; segno++) {
3078+
se = get_seg_entry(sbi, segno);
3079+
if (IS_DATASEG(se->type)) {
3080+
if (se->valid_blocks) {
3081+
data_seg++;
3082+
data_type = se->type;
3083+
} else {
3084+
empty_data_seg++;
3085+
}
3086+
} else {
3087+
if (se->valid_blocks)
3088+
node_seg++;
3089+
else
3090+
empty_node_seg++;
3091+
}
3092+
}
3093+
3094+
/* skip free section */
3095+
if (!data_seg && !node_seg)
3096+
continue;
3097+
3098+
/* data section, fix sit->type of empty node segment to data */
3099+
if (data_seg && !node_seg && empty_node_seg) {
3100+
if (fix_section_type(sbi, secno, data_type, TYPE_DATA))
3101+
fixed = true;
3102+
}
3103+
}
3104+
return fixed;
3105+
}
30153106

30163107
static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi)
30173108
{
@@ -3834,6 +3925,9 @@ int fsck_verify(struct f2fs_sb_info *sbi)
38343925
if (check_sit_types(sbi) != 0)
38353926
force = 1;
38363927

3928+
if (check_large_section_types(sbi))
3929+
force = 1;
3930+
38373931
printf("[FSCK] other corrupted bugs ");
38383932
if (c.bug_on == 0) {
38393933
printf(" [Ok..]\n");

0 commit comments

Comments
 (0)