summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaeho Jeong <daehojeong@google.com>2026-05-14 13:55:13 -0700
committerJaegeuk Kim <jaegeuk@kernel.org>2026-06-22 19:52:34 +0000
commit5dfb768326b95c6dd6554f34dec71b44a01a0bc8 (patch)
tree58d936821ea21f375d0d8bb2ec0dd8455d0de5b7
parentf6b24566035835dc22796f24b1e8738581840b17 (diff)
f2fs: optimize representative type determination in GC
In large section mode, do_garbage_collect() previously determined the section's representative type by looking only at the first segment of the section. However, if data was fsynced into an area previously used as a node section, and this area is recovered during roll-forward recovery after sudden power off (SPO), GC would incorrectly assume the section's type based on an empty or obsolete first segment. This caused the recovered data segment to be misunderstood as being stuck inside a node section, triggering false inconsistency panics (Inconsistent segment type in SSA and SIT) and subsequent mount failures. This patch optimizes do_garbage_collect() to determine the section's representative type by identifying the first segment that actually contains valid blocks (valid_blocks > 0) during the main GC loop. This eliminates false alarms from empty/obsolete leading segments while maintaining strict section-level type consistency checks for genuine corruption. Signed-off-by: Daeho Jeong <daehojeong@google.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/gc.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ba93010924c0..99bc59889825 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1754,9 +1754,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
unsigned int end_segno = start_segno + SEGS_PER_SEC(sbi);
unsigned int sec_end_segno;
int seg_freed = 0, migrated = 0;
- unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
- SUM_TYPE_DATA : SUM_TYPE_NODE;
- unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : NODE;
+ unsigned char type;
+ unsigned char data_type;
int submitted = 0, sum_blk_cnt;
if (__is_large_section(sbi)) {
@@ -1855,6 +1854,12 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
migrated >= sbi->migration_granularity)
continue;
+ if (migrated == 0) {
+ type = IS_DATASEG(get_seg_entry(sbi, cur_segno)->type) ?
+ SUM_TYPE_DATA : SUM_TYPE_NODE;
+ data_type = (type == SUM_TYPE_DATA) ? DATA : NODE;
+ }
+
sum = SUM_BLK_PAGE_ADDR(sbi, sum_folio, cur_segno);
if (type != GET_SUM_TYPE(sum_footer(sbi, sum))) {
f2fs_err(sbi, "Inconsistent segment (%u) type "