From nobody Fri Dec 19 10:55:54 2025 Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 758B23AA1A9 for ; Tue, 11 Nov 2025 17:52:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762883575; cv=none; b=IyiiVNeXFfK+gHhWiSeo1hktjvj3d2ZUHMaPfNZdHq+JgEF7xgSPjdQyJU41b6oPfNjeG7sT86UnzLoC5gCdpFIZjYrPcClcnh4/34L0kK1GLhDfAiPEwn8NQlRse/Va41cYwZNmZInx7B/GFAL81EValWu8uDTXFPGNSlyX++Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762883575; c=relaxed/simple; bh=31nzl/Lp9N7vgEpVIqySN1WtD3KBPr2Jn2bkpm8a+rs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=eyWRobtv9h/qQsPbF4hYoURX4O8WvRp8Kuo5X7akVUQoD3aqr0bZpF61QPCp1pTfAc2FcNt2PqbNkMI8tfkjgTdyApzhZy401xcUbIuomdKppkhBOrTe8/ocW3cpLeDVA5dtqG5CB6gy2SLPkBZZYRt2xdhld3LHVPSuOpcW/Go= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=K2nSidKG; arc=none smtp.client-ip=209.85.214.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="K2nSidKG" Received: by mail-pl1-f176.google.com with SMTP id d9443c01a7336-29844c68068so6919605ad.2 for ; Tue, 11 Nov 2025 09:52:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762883572; x=1763488372; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=CHLAHRkOadRzCSEapLp8Ki63igHWNl+gDZ/Siuh2pUs=; b=K2nSidKGipTU3RsuPbxOG/3zwk1ROjcg0pj1GBKMhSdPf5mVaRS6lefQubnFrKXEzP Ke0U3ENOJL3WjigLto6AxteUbGKcoHaXE6h0+23b9hgkwkGKRAj50D4KITMI0iy+vhhP pDI5PLtSjZ844NW6O4gEbvdrZM4jGjlpRt9DTvaJKjNpOJ+HX4sKGide/J6L1hPLr+ls ykfhY5XYWBCkPCE1bgfvpgKYqoxFTeZcSn5KFciddKUKFNtzwBnxvby03xkNXUGrp2wc azgZ3/Aq3CZH+Z82J71RwEh09uMlSL0CNbzLx4ZjuCt8ikQ8Tqgzq8Ysu8GA8H5fyLfA aFEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762883572; x=1763488372; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=CHLAHRkOadRzCSEapLp8Ki63igHWNl+gDZ/Siuh2pUs=; b=ctjbit+DSE5AOssmB/W2Wygv1/u0aZdX6QxsxuUbUELp1erMwH1dZdTVOxT2k/ccgg 1nr1R+f37fw4+/oqAG56q+u29LUlMhXQEP9qGehZN5ewSBqOrEuDfd/3c1loFv60zuHI w1WODOC7sBf4g+NtGcwDvv2HgWYC+vvIAtLBpVy5GCDxMOmxHEjoUxyNzDIPkmy/8iGz rLEI49/+V3c3moGDdbirDNNNsJ4GblpKp2oBJx1TJbuaTo6L3y0dkgyOlhdkPGNgrTBi 3IKqDwCzlV66ZrwTU3JzT9U84OIgwk4bl3x1R9GdRn9IMiaGwlQ7E+DvW+d4WYI8IAb0 2njA== X-Gm-Message-State: AOJu0Yz1UtG6jnKa4cnTNxJ5xck39sDVMGn84LQ3qqOfX8VJ3NXQxhUB AbMhuT7X16fwjqopZbTML/r9EAjqg2UzlMpRhxzhA+gAHDM7adacmF5zhGQYhw== X-Gm-Gg: ASbGncvbRrKECSdoc7TLhuE0ijZnlRROdIvjBQ+iilk8DGx5IwO2W+q4MX36A0SIrrI ctr7AvSNGBqduYZAnJafUNLwGe1jCZjZD7o7mAuHLf5w8y+2Fw+Ur6GgaY1RPSBZqZcPTat3t7d FlLJeQ/2p6Y0B5ewGOL86AWMQ7REIgaTuKQ+kPWJfLY5Sci4SU1uvb1FDmRyHSJn+7Dby8ON2aE zTmzlMTFmflhRshnWXoRmFly6tIdMSsrkix/oWCgoqb9M57mfTnjxIAwkKmbSnp5RFFd9KsfujX 8cbUI4KwQXz33oTarnNgi/cJgBSWq9VSn4FHAZaUzsLcDmcGdOxgob2ZifY9tOfkmvdJ4gO55aU jkBQa5hqao8tjIbyUsQLy/fTJL5AAkAoltDoWFdQiBdnCaDlnegQCzOExQhvRmHvGxsNKvhDQH/ s8+nrVjbtYp9p+S3MonG673cL9Wr8Pm9UNCy5O8h7oViPUrf30CROeHTruRhq5Y/06T7bxdGC+b 2Bh4A== X-Google-Smtp-Source: AGHT+IF8MujCgjTaLGsQV5RrW8FoHDJB/kkBgEvJrBes0FY+sFNcyfumgR+z7bSvslvwwf0Ky0Jy8Q== X-Received: by 2002:a17:903:244a:b0:295:1aa7:edf7 with SMTP id d9443c01a7336-2984edaaeb0mr1772315ad.30.1762883572175; Tue, 11 Nov 2025 09:52:52 -0800 (PST) Received: from daehojeong-desktop.mtv.corp.google.com ([2a00:79e0:2e7c:8:eac0:6399:2385:bb6]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2984dbf121esm3481355ad.29.2025.11.11.09.52.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Nov 2025 09:52:51 -0800 (PST) From: Daeho Jeong To: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, kernel-team@android.com Cc: Daeho Jeong , Chao Yu Subject: [PATCH v7] f2fs: revert summary entry count from 2048 to 512 in 16kb block support Date: Tue, 11 Nov 2025 09:52:46 -0800 Message-ID: <20251111175246.17202-1-daeho43@gmail.com> X-Mailer: git-send-email 2.51.2.1041.gc1ab5b90ca-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Daeho Jeong The recent increase in the number of Segment Summary Area (SSA) entries from 512 to 2048 was an unintentional change in logic of 16kb block support. This commit corrects the issue. To better utilize the space available from the erroneous 2048-entry calculation, we are implementing a solution to share the currently unused SSA space with neighboring segments. This enhances overall SSA utilization without impacting the established 8MB segment size. Fixes: d7e9a9037de2 ("f2fs: Support Block Size =3D=3D Page Size") Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu --- v7: maintain the old flow in f2fs_update_meta_page() for better performance for 4k blocks. v6: make it follow the old flow for 4k block in write_sum_page() v5: add the feature to sysfs feature and feature_list v4: add a feature to prevent from mounting deprecated format v3: error handling for a failure of f2fs_get_meta_folio(). v2: detect legacy layout and prevent mount. --- fs/f2fs/f2fs.h | 2 + fs/f2fs/gc.c | 117 +++++++++++++++++++++++----------------- fs/f2fs/recovery.c | 2 +- fs/f2fs/segment.c | 38 +++++++++---- fs/f2fs/segment.h | 8 ++- fs/f2fs/super.c | 14 +++++ fs/f2fs/sysfs.c | 7 +++ include/linux/f2fs_fs.h | 5 +- 8 files changed, 130 insertions(+), 63 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b6e35fdd5fd3..c851364de529 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -245,6 +245,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_COMPRESSION 0x00002000 #define F2FS_FEATURE_RO 0x00004000 #define F2FS_FEATURE_DEVICE_ALIAS 0x00008000 +#define F2FS_FEATURE_PACKED_SSA 0x00010000 =20 #define __F2FS_HAS_FEATURE(raw_super, mask) \ ((raw_super->feature & cpu_to_le32(mask)) !=3D 0) @@ -4710,6 +4711,7 @@ F2FS_FEATURE_FUNCS(casefold, CASEFOLD); F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); +F2FS_FEATURE_FUNCS(packed_ssa, PACKED_SSA); =20 #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_zone_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 8abf521530ff..af2f4d28462c 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1732,7 +1732,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sb= i, unsigned char type =3D IS_DATASEG(get_seg_entry(sbi, segno)->type) ? SUM_TYPE_DATA : SUM_TYPE_NODE; unsigned char data_type =3D (type =3D=3D SUM_TYPE_DATA) ? DATA : NODE; - int submitted =3D 0; + int submitted =3D 0, sum_blk_cnt; =20 if (__is_large_section(sbi)) { sec_end_segno =3D rounddown(end_segno, SEGS_PER_SEC(sbi)); @@ -1766,22 +1766,28 @@ static int do_garbage_collect(struct f2fs_sb_info *= sbi, =20 sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); =20 + segno =3D rounddown(segno, SUMS_PER_BLOCK); + sum_blk_cnt =3D DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK); /* readahead multi ssa blocks those have contiguous address */ if (__is_large_section(sbi)) f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno), - end_segno - segno, META_SSA, true); + sum_blk_cnt, META_SSA, true); =20 /* reference all summary page */ while (segno < end_segno) { - struct folio *sum_folio =3D f2fs_get_sum_folio(sbi, segno++); + struct folio *sum_folio =3D f2fs_get_sum_folio(sbi, segno); + + segno +=3D SUMS_PER_BLOCK; if (IS_ERR(sum_folio)) { int err =3D PTR_ERR(sum_folio); =20 - end_segno =3D segno - 1; - for (segno =3D start_segno; segno < end_segno; segno++) { + end_segno =3D segno - SUMS_PER_BLOCK; + segno =3D rounddown(start_segno, SUMS_PER_BLOCK); + while (segno < end_segno) { sum_folio =3D filemap_get_folio(META_MAPPING(sbi), GET_SUM_BLOCK(sbi, segno)); folio_put_refs(sum_folio, 2); + segno +=3D SUMS_PER_BLOCK; } return err; } @@ -1790,68 +1796,83 @@ static int do_garbage_collect(struct f2fs_sb_info *= sbi, =20 blk_start_plug(&plug); =20 - for (segno =3D start_segno; segno < end_segno; segno++) { - struct f2fs_summary_block *sum; + segno =3D start_segno; + while (segno < end_segno) { + unsigned int cur_segno; =20 /* find segment summary of victim */ struct folio *sum_folio =3D filemap_get_folio(META_MAPPING(sbi), GET_SUM_BLOCK(sbi, segno)); + unsigned int block_end_segno =3D rounddown(segno, SUMS_PER_BLOCK) + + SUMS_PER_BLOCK; + + if (block_end_segno > end_segno) + block_end_segno =3D end_segno; =20 if (is_cursec(sbi, GET_SEC_FROM_SEG(sbi, segno))) { f2fs_err(sbi, "%s: segment %u is used by log", __func__, segno); f2fs_bug_on(sbi, 1); - goto skip; + goto next_block; } =20 - if (get_valid_blocks(sbi, segno, false) =3D=3D 0) - goto freed; - if (gc_type =3D=3D BG_GC && __is_large_section(sbi) && - migrated >=3D sbi->migration_granularity) - goto skip; if (!folio_test_uptodate(sum_folio) || unlikely(f2fs_cp_error(sbi))) - goto skip; + goto next_block; =20 - sum =3D folio_address(sum_folio); - if (type !=3D GET_SUM_TYPE((&sum->footer))) { - f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SIT and SSA", - segno, type, GET_SUM_TYPE((&sum->footer))); - f2fs_stop_checkpoint(sbi, false, - STOP_CP_REASON_CORRUPTED_SUMMARY); - goto skip; - } + for (cur_segno =3D segno; cur_segno < block_end_segno; + cur_segno++) { + struct f2fs_summary_block *sum; =20 - /* - * this is to avoid deadlock: - * - lock_page(sum_page) - f2fs_replace_block - * - check_valid_map() - down_write(sentry_lock) - * - down_read(sentry_lock) - change_curseg() - * - lock_page(sum_page) - */ - if (type =3D=3D SUM_TYPE_NODE) - submitted +=3D gc_node_segment(sbi, sum->entries, segno, - gc_type); - else - submitted +=3D gc_data_segment(sbi, sum->entries, gc_list, - segno, gc_type, - force_migrate); + if (get_valid_blocks(sbi, cur_segno, false) =3D=3D 0) + goto freed; + if (gc_type =3D=3D BG_GC && __is_large_section(sbi) && + migrated >=3D sbi->migration_granularity) + continue; =20 - stat_inc_gc_seg_count(sbi, data_type, gc_type); - sbi->gc_reclaimed_segs[sbi->gc_mode]++; - migrated++; + sum =3D SUM_BLK_PAGE_ADDR(sum_folio, cur_segno); + if (type !=3D GET_SUM_TYPE((&sum->footer))) { + f2fs_err(sbi, "Inconsistent segment (%u) type " + "[%d, %d] in SSA and SIT", + cur_segno, type, + GET_SUM_TYPE((&sum->footer))); + f2fs_stop_checkpoint(sbi, false, + STOP_CP_REASON_CORRUPTED_SUMMARY); + continue; + } =20 -freed: - if (gc_type =3D=3D FG_GC && - get_valid_blocks(sbi, segno, false) =3D=3D 0) - seg_freed++; + /* + * this is to avoid deadlock: + * - lock_page(sum_page) - f2fs_replace_block + * - check_valid_map() - down_write(sentry_lock) + * - down_read(sentry_lock) - change_curseg() + * - lock_page(sum_page) + */ + if (type =3D=3D SUM_TYPE_NODE) + submitted +=3D gc_node_segment(sbi, sum->entries, + cur_segno, gc_type); + else + submitted +=3D gc_data_segment(sbi, sum->entries, + gc_list, cur_segno, + gc_type, force_migrate); =20 - if (__is_large_section(sbi)) - sbi->next_victim_seg[gc_type] =3D - (segno + 1 < sec_end_segno) ? - segno + 1 : NULL_SEGNO; -skip: + stat_inc_gc_seg_count(sbi, data_type, gc_type); + sbi->gc_reclaimed_segs[sbi->gc_mode]++; + migrated++; + +freed: + if (gc_type =3D=3D FG_GC && + get_valid_blocks(sbi, cur_segno, false) =3D=3D 0) + seg_freed++; + + if (__is_large_section(sbi)) + sbi->next_victim_seg[gc_type] =3D + (cur_segno + 1 < sec_end_segno) ? + cur_segno + 1 : NULL_SEGNO; + } +next_block: folio_put_refs(sum_folio, 2); + segno =3D block_end_segno; } =20 if (submitted) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 215e442db72c..af72309b9bfc 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -519,7 +519,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_inf= o *sbi, sum_folio =3D f2fs_get_sum_folio(sbi, segno); if (IS_ERR(sum_folio)) return PTR_ERR(sum_folio); - sum_node =3D folio_address(sum_folio); + sum_node =3D SUM_BLK_PAGE_ADDR(sum_folio, segno); sum =3D sum_node->entries[blkoff]; f2fs_folio_put(sum_folio, true); got_it: diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index b45eace879d7..ac84559dc269 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2712,7 +2712,15 @@ struct folio *f2fs_get_sum_folio(struct f2fs_sb_info= *sbi, unsigned int segno) void f2fs_update_meta_page(struct f2fs_sb_info *sbi, void *src, block_t blk_addr) { - struct folio *folio =3D f2fs_grab_meta_folio(sbi, blk_addr); + struct folio *folio; + + if (SUMS_PER_BLOCK =3D=3D 1) + folio =3D f2fs_grab_meta_folio(sbi, blk_addr); + else + folio =3D f2fs_get_meta_folio_retry(sbi, blk_addr); + + if (IS_ERR(folio)) + return; =20 memcpy(folio_address(folio), src, PAGE_SIZE); folio_mark_dirty(folio); @@ -2720,9 +2728,21 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi, } =20 static void write_sum_page(struct f2fs_sb_info *sbi, - struct f2fs_summary_block *sum_blk, block_t blk_addr) + struct f2fs_summary_block *sum_blk, unsigned int segno) { - f2fs_update_meta_page(sbi, (void *)sum_blk, blk_addr); + struct folio *folio; + + if (SUMS_PER_BLOCK =3D=3D 1) + return f2fs_update_meta_page(sbi, (void *)sum_blk, + GET_SUM_BLOCK(sbi, segno)); + + folio =3D f2fs_get_sum_folio(sbi, segno); + if (IS_ERR(folio)) + return; + + memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk)); + folio_mark_dirty(folio); + f2fs_folio_put(folio, true); } =20 static void write_current_sum_page(struct f2fs_sb_info *sbi, @@ -2987,7 +3007,7 @@ static int new_curseg(struct f2fs_sb_info *sbi, int t= ype, bool new_sec) int ret; =20 if (curseg->inited) - write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno)); + write_sum_page(sbi, curseg->sum_blk, segno); =20 segno =3D __get_next_segno(sbi, type); ret =3D get_new_segment(sbi, &segno, new_sec, pinning); @@ -3046,7 +3066,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, in= t type) struct folio *sum_folio; =20 if (curseg->inited) - write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno)); + write_sum_page(sbi, curseg->sum_blk, curseg->segno); =20 __set_test_and_inuse(sbi, new_segno); =20 @@ -3065,7 +3085,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, in= t type) memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE); return PTR_ERR(sum_folio); } - sum_node =3D folio_address(sum_folio); + sum_node =3D SUM_BLK_PAGE_ADDR(sum_folio, new_segno); memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); f2fs_folio_put(sum_folio, true); return 0; @@ -3154,8 +3174,7 @@ static void __f2fs_save_inmem_curseg(struct f2fs_sb_i= nfo *sbi, int type) goto out; =20 if (get_valid_blocks(sbi, curseg->segno, false)) { - write_sum_page(sbi, curseg->sum_blk, - GET_SUM_BLOCK(sbi, curseg->segno)); + write_sum_page(sbi, curseg->sum_blk, curseg->segno); } else { mutex_lock(&DIRTY_I(sbi)->seglist_lock); __set_test_and_free(sbi, curseg->segno, true); @@ -3833,8 +3852,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi= , struct folio *folio, if (segment_full) { if (type =3D=3D CURSEG_COLD_DATA_PINNED && !((curseg->segno + 1) % sbi->segs_per_sec)) { - write_sum_page(sbi, curseg->sum_blk, - GET_SUM_BLOCK(sbi, curseg->segno)); + write_sum_page(sbi, curseg->sum_blk, curseg->segno); reset_curseg_fields(curseg); goto skip_new_segment; } diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 1ce2c8abaf48..e883f14c228f 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -85,8 +85,12 @@ static inline void sanity_check_seg_type(struct f2fs_sb_= info *sbi, #define GET_ZONE_FROM_SEG(sbi, segno) \ GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno)) =20 -#define GET_SUM_BLOCK(sbi, segno) \ - ((sbi)->sm_info->ssa_blkaddr + (segno)) +#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE) +#define GET_SUM_BLOCK(sbi, segno) \ + (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK)) +#define GET_SUM_BLKOFF(segno) (segno % SUMS_PER_BLOCK) +#define SUM_BLK_PAGE_ADDR(folio, segno) \ + (folio_address(folio) + GET_SUM_BLKOFF(segno) * F2FS_SUM_BLKSIZE) =20 #define GET_SUM_TYPE(footer) ((footer)->entry_type) #define SET_SUM_TYPE(footer, type) ((footer)->entry_type =3D (type)) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 6e52e36c1f1a..707e24551fdd 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4052,6 +4052,20 @@ static int sanity_check_raw_super(struct f2fs_sb_inf= o *sbi, if (sanity_check_area_boundary(sbi, folio, index)) return -EFSCORRUPTED; =20 + /* + * Check for legacy summary layout on 16KB+ block devices. + * Modern f2fs-tools packs multiple 4KB summary areas into one block, + * whereas legacy versions used one block per summary, leading + * to a much larger SSA. + */ + if (SUMS_PER_BLOCK > 1 && + !(__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_PACKED_SSA))) { + f2fs_info(sbi, "Error: Device formatted with a legacy version. " + "Please reformat with a tool supporting the packed ssa " + "feature for block sizes larger than 4kb."); + return -EOPNOTSUPP; + } + return 0; } =20 diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6d2a4fba68a2..5685b454bfd1 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -235,6 +235,9 @@ static ssize_t features_show(struct f2fs_attr *a, if (f2fs_sb_has_compression(sbi)) len +=3D sysfs_emit_at(buf, len, "%s%s", len ? ", " : "", "compression"); + if (f2fs_sb_has_packed_ssa(sbi)) + len +=3D sysfs_emit_at(buf, len, "%s%s", + len ? ", " : "", "packed_ssa"); len +=3D sysfs_emit_at(buf, len, "%s%s", len ? ", " : "", "pin_file"); len +=3D sysfs_emit_at(buf, len, "\n"); @@ -1296,6 +1299,7 @@ F2FS_FEATURE_RO_ATTR(pin_file); #ifdef CONFIG_UNICODE F2FS_FEATURE_RO_ATTR(linear_lookup); #endif +F2FS_FEATURE_RO_ATTR(packed_ssa); =20 #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] =3D { @@ -1455,6 +1459,7 @@ static struct attribute *f2fs_feat_attrs[] =3D { #ifdef CONFIG_UNICODE BASE_ATTR_LIST(linear_lookup), #endif + BASE_ATTR_LIST(packed_ssa), NULL, }; ATTRIBUTE_GROUPS(f2fs_feat); @@ -1490,6 +1495,7 @@ F2FS_SB_FEATURE_RO_ATTR(casefold, CASEFOLD); F2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION); F2FS_SB_FEATURE_RO_ATTR(readonly, RO); F2FS_SB_FEATURE_RO_ATTR(device_alias, DEVICE_ALIAS); +F2FS_SB_FEATURE_RO_ATTR(packed_ssa, PACKED_SSA); =20 static struct attribute *f2fs_sb_feat_attrs[] =3D { ATTR_LIST(sb_encryption), @@ -1507,6 +1513,7 @@ static struct attribute *f2fs_sb_feat_attrs[] =3D { ATTR_LIST(sb_compression), ATTR_LIST(sb_readonly), ATTR_LIST(sb_device_alias), + ATTR_LIST(sb_packed_ssa), NULL, }; ATTRIBUTE_GROUPS(f2fs_sb_feat); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 6afb4a13b81d..a7880787cad3 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -17,6 +17,7 @@ #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sect= or/blk */ #define F2FS_BLKSIZE PAGE_SIZE /* support only block =3D=3D page */ #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ +#define F2FS_SUM_BLKSIZE 4096 /* only support 4096 byte sum block */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ #define F2FS_EXTENSION_LEN 8 /* max size of extension */ =20 @@ -441,7 +442,7 @@ struct f2fs_sit_block { * from node's page's beginning to get a data block address. * ex) data_blkaddr =3D (block_t)(nodepage_start_address + ofs_in_node) */ -#define ENTRIES_IN_SUM (F2FS_BLKSIZE / 8) +#define ENTRIES_IN_SUM (F2FS_SUM_BLKSIZE / 8) #define SUMMARY_SIZE (7) /* sizeof(struct f2fs_summary) */ #define SUM_FOOTER_SIZE (5) /* sizeof(struct summary_footer) */ #define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) @@ -467,7 +468,7 @@ struct summary_footer { __le32 check_sum; /* summary checksum */ } __packed; =20 -#define SUM_JOURNAL_SIZE (F2FS_BLKSIZE - SUM_FOOTER_SIZE -\ +#define SUM_JOURNAL_SIZE (F2FS_SUM_BLKSIZE - SUM_FOOTER_SIZE -\ SUM_ENTRY_SIZE) #define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\ sizeof(struct nat_journal_entry)) --=20 2.51.2.1041.gc1ab5b90ca-goog