fs/f2fs/f2fs.h | 56 +++++++++++++++++++-------- fs/f2fs/gc.c | 23 +++++------ fs/f2fs/node.c | 12 +++--- fs/f2fs/recovery.c | 6 +-- fs/f2fs/segment.c | 86 ++++++++++++++++++++++------------------- fs/f2fs/segment.h | 10 ++--- fs/f2fs/super.c | 14 ------- include/linux/f2fs_fs.h | 73 ++++++++++++++++++++-------------- 8 files changed, 157 insertions(+), 123 deletions(-)
From: Daeho Jeong <daehojeong@google.com>
Currently, F2FS requires the packed_ssa feature to be enabled when
utilizing non-4KB block sizes (e.g., 16KB). This restriction limits
the flexibility of filesystem formatting options.
This patch allows F2FS to support non-4KB block sizes even when the
packed_ssa feature is disabled. It adjusts the SSA calculation logic to
correctly handle summary entries in larger blocks without the packed
layout.
Fixes: 7ee8bc3942f2 ("f2fs: revert summary entry count from 2048 to 512 in 16kb block support")
Signed-off-by: Daeho Jeong <daehojeong@google.com>
---
fs/f2fs/f2fs.h | 56 +++++++++++++++++++--------
fs/f2fs/gc.c | 23 +++++------
fs/f2fs/node.c | 12 +++---
fs/f2fs/recovery.c | 6 +--
fs/f2fs/segment.c | 86 ++++++++++++++++++++++-------------------
fs/f2fs/segment.h | 10 ++---
fs/f2fs/super.c | 14 -------
include/linux/f2fs_fs.h | 73 ++++++++++++++++++++--------------
8 files changed, 157 insertions(+), 123 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 20edbb99b814..0ceae7d83a48 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -521,13 +521,36 @@ struct fsync_inode_entry {
#define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats))
#define sits_in_cursum(jnl) (le16_to_cpu((jnl)->n_sits))
-#define nat_in_journal(jnl, i) ((jnl)->nat_j.entries[i].ne)
-#define nid_in_journal(jnl, i) ((jnl)->nat_j.entries[i].nid)
-#define sit_in_journal(jnl, i) ((jnl)->sit_j.entries[i].se)
-#define segno_in_journal(jnl, i) ((jnl)->sit_j.entries[i].segno)
-
-#define MAX_NAT_JENTRIES(jnl) (NAT_JOURNAL_ENTRIES - nats_in_cursum(jnl))
-#define MAX_SIT_JENTRIES(jnl) (SIT_JOURNAL_ENTRIES - sits_in_cursum(jnl))
+#define nat_in_journal(jnl, i) \
+ (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].ne)
+#define nid_in_journal(jnl, i) \
+ (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].nid)
+#define sit_in_journal(jnl, i) \
+ (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].se)
+#define segno_in_journal(jnl, i) \
+ (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].segno)
+
+#define F2FS_SUM_BLKSIZE(sbi) \
+ (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_PACKED_SSA) ? 4096 : (sbi)->blocksize)
+#define ENTRIES_IN_SUM(sbi) (F2FS_SUM_BLKSIZE(sbi) / 8)
+#define SUM_ENTRY_SIZE(sbi) (SUMMARY_SIZE * ENTRIES_IN_SUM(sbi))
+#define SUM_JOURNAL_SIZE(sbi) (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE - \
+ SUM_ENTRY_SIZE(sbi))
+#define NAT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
+ sizeof(struct nat_journal_entry))
+#define SIT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
+ sizeof(struct sit_journal_entry))
+
+#define sum_entries(sum) ((struct f2fs_summary *)(sum))
+#define sum_journal(sbi, sum) \
+ ((struct f2fs_journal *)((char *)(sum) + \
+ (ENTRIES_IN_SUM(sbi) * sizeof(struct f2fs_summary))))
+#define sum_footer(sbi, sum) \
+ ((struct summary_footer *)((char *)(sum) + F2FS_SUM_BLKSIZE(sbi) - \
+ sizeof(struct summary_footer)))
+
+#define MAX_NAT_JENTRIES(sbi, jnl) (NAT_JOURNAL_ENTRIES(sbi) - nats_in_cursum(jnl))
+#define MAX_SIT_JENTRIES(sbi, jnl) (SIT_JOURNAL_ENTRIES(sbi) - sits_in_cursum(jnl))
static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i)
{
@@ -545,14 +568,6 @@ static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i)
return before;
}
-static inline bool __has_cursum_space(struct f2fs_journal *journal,
- int size, int type)
-{
- if (type == NAT_JOURNAL)
- return size <= MAX_NAT_JENTRIES(journal);
- return size <= MAX_SIT_JENTRIES(journal);
-}
-
/* for inline stuff */
#define DEF_INLINE_RESERVED_SIZE 1
static inline int get_extra_isize(struct inode *inode);
@@ -2813,6 +2828,14 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
}
+static inline bool __has_cursum_space(struct f2fs_sb_info *sbi,
+ struct f2fs_journal *journal, int size, int type)
+{
+ if (type == NAT_JOURNAL)
+ return size <= MAX_NAT_JENTRIES(sbi, journal);
+ return size <= MAX_SIT_JENTRIES(sbi, journal);
+}
+
extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync);
static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
struct inode *inode, bool is_inode)
@@ -3956,7 +3979,8 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
block_t len);
void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
-int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
+int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
+ struct f2fs_journal *journal, int type,
unsigned int val, int alloc);
void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
int f2fs_check_and_fix_write_pointer(struct f2fs_sb_info *sbi);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 384fa7e2085b..65c819d08807 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1769,8 +1769,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
- segno = rounddown(segno, SUMS_PER_BLOCK);
- sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK);
+ segno = rounddown(segno, SUMS_PER_BLOCK(sbi));
+ sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK(sbi));
/* readahead multi ssa blocks those have contiguous address */
if (__is_large_section(sbi))
f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
@@ -1780,17 +1780,17 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
while (segno < end_segno) {
struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
- segno += SUMS_PER_BLOCK;
+ segno += SUMS_PER_BLOCK(sbi);
if (IS_ERR(sum_folio)) {
int err = PTR_ERR(sum_folio);
- end_segno = segno - SUMS_PER_BLOCK;
- segno = rounddown(start_segno, SUMS_PER_BLOCK);
+ end_segno = segno - SUMS_PER_BLOCK(sbi);
+ segno = rounddown(start_segno, SUMS_PER_BLOCK(sbi));
while (segno < end_segno) {
sum_folio = filemap_get_folio(META_MAPPING(sbi),
GET_SUM_BLOCK(sbi, segno));
folio_put_refs(sum_folio, 2);
- segno += SUMS_PER_BLOCK;
+ segno += SUMS_PER_BLOCK(sbi);
}
return err;
}
@@ -1806,8 +1806,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
/* find segment summary of victim */
struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
GET_SUM_BLOCK(sbi, segno));
- unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK)
- + SUMS_PER_BLOCK;
+ unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK(sbi))
+ + SUMS_PER_BLOCK(sbi);
if (block_end_segno > end_segno)
block_end_segno = end_segno;
@@ -1833,12 +1833,13 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
migrated >= sbi->migration_granularity)
continue;
- sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno);
- if (type != GET_SUM_TYPE((&sum->footer))) {
+ 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 "
"[%d, %d] in SSA and SIT",
cur_segno, type,
- GET_SUM_TYPE((&sum->footer)));
+ GET_SUM_TYPE(
+ sum_footer(sbi, sum)));
f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_CORRUPTED_SUMMARY);
continue;
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 482a362f2625..f78d53ec59d4 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -606,7 +606,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
goto retry;
}
- i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
+ i = f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 0);
if (i >= 0) {
ne = nat_in_journal(journal, i);
node_info_from_raw_nat(ni, &ne);
@@ -2937,7 +2937,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
/* scan the node segment */
last_offset = BLKS_PER_SEG(sbi);
addr = START_BLOCK(sbi, segno);
- sum_entry = &sum->entries[0];
+ sum_entry = sum_entries(sum);
for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
nrpages = bio_max_segs(last_offset - i);
@@ -3078,7 +3078,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
* #2, flush nat entries to nat page.
*/
if (enabled_nat_bits(sbi, cpc) ||
- !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
+ !__has_cursum_space(sbi, journal, set->entry_cnt, NAT_JOURNAL))
to_journal = false;
if (to_journal) {
@@ -3101,7 +3101,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
if (to_journal) {
- offset = f2fs_lookup_journal_in_cursum(journal,
+ offset = f2fs_lookup_journal_in_cursum(sbi, journal,
NAT_JOURNAL, nid, 1);
f2fs_bug_on(sbi, offset < 0);
raw_ne = &nat_in_journal(journal, offset);
@@ -3172,7 +3172,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
* into nat entry set.
*/
if (enabled_nat_bits(sbi, cpc) ||
- !__has_cursum_space(journal,
+ !__has_cursum_space(sbi, journal,
nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
remove_nats_in_journal(sbi);
@@ -3183,7 +3183,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
set_idx = setvec[found - 1]->set + 1;
for (idx = 0; idx < found; idx++)
__adjust_nat_entry_set(setvec[idx], &sets,
- MAX_NAT_JENTRIES(journal));
+ MAX_NAT_JENTRIES(sbi, journal));
}
/* flush dirty nats in nat entry set */
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index c3415ebb9f50..a6bfc8e759cf 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -514,7 +514,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
struct curseg_info *curseg = CURSEG_I(sbi, i);
if (curseg->segno == segno) {
- sum = curseg->sum_blk->entries[blkoff];
+ sum = sum_entries(curseg->sum_blk)[blkoff];
goto got_it;
}
}
@@ -522,8 +522,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
sum_folio = f2fs_get_sum_folio(sbi, segno);
if (IS_ERR(sum_folio))
return PTR_ERR(sum_folio);
- sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno);
- sum = sum_node->entries[blkoff];
+ sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno);
+ sum = sum_entries(sum_node)[blkoff];
f2fs_folio_put(sum_folio, true);
got_it:
/* Use the locked dnode page and inode */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c26424f47686..9a73b979b2e6 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2685,12 +2685,12 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
valid_sum_count += f2fs_curseg_valid_blocks(sbi, i);
}
- sum_in_page = (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE -
+ sum_in_page = (F2FS_SUM_BLKSIZE(sbi) - 2 * SUM_JOURNAL_SIZE(sbi) -
SUM_FOOTER_SIZE) / SUMMARY_SIZE;
if (valid_sum_count <= sum_in_page)
return 1;
else if ((valid_sum_count - sum_in_page) <=
- (PAGE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
+ (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
return 2;
return 3;
}
@@ -2710,7 +2710,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
{
struct folio *folio;
- if (SUMS_PER_BLOCK == 1)
+ if (!f2fs_sb_has_packed_ssa(sbi))
folio = f2fs_grab_meta_folio(sbi, blk_addr);
else
folio = f2fs_get_meta_folio_retry(sbi, blk_addr);
@@ -2728,7 +2728,7 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
{
struct folio *folio;
- if (SUMS_PER_BLOCK == 1)
+ if (!f2fs_sb_has_packed_ssa(sbi))
return f2fs_update_meta_page(sbi, (void *)sum_blk,
GET_SUM_BLOCK(sbi, segno));
@@ -2736,7 +2736,8 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
if (IS_ERR(folio))
return;
- memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk));
+ memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk,
+ F2FS_SUM_BLKSIZE(sbi));
folio_mark_dirty(folio);
f2fs_folio_put(folio, true);
}
@@ -2755,11 +2756,11 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi,
mutex_lock(&curseg->curseg_mutex);
down_read(&curseg->journal_rwsem);
- memcpy(&dst->journal, curseg->journal, SUM_JOURNAL_SIZE);
+ memcpy(sum_journal(sbi, dst), curseg->journal, SUM_JOURNAL_SIZE(sbi));
up_read(&curseg->journal_rwsem);
- memcpy(dst->entries, src->entries, SUM_ENTRY_SIZE);
- memcpy(&dst->footer, &src->footer, SUM_FOOTER_SIZE);
+ memcpy(sum_entries(dst), sum_entries(src), SUM_ENTRY_SIZE(sbi));
+ memcpy(sum_footer(sbi, dst), sum_footer(sbi, src), SUM_FOOTER_SIZE);
mutex_unlock(&curseg->curseg_mutex);
@@ -2932,7 +2933,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
curseg->next_blkoff = 0;
curseg->next_segno = NULL_SEGNO;
- sum_footer = &(curseg->sum_blk->footer);
+ sum_footer = sum_footer(sbi, curseg->sum_blk);
memset(sum_footer, 0, sizeof(struct summary_footer));
sanity_check_seg_type(sbi, seg_type);
@@ -3078,11 +3079,11 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
sum_folio = f2fs_get_sum_folio(sbi, new_segno);
if (IS_ERR(sum_folio)) {
/* GC won't be able to use stale summary pages by cp_error */
- memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE);
+ memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE(sbi));
return PTR_ERR(sum_folio);
}
- sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno);
- memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
+ sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno);
+ memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE(sbi));
f2fs_folio_put(sum_folio, true);
return 0;
}
@@ -3814,7 +3815,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio,
f2fs_wait_discard_bio(sbi, *new_blkaddr);
- curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
+ sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
if (curseg->alloc_type == SSR) {
curseg->next_blkoff = f2fs_find_next_ssr_block(sbi, curseg);
} else {
@@ -4183,7 +4184,7 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
}
curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
- curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
+ sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
if (!recover_curseg || recover_newaddr) {
if (!from_gc)
@@ -4303,12 +4304,12 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
/* Step 1: restore nat cache */
seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
- memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE);
+ memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE(sbi));
/* Step 2: restore sit cache */
seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
- memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE);
- offset = 2 * SUM_JOURNAL_SIZE;
+ memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE(sbi), SUM_JOURNAL_SIZE(sbi));
+ offset = 2 * SUM_JOURNAL_SIZE(sbi);
/* Step 3: restore summary entries */
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
@@ -4330,9 +4331,9 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
struct f2fs_summary *s;
s = (struct f2fs_summary *)(kaddr + offset);
- seg_i->sum_blk->entries[j] = *s;
+ sum_entries(seg_i->sum_blk)[j] = *s;
offset += SUMMARY_SIZE;
- if (offset + SUMMARY_SIZE <= PAGE_SIZE -
+ if (offset + SUMMARY_SIZE <= F2FS_SUM_BLKSIZE(sbi) -
SUM_FOOTER_SIZE)
continue;
@@ -4388,7 +4389,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
if (IS_NODESEG(type)) {
if (__exist_node_summaries(sbi)) {
- struct f2fs_summary *ns = &sum->entries[0];
+ struct f2fs_summary *ns = sum_entries(sum);
int i;
for (i = 0; i < BLKS_PER_SEG(sbi); i++, ns++) {
@@ -4408,11 +4409,13 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
/* update journal info */
down_write(&curseg->journal_rwsem);
- memcpy(curseg->journal, &sum->journal, SUM_JOURNAL_SIZE);
+ memcpy(curseg->journal, sum_journal(sbi, sum), SUM_JOURNAL_SIZE(sbi));
up_write(&curseg->journal_rwsem);
- memcpy(curseg->sum_blk->entries, sum->entries, SUM_ENTRY_SIZE);
- memcpy(&curseg->sum_blk->footer, &sum->footer, SUM_FOOTER_SIZE);
+ memcpy(sum_entries(curseg->sum_blk), sum_entries(sum),
+ SUM_ENTRY_SIZE(sbi));
+ memcpy(sum_footer(sbi, curseg->sum_blk), sum_footer(sbi, sum),
+ SUM_FOOTER_SIZE);
curseg->next_segno = segno;
reset_curseg(sbi, type, 0);
curseg->alloc_type = ckpt->alloc_type[type];
@@ -4456,8 +4459,8 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
}
/* sanity check for summary blocks */
- if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES ||
- sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) {
+ if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES(sbi) ||
+ sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES(sbi)) {
f2fs_err(sbi, "invalid journal entries nats %u sits %u",
nats_in_cursum(nat_j), sits_in_cursum(sit_j));
return -EINVAL;
@@ -4481,13 +4484,13 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
/* Step 1: write nat cache */
seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
- memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE);
- written_size += SUM_JOURNAL_SIZE;
+ memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
+ written_size += SUM_JOURNAL_SIZE(sbi);
/* Step 2: write sit cache */
seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
- memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE);
- written_size += SUM_JOURNAL_SIZE;
+ memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
+ written_size += SUM_JOURNAL_SIZE(sbi);
/* Step 3: write summary entries */
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
@@ -4500,7 +4503,7 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
written_size = 0;
}
summary = (struct f2fs_summary *)(kaddr + written_size);
- *summary = seg_i->sum_blk->entries[j];
+ *summary = sum_entries(seg_i->sum_blk)[j];
written_size += SUMMARY_SIZE;
if (written_size + SUMMARY_SIZE <= PAGE_SIZE -
@@ -4545,8 +4548,9 @@ void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
}
-int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
- unsigned int val, int alloc)
+int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
+ struct f2fs_journal *journal, int type,
+ unsigned int val, int alloc)
{
int i;
@@ -4555,13 +4559,13 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
if (le32_to_cpu(nid_in_journal(journal, i)) == val)
return i;
}
- if (alloc && __has_cursum_space(journal, 1, NAT_JOURNAL))
+ if (alloc && __has_cursum_space(sbi, journal, 1, NAT_JOURNAL))
return update_nats_in_cursum(journal, 1);
} else if (type == SIT_JOURNAL) {
for (i = 0; i < sits_in_cursum(journal); i++)
if (le32_to_cpu(segno_in_journal(journal, i)) == val)
return i;
- if (alloc && __has_cursum_space(journal, 1, SIT_JOURNAL))
+ if (alloc && __has_cursum_space(sbi, journal, 1, SIT_JOURNAL))
return update_sits_in_cursum(journal, 1);
}
return -1;
@@ -4709,8 +4713,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
* entries, remove all entries from journal and add and account
* them in sit entry set.
*/
- if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL) ||
- !to_journal)
+ if (!__has_cursum_space(sbi, journal,
+ sit_i->dirty_sentries, SIT_JOURNAL) || !to_journal)
remove_sits_in_journal(sbi);
/*
@@ -4727,7 +4731,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
unsigned int segno = start_segno;
if (to_journal &&
- !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL))
+ !__has_cursum_space(sbi, journal, ses->entry_cnt,
+ SIT_JOURNAL))
to_journal = false;
if (to_journal) {
@@ -4755,7 +4760,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
}
if (to_journal) {
- offset = f2fs_lookup_journal_in_cursum(journal,
+ offset = f2fs_lookup_journal_in_cursum(sbi, journal,
SIT_JOURNAL, segno, 1);
f2fs_bug_on(sbi, offset < 0);
segno_in_journal(journal, offset) =
@@ -4962,12 +4967,13 @@ static int build_curseg(struct f2fs_sb_info *sbi)
for (i = 0; i < NO_CHECK_TYPE; i++) {
mutex_init(&array[i].curseg_mutex);
- array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
+ array[i].sum_blk = f2fs_kzalloc(sbi, F2FS_SUM_BLKSIZE(sbi),
+ GFP_KERNEL);
if (!array[i].sum_blk)
return -ENOMEM;
init_rwsem(&array[i].journal_rwsem);
array[i].journal = f2fs_kzalloc(sbi,
- sizeof(struct f2fs_journal), GFP_KERNEL);
+ SUM_JOURNAL_SIZE(sbi), GFP_KERNEL);
if (!array[i].journal)
return -ENOMEM;
array[i].seg_type = log_type_to_seg_type(i);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 07dcbcbeb7c6..8b38f3693b1a 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -90,12 +90,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))
-#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE)
+#define SUMS_PER_BLOCK(sbi) ((sbi)->blocksize / F2FS_SUM_BLKSIZE(sbi))
#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)
+ (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK(sbi)))
+#define GET_SUM_BLKOFF(sbi, segno) (segno % SUMS_PER_BLOCK(sbi))
+#define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
+ (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * F2FS_SUM_BLKSIZE(sbi))
#define GET_SUM_TYPE(footer) ((footer)->entry_type)
#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index c4c225e09dc4..253a23a7b67d 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4080,20 +4080,6 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
if (sanity_check_area_boundary(sbi, folio, index))
return -EFSCORRUPTED;
- /*
- * 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;
}
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index a7880787cad3..394f7af3a102 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -17,7 +17,6 @@
#define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
#define F2FS_BLKSIZE PAGE_SIZE /* support only block == 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 */
@@ -442,10 +441,8 @@ struct f2fs_sit_block {
* from node's page's beginning to get a data block address.
* ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
*/
-#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)
/* a summary entry for a block in a segment */
struct f2fs_summary {
@@ -468,22 +465,6 @@ struct summary_footer {
__le32 check_sum; /* summary checksum */
} __packed;
-#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))
-#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
- sizeof(struct nat_journal_entry))
-#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
- sizeof(struct sit_journal_entry))
-#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
- sizeof(struct sit_journal_entry))
-
-/* Reserved area should make size of f2fs_extra_info equals to
- * that of nat_journal and sit_journal.
- */
-#define EXTRA_INFO_RESERVED (SUM_JOURNAL_SIZE - 2 - 8)
-
/*
* frequently updated NAT/SIT entries can be stored in the spare area in
* summary blocks
@@ -498,9 +479,16 @@ struct nat_journal_entry {
struct f2fs_nat_entry ne;
} __packed;
+/*
+ * The nat_journal structure is a placeholder whose actual size varies depending
+ * on the use of packed_ssa. Therefore, it must always be accessed only through
+ * specific sets of macros, and size calculations should use size-related macros
+ * instead of sizeof().
+ * Relevant macros: NAT_JOURNAL_ENTRIES, nat_in_journal, nid_in_journal,
+ * MAX_NAT_JENTRIES.
+ */
struct nat_journal {
- struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
- __u8 reserved[NAT_JOURNAL_RESERVED];
+ struct nat_journal_entry entries[0];
} __packed;
struct sit_journal_entry {
@@ -508,14 +496,21 @@ struct sit_journal_entry {
struct f2fs_sit_entry se;
} __packed;
+/*
+ * The sit_journal structure is a placeholder whose actual size varies depending
+ * on the use of packed_ssa. Therefore, it must always be accessed only through
+ * specific sets of macros, and size calculations should use size-related macros
+ * instead of sizeof().
+ * Relevant macros: SIT_JOURNAL_ENTRIES, sit_in_journal, segno_in_journal,
+ * MAX_SIT_JENTRIES.
+ */
struct sit_journal {
- struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
- __u8 reserved[SIT_JOURNAL_RESERVED];
+ struct sit_journal_entry entries[0];
} __packed;
struct f2fs_extra_info {
__le64 kbytes_written;
- __u8 reserved[EXTRA_INFO_RESERVED];
+ __u8 reserved[];
} __packed;
struct f2fs_journal {
@@ -531,11 +526,33 @@ struct f2fs_journal {
};
} __packed;
-/* Block-sized summary block structure */
+/*
+ * Block-sized summary block structure
+ *
+ * The f2fs_summary_block structure is a placeholder whose actual size varies
+ * depending on the use of packed_ssa. Therefore, it must always be accessed
+ * only through specific sets of macros, and size calculations should use
+ * size-related macros instead of sizeof().
+ * Relevant macros: F2FS_SUM_BLKSIZE, ENTRIES_IN_SUM, SUM_ENTRY_SIZE,
+ * sum_entries, sum_journal, sum_footer.
+ *
+ * Summary Block Layout
+ *
+ * +-----------------------+ <--- Block Start
+ * | struct f2fs_summary |
+ * | entries[0] |
+ * | ... |
+ * | entries[N-1] |
+ * +-----------------------+
+ * | struct f2fs_journal |
+ * +-----------------------+
+ * | struct summary_footer |
+ * +-----------------------+ <--- Block End
+ */
struct f2fs_summary_block {
- struct f2fs_summary entries[ENTRIES_IN_SUM];
- struct f2fs_journal journal;
- struct summary_footer footer;
+ struct f2fs_summary entries[0];
+ // struct f2fs_journal journal;
+ // struct summary_footer footer;
} __packed;
/*
--
2.52.0.351.gbe84eed79e-goog
On 1/8/2026 9:46 AM, Daeho Jeong wrote:
> From: Daeho Jeong <daehojeong@google.com>
>
> Currently, F2FS requires the packed_ssa feature to be enabled when
> utilizing non-4KB block sizes (e.g., 16KB). This restriction limits
> the flexibility of filesystem formatting options.
>
> This patch allows F2FS to support non-4KB block sizes even when the
> packed_ssa feature is disabled. It adjusts the SSA calculation logic to
> correctly handle summary entries in larger blocks without the packed
> layout.
Can we consider to add testcases into xfsqa to cover recent revert patch
and packed_ssa feature which changes disk layout a bit? not sure, we may
miss some corner cases in keep compatibility, e.g. mount old/new image w/
new kernel.
>
> Fixes: 7ee8bc3942f2 ("f2fs: revert summary entry count from 2048 to 512 in 16kb block support")
Cc: stable@kernel.org
> Signed-off-by: Daeho Jeong <daehojeong@google.com>
> ---
> fs/f2fs/f2fs.h | 56 +++++++++++++++++++--------
> fs/f2fs/gc.c | 23 +++++------
> fs/f2fs/node.c | 12 +++---
> fs/f2fs/recovery.c | 6 +--
> fs/f2fs/segment.c | 86 ++++++++++++++++++++++-------------------
> fs/f2fs/segment.h | 10 ++---
> fs/f2fs/super.c | 14 -------
> include/linux/f2fs_fs.h | 73 ++++++++++++++++++++--------------
> 8 files changed, 157 insertions(+), 123 deletions(-)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 20edbb99b814..0ceae7d83a48 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -521,13 +521,36 @@ struct fsync_inode_entry {
> #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats))
> #define sits_in_cursum(jnl) (le16_to_cpu((jnl)->n_sits))
>
> -#define nat_in_journal(jnl, i) ((jnl)->nat_j.entries[i].ne)
> -#define nid_in_journal(jnl, i) ((jnl)->nat_j.entries[i].nid)
> -#define sit_in_journal(jnl, i) ((jnl)->sit_j.entries[i].se)
> -#define segno_in_journal(jnl, i) ((jnl)->sit_j.entries[i].segno)
> -
> -#define MAX_NAT_JENTRIES(jnl) (NAT_JOURNAL_ENTRIES - nats_in_cursum(jnl))
> -#define MAX_SIT_JENTRIES(jnl) (SIT_JOURNAL_ENTRIES - sits_in_cursum(jnl))
> +#define nat_in_journal(jnl, i) \
> + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].ne)
> +#define nid_in_journal(jnl, i) \
> + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].nid)
> +#define sit_in_journal(jnl, i) \
> + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].se)
> +#define segno_in_journal(jnl, i) \
> + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].segno)
> +
> +#define F2FS_SUM_BLKSIZE(sbi) \
> + (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_PACKED_SSA) ? 4096 : (sbi)->blocksize)
What about caching F2FS_SUM_BLKSIZE() as sbi->sum_blksize to avoid rundandent
calculation in lots of places?
> +#define ENTRIES_IN_SUM(sbi) (F2FS_SUM_BLKSIZE(sbi) / 8)
> +#define SUM_ENTRY_SIZE(sbi) (SUMMARY_SIZE * ENTRIES_IN_SUM(sbi))
> +#define SUM_JOURNAL_SIZE(sbi) (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE - \
> + SUM_ENTRY_SIZE(sbi))
> +#define NAT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
> + sizeof(struct nat_journal_entry))
> +#define SIT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
> + sizeof(struct sit_journal_entry))
Ditto?
Thanks,
> +
> +#define sum_entries(sum) ((struct f2fs_summary *)(sum))
> +#define sum_journal(sbi, sum) \
> + ((struct f2fs_journal *)((char *)(sum) + \
> + (ENTRIES_IN_SUM(sbi) * sizeof(struct f2fs_summary))))
> +#define sum_footer(sbi, sum) \
> + ((struct summary_footer *)((char *)(sum) + F2FS_SUM_BLKSIZE(sbi) - \
> + sizeof(struct summary_footer)))
> +
> +#define MAX_NAT_JENTRIES(sbi, jnl) (NAT_JOURNAL_ENTRIES(sbi) - nats_in_cursum(jnl))
> +#define MAX_SIT_JENTRIES(sbi, jnl) (SIT_JOURNAL_ENTRIES(sbi) - sits_in_cursum(jnl))
>
> static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i)
> {
> @@ -545,14 +568,6 @@ static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i)
> return before;
> }
>
> -static inline bool __has_cursum_space(struct f2fs_journal *journal,
> - int size, int type)
> -{
> - if (type == NAT_JOURNAL)
> - return size <= MAX_NAT_JENTRIES(journal);
> - return size <= MAX_SIT_JENTRIES(journal);
> -}
> -
> /* for inline stuff */
> #define DEF_INLINE_RESERVED_SIZE 1
> static inline int get_extra_isize(struct inode *inode);
> @@ -2813,6 +2828,14 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
> return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
> }
>
> +static inline bool __has_cursum_space(struct f2fs_sb_info *sbi,
> + struct f2fs_journal *journal, int size, int type)
> +{
> + if (type == NAT_JOURNAL)
> + return size <= MAX_NAT_JENTRIES(sbi, journal);
> + return size <= MAX_SIT_JENTRIES(sbi, journal);
> +}
> +
> extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync);
> static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
> struct inode *inode, bool is_inode)
> @@ -3956,7 +3979,8 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> block_t len);
> void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
> void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
> -int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
> +int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
> + struct f2fs_journal *journal, int type,
> unsigned int val, int alloc);
> void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
> int f2fs_check_and_fix_write_pointer(struct f2fs_sb_info *sbi);
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 384fa7e2085b..65c819d08807 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1769,8 +1769,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>
> sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
>
> - segno = rounddown(segno, SUMS_PER_BLOCK);
> - sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK);
> + segno = rounddown(segno, SUMS_PER_BLOCK(sbi));
> + sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK(sbi));
> /* readahead multi ssa blocks those have contiguous address */
> if (__is_large_section(sbi))
> f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
> @@ -1780,17 +1780,17 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> while (segno < end_segno) {
> struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
>
> - segno += SUMS_PER_BLOCK;
> + segno += SUMS_PER_BLOCK(sbi);
> if (IS_ERR(sum_folio)) {
> int err = PTR_ERR(sum_folio);
>
> - end_segno = segno - SUMS_PER_BLOCK;
> - segno = rounddown(start_segno, SUMS_PER_BLOCK);
> + end_segno = segno - SUMS_PER_BLOCK(sbi);
> + segno = rounddown(start_segno, SUMS_PER_BLOCK(sbi));
> while (segno < end_segno) {
> sum_folio = filemap_get_folio(META_MAPPING(sbi),
> GET_SUM_BLOCK(sbi, segno));
> folio_put_refs(sum_folio, 2);
> - segno += SUMS_PER_BLOCK;
> + segno += SUMS_PER_BLOCK(sbi);
> }
> return err;
> }
> @@ -1806,8 +1806,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> /* find segment summary of victim */
> struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
> GET_SUM_BLOCK(sbi, segno));
> - unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK)
> - + SUMS_PER_BLOCK;
> + unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK(sbi))
> + + SUMS_PER_BLOCK(sbi);
>
> if (block_end_segno > end_segno)
> block_end_segno = end_segno;
> @@ -1833,12 +1833,13 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> migrated >= sbi->migration_granularity)
> continue;
>
> - sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno);
> - if (type != GET_SUM_TYPE((&sum->footer))) {
> + 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 "
> "[%d, %d] in SSA and SIT",
> cur_segno, type,
> - GET_SUM_TYPE((&sum->footer)));
> + GET_SUM_TYPE(
> + sum_footer(sbi, sum)));
> f2fs_stop_checkpoint(sbi, false,
> STOP_CP_REASON_CORRUPTED_SUMMARY);
> continue;
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 482a362f2625..f78d53ec59d4 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -606,7 +606,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> goto retry;
> }
>
> - i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
> + i = f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 0);
> if (i >= 0) {
> ne = nat_in_journal(journal, i);
> node_info_from_raw_nat(ni, &ne);
> @@ -2937,7 +2937,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> /* scan the node segment */
> last_offset = BLKS_PER_SEG(sbi);
> addr = START_BLOCK(sbi, segno);
> - sum_entry = &sum->entries[0];
> + sum_entry = sum_entries(sum);
>
> for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
> nrpages = bio_max_segs(last_offset - i);
> @@ -3078,7 +3078,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> * #2, flush nat entries to nat page.
> */
> if (enabled_nat_bits(sbi, cpc) ||
> - !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
> + !__has_cursum_space(sbi, journal, set->entry_cnt, NAT_JOURNAL))
> to_journal = false;
>
> if (to_journal) {
> @@ -3101,7 +3101,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
>
> if (to_journal) {
> - offset = f2fs_lookup_journal_in_cursum(journal,
> + offset = f2fs_lookup_journal_in_cursum(sbi, journal,
> NAT_JOURNAL, nid, 1);
> f2fs_bug_on(sbi, offset < 0);
> raw_ne = &nat_in_journal(journal, offset);
> @@ -3172,7 +3172,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> * into nat entry set.
> */
> if (enabled_nat_bits(sbi, cpc) ||
> - !__has_cursum_space(journal,
> + !__has_cursum_space(sbi, journal,
> nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
> remove_nats_in_journal(sbi);
>
> @@ -3183,7 +3183,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> set_idx = setvec[found - 1]->set + 1;
> for (idx = 0; idx < found; idx++)
> __adjust_nat_entry_set(setvec[idx], &sets,
> - MAX_NAT_JENTRIES(journal));
> + MAX_NAT_JENTRIES(sbi, journal));
> }
>
> /* flush dirty nats in nat entry set */
> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> index c3415ebb9f50..a6bfc8e759cf 100644
> --- a/fs/f2fs/recovery.c
> +++ b/fs/f2fs/recovery.c
> @@ -514,7 +514,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> struct curseg_info *curseg = CURSEG_I(sbi, i);
>
> if (curseg->segno == segno) {
> - sum = curseg->sum_blk->entries[blkoff];
> + sum = sum_entries(curseg->sum_blk)[blkoff];
> goto got_it;
> }
> }
> @@ -522,8 +522,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> sum_folio = f2fs_get_sum_folio(sbi, segno);
> if (IS_ERR(sum_folio))
> return PTR_ERR(sum_folio);
> - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno);
> - sum = sum_node->entries[blkoff];
> + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno);
> + sum = sum_entries(sum_node)[blkoff];
> f2fs_folio_put(sum_folio, true);
> got_it:
> /* Use the locked dnode page and inode */
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index c26424f47686..9a73b979b2e6 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2685,12 +2685,12 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
> valid_sum_count += f2fs_curseg_valid_blocks(sbi, i);
> }
>
> - sum_in_page = (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE -
> + sum_in_page = (F2FS_SUM_BLKSIZE(sbi) - 2 * SUM_JOURNAL_SIZE(sbi) -
> SUM_FOOTER_SIZE) / SUMMARY_SIZE;
> if (valid_sum_count <= sum_in_page)
> return 1;
> else if ((valid_sum_count - sum_in_page) <=
> - (PAGE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
> + (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
> return 2;
> return 3;
> }
> @@ -2710,7 +2710,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
> {
> struct folio *folio;
>
> - if (SUMS_PER_BLOCK == 1)
> + if (!f2fs_sb_has_packed_ssa(sbi))
> folio = f2fs_grab_meta_folio(sbi, blk_addr);
> else
> folio = f2fs_get_meta_folio_retry(sbi, blk_addr);
> @@ -2728,7 +2728,7 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
> {
> struct folio *folio;
>
> - if (SUMS_PER_BLOCK == 1)
> + if (!f2fs_sb_has_packed_ssa(sbi))
> return f2fs_update_meta_page(sbi, (void *)sum_blk,
> GET_SUM_BLOCK(sbi, segno));
>
> @@ -2736,7 +2736,8 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
> if (IS_ERR(folio))
> return;
>
> - memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk));
> + memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk,
> + F2FS_SUM_BLKSIZE(sbi));
> folio_mark_dirty(folio);
> f2fs_folio_put(folio, true);
> }
> @@ -2755,11 +2756,11 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi,
> mutex_lock(&curseg->curseg_mutex);
>
> down_read(&curseg->journal_rwsem);
> - memcpy(&dst->journal, curseg->journal, SUM_JOURNAL_SIZE);
> + memcpy(sum_journal(sbi, dst), curseg->journal, SUM_JOURNAL_SIZE(sbi));
> up_read(&curseg->journal_rwsem);
>
> - memcpy(dst->entries, src->entries, SUM_ENTRY_SIZE);
> - memcpy(&dst->footer, &src->footer, SUM_FOOTER_SIZE);
> + memcpy(sum_entries(dst), sum_entries(src), SUM_ENTRY_SIZE(sbi));
> + memcpy(sum_footer(sbi, dst), sum_footer(sbi, src), SUM_FOOTER_SIZE);
>
> mutex_unlock(&curseg->curseg_mutex);
>
> @@ -2932,7 +2933,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
> curseg->next_blkoff = 0;
> curseg->next_segno = NULL_SEGNO;
>
> - sum_footer = &(curseg->sum_blk->footer);
> + sum_footer = sum_footer(sbi, curseg->sum_blk);
> memset(sum_footer, 0, sizeof(struct summary_footer));
>
> sanity_check_seg_type(sbi, seg_type);
> @@ -3078,11 +3079,11 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
> sum_folio = f2fs_get_sum_folio(sbi, new_segno);
> if (IS_ERR(sum_folio)) {
> /* GC won't be able to use stale summary pages by cp_error */
> - memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE);
> + memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE(sbi));
> return PTR_ERR(sum_folio);
> }
> - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno);
> - memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
> + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno);
> + memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE(sbi));
> f2fs_folio_put(sum_folio, true);
> return 0;
> }
> @@ -3814,7 +3815,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio,
>
> f2fs_wait_discard_bio(sbi, *new_blkaddr);
>
> - curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
> + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
> if (curseg->alloc_type == SSR) {
> curseg->next_blkoff = f2fs_find_next_ssr_block(sbi, curseg);
> } else {
> @@ -4183,7 +4184,7 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
> }
>
> curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
> - curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
> + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
>
> if (!recover_curseg || recover_newaddr) {
> if (!from_gc)
> @@ -4303,12 +4304,12 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
>
> /* Step 1: restore nat cache */
> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> - memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE);
> + memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE(sbi));
>
> /* Step 2: restore sit cache */
> seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
> - memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE);
> - offset = 2 * SUM_JOURNAL_SIZE;
> + memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE(sbi), SUM_JOURNAL_SIZE(sbi));
> + offset = 2 * SUM_JOURNAL_SIZE(sbi);
>
> /* Step 3: restore summary entries */
> for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
> @@ -4330,9 +4331,9 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> struct f2fs_summary *s;
>
> s = (struct f2fs_summary *)(kaddr + offset);
> - seg_i->sum_blk->entries[j] = *s;
> + sum_entries(seg_i->sum_blk)[j] = *s;
> offset += SUMMARY_SIZE;
> - if (offset + SUMMARY_SIZE <= PAGE_SIZE -
> + if (offset + SUMMARY_SIZE <= F2FS_SUM_BLKSIZE(sbi) -
> SUM_FOOTER_SIZE)
> continue;
>
> @@ -4388,7 +4389,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
>
> if (IS_NODESEG(type)) {
> if (__exist_node_summaries(sbi)) {
> - struct f2fs_summary *ns = &sum->entries[0];
> + struct f2fs_summary *ns = sum_entries(sum);
> int i;
>
> for (i = 0; i < BLKS_PER_SEG(sbi); i++, ns++) {
> @@ -4408,11 +4409,13 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
>
> /* update journal info */
> down_write(&curseg->journal_rwsem);
> - memcpy(curseg->journal, &sum->journal, SUM_JOURNAL_SIZE);
> + memcpy(curseg->journal, sum_journal(sbi, sum), SUM_JOURNAL_SIZE(sbi));
> up_write(&curseg->journal_rwsem);
>
> - memcpy(curseg->sum_blk->entries, sum->entries, SUM_ENTRY_SIZE);
> - memcpy(&curseg->sum_blk->footer, &sum->footer, SUM_FOOTER_SIZE);
> + memcpy(sum_entries(curseg->sum_blk), sum_entries(sum),
> + SUM_ENTRY_SIZE(sbi));
> + memcpy(sum_footer(sbi, curseg->sum_blk), sum_footer(sbi, sum),
> + SUM_FOOTER_SIZE);
> curseg->next_segno = segno;
> reset_curseg(sbi, type, 0);
> curseg->alloc_type = ckpt->alloc_type[type];
> @@ -4456,8 +4459,8 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
> }
>
> /* sanity check for summary blocks */
> - if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES ||
> - sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) {
> + if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES(sbi) ||
> + sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES(sbi)) {
> f2fs_err(sbi, "invalid journal entries nats %u sits %u",
> nats_in_cursum(nat_j), sits_in_cursum(sit_j));
> return -EINVAL;
> @@ -4481,13 +4484,13 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
>
> /* Step 1: write nat cache */
> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> - memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE);
> - written_size += SUM_JOURNAL_SIZE;
> + memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
> + written_size += SUM_JOURNAL_SIZE(sbi);
>
> /* Step 2: write sit cache */
> seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
> - memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE);
> - written_size += SUM_JOURNAL_SIZE;
> + memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
> + written_size += SUM_JOURNAL_SIZE(sbi);
>
> /* Step 3: write summary entries */
> for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
> @@ -4500,7 +4503,7 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> written_size = 0;
> }
> summary = (struct f2fs_summary *)(kaddr + written_size);
> - *summary = seg_i->sum_blk->entries[j];
> + *summary = sum_entries(seg_i->sum_blk)[j];
> written_size += SUMMARY_SIZE;
>
> if (written_size + SUMMARY_SIZE <= PAGE_SIZE -
> @@ -4545,8 +4548,9 @@ void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
> write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
> }
>
> -int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
> - unsigned int val, int alloc)
> +int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
> + struct f2fs_journal *journal, int type,
> + unsigned int val, int alloc)
> {
> int i;
>
> @@ -4555,13 +4559,13 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
> if (le32_to_cpu(nid_in_journal(journal, i)) == val)
> return i;
> }
> - if (alloc && __has_cursum_space(journal, 1, NAT_JOURNAL))
> + if (alloc && __has_cursum_space(sbi, journal, 1, NAT_JOURNAL))
> return update_nats_in_cursum(journal, 1);
> } else if (type == SIT_JOURNAL) {
> for (i = 0; i < sits_in_cursum(journal); i++)
> if (le32_to_cpu(segno_in_journal(journal, i)) == val)
> return i;
> - if (alloc && __has_cursum_space(journal, 1, SIT_JOURNAL))
> + if (alloc && __has_cursum_space(sbi, journal, 1, SIT_JOURNAL))
> return update_sits_in_cursum(journal, 1);
> }
> return -1;
> @@ -4709,8 +4713,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> * entries, remove all entries from journal and add and account
> * them in sit entry set.
> */
> - if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL) ||
> - !to_journal)
> + if (!__has_cursum_space(sbi, journal,
> + sit_i->dirty_sentries, SIT_JOURNAL) || !to_journal)
> remove_sits_in_journal(sbi);
>
> /*
> @@ -4727,7 +4731,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> unsigned int segno = start_segno;
>
> if (to_journal &&
> - !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL))
> + !__has_cursum_space(sbi, journal, ses->entry_cnt,
> + SIT_JOURNAL))
> to_journal = false;
>
> if (to_journal) {
> @@ -4755,7 +4760,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> }
>
> if (to_journal) {
> - offset = f2fs_lookup_journal_in_cursum(journal,
> + offset = f2fs_lookup_journal_in_cursum(sbi, journal,
> SIT_JOURNAL, segno, 1);
> f2fs_bug_on(sbi, offset < 0);
> segno_in_journal(journal, offset) =
> @@ -4962,12 +4967,13 @@ static int build_curseg(struct f2fs_sb_info *sbi)
>
> for (i = 0; i < NO_CHECK_TYPE; i++) {
> mutex_init(&array[i].curseg_mutex);
> - array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
> + array[i].sum_blk = f2fs_kzalloc(sbi, F2FS_SUM_BLKSIZE(sbi),
> + GFP_KERNEL);
> if (!array[i].sum_blk)
> return -ENOMEM;
> init_rwsem(&array[i].journal_rwsem);
> array[i].journal = f2fs_kzalloc(sbi,
> - sizeof(struct f2fs_journal), GFP_KERNEL);
> + SUM_JOURNAL_SIZE(sbi), GFP_KERNEL);
> if (!array[i].journal)
> return -ENOMEM;
> array[i].seg_type = log_type_to_seg_type(i);
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index 07dcbcbeb7c6..8b38f3693b1a 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -90,12 +90,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))
>
> -#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE)
> +#define SUMS_PER_BLOCK(sbi) ((sbi)->blocksize / F2FS_SUM_BLKSIZE(sbi))
> #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)
> + (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK(sbi)))
> +#define GET_SUM_BLKOFF(sbi, segno) (segno % SUMS_PER_BLOCK(sbi))
> +#define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
> + (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * F2FS_SUM_BLKSIZE(sbi))
>
> #define GET_SUM_TYPE(footer) ((footer)->entry_type)
> #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index c4c225e09dc4..253a23a7b67d 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4080,20 +4080,6 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
> if (sanity_check_area_boundary(sbi, folio, index))
> return -EFSCORRUPTED;
>
> - /*
> - * 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;
> }
>
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index a7880787cad3..394f7af3a102 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -17,7 +17,6 @@
> #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
> #define F2FS_BLKSIZE PAGE_SIZE /* support only block == 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 */
>
> @@ -442,10 +441,8 @@ struct f2fs_sit_block {
> * from node's page's beginning to get a data block address.
> * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
> */
> -#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)
>
> /* a summary entry for a block in a segment */
> struct f2fs_summary {
> @@ -468,22 +465,6 @@ struct summary_footer {
> __le32 check_sum; /* summary checksum */
> } __packed;
>
> -#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))
> -#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
> - sizeof(struct nat_journal_entry))
> -#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
> - sizeof(struct sit_journal_entry))
> -#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
> - sizeof(struct sit_journal_entry))
> -
> -/* Reserved area should make size of f2fs_extra_info equals to
> - * that of nat_journal and sit_journal.
> - */
> -#define EXTRA_INFO_RESERVED (SUM_JOURNAL_SIZE - 2 - 8)
> -
> /*
> * frequently updated NAT/SIT entries can be stored in the spare area in
> * summary blocks
> @@ -498,9 +479,16 @@ struct nat_journal_entry {
> struct f2fs_nat_entry ne;
> } __packed;
>
> +/*
> + * The nat_journal structure is a placeholder whose actual size varies depending
> + * on the use of packed_ssa. Therefore, it must always be accessed only through
> + * specific sets of macros, and size calculations should use size-related macros
> + * instead of sizeof().
> + * Relevant macros: NAT_JOURNAL_ENTRIES, nat_in_journal, nid_in_journal,
> + * MAX_NAT_JENTRIES.
> + */
> struct nat_journal {
> - struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
> - __u8 reserved[NAT_JOURNAL_RESERVED];
> + struct nat_journal_entry entries[0];
> } __packed;
>
> struct sit_journal_entry {
> @@ -508,14 +496,21 @@ struct sit_journal_entry {
> struct f2fs_sit_entry se;
> } __packed;
>
> +/*
> + * The sit_journal structure is a placeholder whose actual size varies depending
> + * on the use of packed_ssa. Therefore, it must always be accessed only through
> + * specific sets of macros, and size calculations should use size-related macros
> + * instead of sizeof().
> + * Relevant macros: SIT_JOURNAL_ENTRIES, sit_in_journal, segno_in_journal,
> + * MAX_SIT_JENTRIES.
> + */
> struct sit_journal {
> - struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
> - __u8 reserved[SIT_JOURNAL_RESERVED];
> + struct sit_journal_entry entries[0];
> } __packed;
>
> struct f2fs_extra_info {
> __le64 kbytes_written;
> - __u8 reserved[EXTRA_INFO_RESERVED];
> + __u8 reserved[];
> } __packed;
>
> struct f2fs_journal {
> @@ -531,11 +526,33 @@ struct f2fs_journal {
> };
> } __packed;
>
> -/* Block-sized summary block structure */
> +/*
> + * Block-sized summary block structure
> + *
> + * The f2fs_summary_block structure is a placeholder whose actual size varies
> + * depending on the use of packed_ssa. Therefore, it must always be accessed
> + * only through specific sets of macros, and size calculations should use
> + * size-related macros instead of sizeof().
> + * Relevant macros: F2FS_SUM_BLKSIZE, ENTRIES_IN_SUM, SUM_ENTRY_SIZE,
> + * sum_entries, sum_journal, sum_footer.
> + *
> + * Summary Block Layout
> + *
> + * +-----------------------+ <--- Block Start
> + * | struct f2fs_summary |
> + * | entries[0] |
> + * | ... |
> + * | entries[N-1] |
> + * +-----------------------+
> + * | struct f2fs_journal |
> + * +-----------------------+
> + * | struct summary_footer |
> + * +-----------------------+ <--- Block End
> + */
> struct f2fs_summary_block {
> - struct f2fs_summary entries[ENTRIES_IN_SUM];
> - struct f2fs_journal journal;
> - struct summary_footer footer;
> + struct f2fs_summary entries[0];
> + // struct f2fs_journal journal;
> + // struct summary_footer footer;
> } __packed;
>
> /*
On Thu, Jan 8, 2026 at 10:52 PM Chao Yu <chao@kernel.org> wrote:
>
> On 1/8/2026 9:46 AM, Daeho Jeong wrote:
> > From: Daeho Jeong <daehojeong@google.com>
> >
> > Currently, F2FS requires the packed_ssa feature to be enabled when
> > utilizing non-4KB block sizes (e.g., 16KB). This restriction limits
> > the flexibility of filesystem formatting options.
> >
> > This patch allows F2FS to support non-4KB block sizes even when the
> > packed_ssa feature is disabled. It adjusts the SSA calculation logic to
> > correctly handle summary entries in larger blocks without the packed
> > layout.
>
> Can we consider to add testcases into xfsqa to cover recent revert patch
> and packed_ssa feature which changes disk layout a bit? not sure, we may
> miss some corner cases in keep compatibility, e.g. mount old/new image w/
> new kernel.
Regarding the test cases, I've already verified all combinations
locally—specifically
focusing on cross-compatibility between old/new images and the new kernel. The
results were consistent across the board. While adding them to xfsqa
is a good idea
for long-term tracking, I've confirmed that the recent changes don't
break any of those
corner cases.
>
> >
> > Fixes: 7ee8bc3942f2 ("f2fs: revert summary entry count from 2048 to 512 in 16kb block support")
>
> Cc: stable@kernel.org
>
> > Signed-off-by: Daeho Jeong <daehojeong@google.com>
> > ---
> > fs/f2fs/f2fs.h | 56 +++++++++++++++++++--------
> > fs/f2fs/gc.c | 23 +++++------
> > fs/f2fs/node.c | 12 +++---
> > fs/f2fs/recovery.c | 6 +--
> > fs/f2fs/segment.c | 86 ++++++++++++++++++++++-------------------
> > fs/f2fs/segment.h | 10 ++---
> > fs/f2fs/super.c | 14 -------
> > include/linux/f2fs_fs.h | 73 ++++++++++++++++++++--------------
> > 8 files changed, 157 insertions(+), 123 deletions(-)
> >
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 20edbb99b814..0ceae7d83a48 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -521,13 +521,36 @@ struct fsync_inode_entry {
> > #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats))
> > #define sits_in_cursum(jnl) (le16_to_cpu((jnl)->n_sits))
> >
> > -#define nat_in_journal(jnl, i) ((jnl)->nat_j.entries[i].ne)
> > -#define nid_in_journal(jnl, i) ((jnl)->nat_j.entries[i].nid)
> > -#define sit_in_journal(jnl, i) ((jnl)->sit_j.entries[i].se)
> > -#define segno_in_journal(jnl, i) ((jnl)->sit_j.entries[i].segno)
> > -
> > -#define MAX_NAT_JENTRIES(jnl) (NAT_JOURNAL_ENTRIES - nats_in_cursum(jnl))
> > -#define MAX_SIT_JENTRIES(jnl) (SIT_JOURNAL_ENTRIES - sits_in_cursum(jnl))
> > +#define nat_in_journal(jnl, i) \
> > + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].ne)
> > +#define nid_in_journal(jnl, i) \
> > + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].nid)
> > +#define sit_in_journal(jnl, i) \
> > + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].se)
> > +#define segno_in_journal(jnl, i) \
> > + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].segno)
> > +
> > +#define F2FS_SUM_BLKSIZE(sbi) \
> > + (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_PACKED_SSA) ? 4096 : (sbi)->blocksize)
>
> What about caching F2FS_SUM_BLKSIZE() as sbi->sum_blksize to avoid rundandent
> calculation in lots of places?
makes sense. Thanks.
>
> > +#define ENTRIES_IN_SUM(sbi) (F2FS_SUM_BLKSIZE(sbi) / 8)
> > +#define SUM_ENTRY_SIZE(sbi) (SUMMARY_SIZE * ENTRIES_IN_SUM(sbi))
> > +#define SUM_JOURNAL_SIZE(sbi) (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE - \
> > + SUM_ENTRY_SIZE(sbi))
> > +#define NAT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
> > + sizeof(struct nat_journal_entry))
> > +#define SIT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
> > + sizeof(struct sit_journal_entry))
>
> Ditto?
>
> Thanks,
>
> > +
> > +#define sum_entries(sum) ((struct f2fs_summary *)(sum))
> > +#define sum_journal(sbi, sum) \
> > + ((struct f2fs_journal *)((char *)(sum) + \
> > + (ENTRIES_IN_SUM(sbi) * sizeof(struct f2fs_summary))))
> > +#define sum_footer(sbi, sum) \
> > + ((struct summary_footer *)((char *)(sum) + F2FS_SUM_BLKSIZE(sbi) - \
> > + sizeof(struct summary_footer)))
> > +
> > +#define MAX_NAT_JENTRIES(sbi, jnl) (NAT_JOURNAL_ENTRIES(sbi) - nats_in_cursum(jnl))
> > +#define MAX_SIT_JENTRIES(sbi, jnl) (SIT_JOURNAL_ENTRIES(sbi) - sits_in_cursum(jnl))
> >
> > static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i)
> > {
> > @@ -545,14 +568,6 @@ static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i)
> > return before;
> > }
> >
> > -static inline bool __has_cursum_space(struct f2fs_journal *journal,
> > - int size, int type)
> > -{
> > - if (type == NAT_JOURNAL)
> > - return size <= MAX_NAT_JENTRIES(journal);
> > - return size <= MAX_SIT_JENTRIES(journal);
> > -}
> > -
> > /* for inline stuff */
> > #define DEF_INLINE_RESERVED_SIZE 1
> > static inline int get_extra_isize(struct inode *inode);
> > @@ -2813,6 +2828,14 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
> > return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
> > }
> >
> > +static inline bool __has_cursum_space(struct f2fs_sb_info *sbi,
> > + struct f2fs_journal *journal, int size, int type)
> > +{
> > + if (type == NAT_JOURNAL)
> > + return size <= MAX_NAT_JENTRIES(sbi, journal);
> > + return size <= MAX_SIT_JENTRIES(sbi, journal);
> > +}
> > +
> > extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync);
> > static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
> > struct inode *inode, bool is_inode)
> > @@ -3956,7 +3979,8 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
> > block_t len);
> > void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
> > void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
> > -int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
> > +int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
> > + struct f2fs_journal *journal, int type,
> > unsigned int val, int alloc);
> > void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
> > int f2fs_check_and_fix_write_pointer(struct f2fs_sb_info *sbi);
> > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > index 384fa7e2085b..65c819d08807 100644
> > --- a/fs/f2fs/gc.c
> > +++ b/fs/f2fs/gc.c
> > @@ -1769,8 +1769,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> >
> > sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
> >
> > - segno = rounddown(segno, SUMS_PER_BLOCK);
> > - sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK);
> > + segno = rounddown(segno, SUMS_PER_BLOCK(sbi));
> > + sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK(sbi));
> > /* readahead multi ssa blocks those have contiguous address */
> > if (__is_large_section(sbi))
> > f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
> > @@ -1780,17 +1780,17 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> > while (segno < end_segno) {
> > struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
> >
> > - segno += SUMS_PER_BLOCK;
> > + segno += SUMS_PER_BLOCK(sbi);
> > if (IS_ERR(sum_folio)) {
> > int err = PTR_ERR(sum_folio);
> >
> > - end_segno = segno - SUMS_PER_BLOCK;
> > - segno = rounddown(start_segno, SUMS_PER_BLOCK);
> > + end_segno = segno - SUMS_PER_BLOCK(sbi);
> > + segno = rounddown(start_segno, SUMS_PER_BLOCK(sbi));
> > while (segno < end_segno) {
> > sum_folio = filemap_get_folio(META_MAPPING(sbi),
> > GET_SUM_BLOCK(sbi, segno));
> > folio_put_refs(sum_folio, 2);
> > - segno += SUMS_PER_BLOCK;
> > + segno += SUMS_PER_BLOCK(sbi);
> > }
> > return err;
> > }
> > @@ -1806,8 +1806,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> > /* find segment summary of victim */
> > struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
> > GET_SUM_BLOCK(sbi, segno));
> > - unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK)
> > - + SUMS_PER_BLOCK;
> > + unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK(sbi))
> > + + SUMS_PER_BLOCK(sbi);
> >
> > if (block_end_segno > end_segno)
> > block_end_segno = end_segno;
> > @@ -1833,12 +1833,13 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
> > migrated >= sbi->migration_granularity)
> > continue;
> >
> > - sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno);
> > - if (type != GET_SUM_TYPE((&sum->footer))) {
> > + 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 "
> > "[%d, %d] in SSA and SIT",
> > cur_segno, type,
> > - GET_SUM_TYPE((&sum->footer)));
> > + GET_SUM_TYPE(
> > + sum_footer(sbi, sum)));
> > f2fs_stop_checkpoint(sbi, false,
> > STOP_CP_REASON_CORRUPTED_SUMMARY);
> > continue;
> > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> > index 482a362f2625..f78d53ec59d4 100644
> > --- a/fs/f2fs/node.c
> > +++ b/fs/f2fs/node.c
> > @@ -606,7 +606,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> > goto retry;
> > }
> >
> > - i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
> > + i = f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 0);
> > if (i >= 0) {
> > ne = nat_in_journal(journal, i);
> > node_info_from_raw_nat(ni, &ne);
> > @@ -2937,7 +2937,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> > /* scan the node segment */
> > last_offset = BLKS_PER_SEG(sbi);
> > addr = START_BLOCK(sbi, segno);
> > - sum_entry = &sum->entries[0];
> > + sum_entry = sum_entries(sum);
> >
> > for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
> > nrpages = bio_max_segs(last_offset - i);
> > @@ -3078,7 +3078,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> > * #2, flush nat entries to nat page.
> > */
> > if (enabled_nat_bits(sbi, cpc) ||
> > - !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
> > + !__has_cursum_space(sbi, journal, set->entry_cnt, NAT_JOURNAL))
> > to_journal = false;
> >
> > if (to_journal) {
> > @@ -3101,7 +3101,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> > f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
> >
> > if (to_journal) {
> > - offset = f2fs_lookup_journal_in_cursum(journal,
> > + offset = f2fs_lookup_journal_in_cursum(sbi, journal,
> > NAT_JOURNAL, nid, 1);
> > f2fs_bug_on(sbi, offset < 0);
> > raw_ne = &nat_in_journal(journal, offset);
> > @@ -3172,7 +3172,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> > * into nat entry set.
> > */
> > if (enabled_nat_bits(sbi, cpc) ||
> > - !__has_cursum_space(journal,
> > + !__has_cursum_space(sbi, journal,
> > nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
> > remove_nats_in_journal(sbi);
> >
> > @@ -3183,7 +3183,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> > set_idx = setvec[found - 1]->set + 1;
> > for (idx = 0; idx < found; idx++)
> > __adjust_nat_entry_set(setvec[idx], &sets,
> > - MAX_NAT_JENTRIES(journal));
> > + MAX_NAT_JENTRIES(sbi, journal));
> > }
> >
> > /* flush dirty nats in nat entry set */
> > diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> > index c3415ebb9f50..a6bfc8e759cf 100644
> > --- a/fs/f2fs/recovery.c
> > +++ b/fs/f2fs/recovery.c
> > @@ -514,7 +514,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> > struct curseg_info *curseg = CURSEG_I(sbi, i);
> >
> > if (curseg->segno == segno) {
> > - sum = curseg->sum_blk->entries[blkoff];
> > + sum = sum_entries(curseg->sum_blk)[blkoff];
> > goto got_it;
> > }
> > }
> > @@ -522,8 +522,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
> > sum_folio = f2fs_get_sum_folio(sbi, segno);
> > if (IS_ERR(sum_folio))
> > return PTR_ERR(sum_folio);
> > - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno);
> > - sum = sum_node->entries[blkoff];
> > + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno);
> > + sum = sum_entries(sum_node)[blkoff];
> > f2fs_folio_put(sum_folio, true);
> > got_it:
> > /* Use the locked dnode page and inode */
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index c26424f47686..9a73b979b2e6 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -2685,12 +2685,12 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
> > valid_sum_count += f2fs_curseg_valid_blocks(sbi, i);
> > }
> >
> > - sum_in_page = (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE -
> > + sum_in_page = (F2FS_SUM_BLKSIZE(sbi) - 2 * SUM_JOURNAL_SIZE(sbi) -
> > SUM_FOOTER_SIZE) / SUMMARY_SIZE;
> > if (valid_sum_count <= sum_in_page)
> > return 1;
> > else if ((valid_sum_count - sum_in_page) <=
> > - (PAGE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
> > + (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
> > return 2;
> > return 3;
> > }
> > @@ -2710,7 +2710,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
> > {
> > struct folio *folio;
> >
> > - if (SUMS_PER_BLOCK == 1)
> > + if (!f2fs_sb_has_packed_ssa(sbi))
> > folio = f2fs_grab_meta_folio(sbi, blk_addr);
> > else
> > folio = f2fs_get_meta_folio_retry(sbi, blk_addr);
> > @@ -2728,7 +2728,7 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
> > {
> > struct folio *folio;
> >
> > - if (SUMS_PER_BLOCK == 1)
> > + if (!f2fs_sb_has_packed_ssa(sbi))
> > return f2fs_update_meta_page(sbi, (void *)sum_blk,
> > GET_SUM_BLOCK(sbi, segno));
> >
> > @@ -2736,7 +2736,8 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
> > if (IS_ERR(folio))
> > return;
> >
> > - memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk));
> > + memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk,
> > + F2FS_SUM_BLKSIZE(sbi));
> > folio_mark_dirty(folio);
> > f2fs_folio_put(folio, true);
> > }
> > @@ -2755,11 +2756,11 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi,
> > mutex_lock(&curseg->curseg_mutex);
> >
> > down_read(&curseg->journal_rwsem);
> > - memcpy(&dst->journal, curseg->journal, SUM_JOURNAL_SIZE);
> > + memcpy(sum_journal(sbi, dst), curseg->journal, SUM_JOURNAL_SIZE(sbi));
> > up_read(&curseg->journal_rwsem);
> >
> > - memcpy(dst->entries, src->entries, SUM_ENTRY_SIZE);
> > - memcpy(&dst->footer, &src->footer, SUM_FOOTER_SIZE);
> > + memcpy(sum_entries(dst), sum_entries(src), SUM_ENTRY_SIZE(sbi));
> > + memcpy(sum_footer(sbi, dst), sum_footer(sbi, src), SUM_FOOTER_SIZE);
> >
> > mutex_unlock(&curseg->curseg_mutex);
> >
> > @@ -2932,7 +2933,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
> > curseg->next_blkoff = 0;
> > curseg->next_segno = NULL_SEGNO;
> >
> > - sum_footer = &(curseg->sum_blk->footer);
> > + sum_footer = sum_footer(sbi, curseg->sum_blk);
> > memset(sum_footer, 0, sizeof(struct summary_footer));
> >
> > sanity_check_seg_type(sbi, seg_type);
> > @@ -3078,11 +3079,11 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
> > sum_folio = f2fs_get_sum_folio(sbi, new_segno);
> > if (IS_ERR(sum_folio)) {
> > /* GC won't be able to use stale summary pages by cp_error */
> > - memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE);
> > + memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE(sbi));
> > return PTR_ERR(sum_folio);
> > }
> > - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno);
> > - memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
> > + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno);
> > + memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE(sbi));
> > f2fs_folio_put(sum_folio, true);
> > return 0;
> > }
> > @@ -3814,7 +3815,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio,
> >
> > f2fs_wait_discard_bio(sbi, *new_blkaddr);
> >
> > - curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
> > + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
> > if (curseg->alloc_type == SSR) {
> > curseg->next_blkoff = f2fs_find_next_ssr_block(sbi, curseg);
> > } else {
> > @@ -4183,7 +4184,7 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
> > }
> >
> > curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
> > - curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
> > + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
> >
> > if (!recover_curseg || recover_newaddr) {
> > if (!from_gc)
> > @@ -4303,12 +4304,12 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> >
> > /* Step 1: restore nat cache */
> > seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> > - memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE);
> > + memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE(sbi));
> >
> > /* Step 2: restore sit cache */
> > seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
> > - memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE);
> > - offset = 2 * SUM_JOURNAL_SIZE;
> > + memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE(sbi), SUM_JOURNAL_SIZE(sbi));
> > + offset = 2 * SUM_JOURNAL_SIZE(sbi);
> >
> > /* Step 3: restore summary entries */
> > for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
> > @@ -4330,9 +4331,9 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
> > struct f2fs_summary *s;
> >
> > s = (struct f2fs_summary *)(kaddr + offset);
> > - seg_i->sum_blk->entries[j] = *s;
> > + sum_entries(seg_i->sum_blk)[j] = *s;
> > offset += SUMMARY_SIZE;
> > - if (offset + SUMMARY_SIZE <= PAGE_SIZE -
> > + if (offset + SUMMARY_SIZE <= F2FS_SUM_BLKSIZE(sbi) -
> > SUM_FOOTER_SIZE)
> > continue;
> >
> > @@ -4388,7 +4389,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> >
> > if (IS_NODESEG(type)) {
> > if (__exist_node_summaries(sbi)) {
> > - struct f2fs_summary *ns = &sum->entries[0];
> > + struct f2fs_summary *ns = sum_entries(sum);
> > int i;
> >
> > for (i = 0; i < BLKS_PER_SEG(sbi); i++, ns++) {
> > @@ -4408,11 +4409,13 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
> >
> > /* update journal info */
> > down_write(&curseg->journal_rwsem);
> > - memcpy(curseg->journal, &sum->journal, SUM_JOURNAL_SIZE);
> > + memcpy(curseg->journal, sum_journal(sbi, sum), SUM_JOURNAL_SIZE(sbi));
> > up_write(&curseg->journal_rwsem);
> >
> > - memcpy(curseg->sum_blk->entries, sum->entries, SUM_ENTRY_SIZE);
> > - memcpy(&curseg->sum_blk->footer, &sum->footer, SUM_FOOTER_SIZE);
> > + memcpy(sum_entries(curseg->sum_blk), sum_entries(sum),
> > + SUM_ENTRY_SIZE(sbi));
> > + memcpy(sum_footer(sbi, curseg->sum_blk), sum_footer(sbi, sum),
> > + SUM_FOOTER_SIZE);
> > curseg->next_segno = segno;
> > reset_curseg(sbi, type, 0);
> > curseg->alloc_type = ckpt->alloc_type[type];
> > @@ -4456,8 +4459,8 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
> > }
> >
> > /* sanity check for summary blocks */
> > - if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES ||
> > - sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) {
> > + if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES(sbi) ||
> > + sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES(sbi)) {
> > f2fs_err(sbi, "invalid journal entries nats %u sits %u",
> > nats_in_cursum(nat_j), sits_in_cursum(sit_j));
> > return -EINVAL;
> > @@ -4481,13 +4484,13 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> >
> > /* Step 1: write nat cache */
> > seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
> > - memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE);
> > - written_size += SUM_JOURNAL_SIZE;
> > + memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
> > + written_size += SUM_JOURNAL_SIZE(sbi);
> >
> > /* Step 2: write sit cache */
> > seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
> > - memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE);
> > - written_size += SUM_JOURNAL_SIZE;
> > + memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
> > + written_size += SUM_JOURNAL_SIZE(sbi);
> >
> > /* Step 3: write summary entries */
> > for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
> > @@ -4500,7 +4503,7 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
> > written_size = 0;
> > }
> > summary = (struct f2fs_summary *)(kaddr + written_size);
> > - *summary = seg_i->sum_blk->entries[j];
> > + *summary = sum_entries(seg_i->sum_blk)[j];
> > written_size += SUMMARY_SIZE;
> >
> > if (written_size + SUMMARY_SIZE <= PAGE_SIZE -
> > @@ -4545,8 +4548,9 @@ void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
> > write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
> > }
> >
> > -int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
> > - unsigned int val, int alloc)
> > +int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
> > + struct f2fs_journal *journal, int type,
> > + unsigned int val, int alloc)
> > {
> > int i;
> >
> > @@ -4555,13 +4559,13 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
> > if (le32_to_cpu(nid_in_journal(journal, i)) == val)
> > return i;
> > }
> > - if (alloc && __has_cursum_space(journal, 1, NAT_JOURNAL))
> > + if (alloc && __has_cursum_space(sbi, journal, 1, NAT_JOURNAL))
> > return update_nats_in_cursum(journal, 1);
> > } else if (type == SIT_JOURNAL) {
> > for (i = 0; i < sits_in_cursum(journal); i++)
> > if (le32_to_cpu(segno_in_journal(journal, i)) == val)
> > return i;
> > - if (alloc && __has_cursum_space(journal, 1, SIT_JOURNAL))
> > + if (alloc && __has_cursum_space(sbi, journal, 1, SIT_JOURNAL))
> > return update_sits_in_cursum(journal, 1);
> > }
> > return -1;
> > @@ -4709,8 +4713,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> > * entries, remove all entries from journal and add and account
> > * them in sit entry set.
> > */
> > - if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL) ||
> > - !to_journal)
> > + if (!__has_cursum_space(sbi, journal,
> > + sit_i->dirty_sentries, SIT_JOURNAL) || !to_journal)
> > remove_sits_in_journal(sbi);
> >
> > /*
> > @@ -4727,7 +4731,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> > unsigned int segno = start_segno;
> >
> > if (to_journal &&
> > - !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL))
> > + !__has_cursum_space(sbi, journal, ses->entry_cnt,
> > + SIT_JOURNAL))
> > to_journal = false;
> >
> > if (to_journal) {
> > @@ -4755,7 +4760,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> > }
> >
> > if (to_journal) {
> > - offset = f2fs_lookup_journal_in_cursum(journal,
> > + offset = f2fs_lookup_journal_in_cursum(sbi, journal,
> > SIT_JOURNAL, segno, 1);
> > f2fs_bug_on(sbi, offset < 0);
> > segno_in_journal(journal, offset) =
> > @@ -4962,12 +4967,13 @@ static int build_curseg(struct f2fs_sb_info *sbi)
> >
> > for (i = 0; i < NO_CHECK_TYPE; i++) {
> > mutex_init(&array[i].curseg_mutex);
> > - array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
> > + array[i].sum_blk = f2fs_kzalloc(sbi, F2FS_SUM_BLKSIZE(sbi),
> > + GFP_KERNEL);
> > if (!array[i].sum_blk)
> > return -ENOMEM;
> > init_rwsem(&array[i].journal_rwsem);
> > array[i].journal = f2fs_kzalloc(sbi,
> > - sizeof(struct f2fs_journal), GFP_KERNEL);
> > + SUM_JOURNAL_SIZE(sbi), GFP_KERNEL);
> > if (!array[i].journal)
> > return -ENOMEM;
> > array[i].seg_type = log_type_to_seg_type(i);
> > diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> > index 07dcbcbeb7c6..8b38f3693b1a 100644
> > --- a/fs/f2fs/segment.h
> > +++ b/fs/f2fs/segment.h
> > @@ -90,12 +90,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))
> >
> > -#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE)
> > +#define SUMS_PER_BLOCK(sbi) ((sbi)->blocksize / F2FS_SUM_BLKSIZE(sbi))
> > #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)
> > + (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK(sbi)))
> > +#define GET_SUM_BLKOFF(sbi, segno) (segno % SUMS_PER_BLOCK(sbi))
> > +#define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
> > + (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * F2FS_SUM_BLKSIZE(sbi))
> >
> > #define GET_SUM_TYPE(footer) ((footer)->entry_type)
> > #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index c4c225e09dc4..253a23a7b67d 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -4080,20 +4080,6 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
> > if (sanity_check_area_boundary(sbi, folio, index))
> > return -EFSCORRUPTED;
> >
> > - /*
> > - * 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;
> > }
> >
> > diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> > index a7880787cad3..394f7af3a102 100644
> > --- a/include/linux/f2fs_fs.h
> > +++ b/include/linux/f2fs_fs.h
> > @@ -17,7 +17,6 @@
> > #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
> > #define F2FS_BLKSIZE PAGE_SIZE /* support only block == 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 */
> >
> > @@ -442,10 +441,8 @@ struct f2fs_sit_block {
> > * from node's page's beginning to get a data block address.
> > * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
> > */
> > -#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)
> >
> > /* a summary entry for a block in a segment */
> > struct f2fs_summary {
> > @@ -468,22 +465,6 @@ struct summary_footer {
> > __le32 check_sum; /* summary checksum */
> > } __packed;
> >
> > -#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))
> > -#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
> > - sizeof(struct nat_journal_entry))
> > -#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
> > - sizeof(struct sit_journal_entry))
> > -#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
> > - sizeof(struct sit_journal_entry))
> > -
> > -/* Reserved area should make size of f2fs_extra_info equals to
> > - * that of nat_journal and sit_journal.
> > - */
> > -#define EXTRA_INFO_RESERVED (SUM_JOURNAL_SIZE - 2 - 8)
> > -
> > /*
> > * frequently updated NAT/SIT entries can be stored in the spare area in
> > * summary blocks
> > @@ -498,9 +479,16 @@ struct nat_journal_entry {
> > struct f2fs_nat_entry ne;
> > } __packed;
> >
> > +/*
> > + * The nat_journal structure is a placeholder whose actual size varies depending
> > + * on the use of packed_ssa. Therefore, it must always be accessed only through
> > + * specific sets of macros, and size calculations should use size-related macros
> > + * instead of sizeof().
> > + * Relevant macros: NAT_JOURNAL_ENTRIES, nat_in_journal, nid_in_journal,
> > + * MAX_NAT_JENTRIES.
> > + */
> > struct nat_journal {
> > - struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
> > - __u8 reserved[NAT_JOURNAL_RESERVED];
> > + struct nat_journal_entry entries[0];
> > } __packed;
> >
> > struct sit_journal_entry {
> > @@ -508,14 +496,21 @@ struct sit_journal_entry {
> > struct f2fs_sit_entry se;
> > } __packed;
> >
> > +/*
> > + * The sit_journal structure is a placeholder whose actual size varies depending
> > + * on the use of packed_ssa. Therefore, it must always be accessed only through
> > + * specific sets of macros, and size calculations should use size-related macros
> > + * instead of sizeof().
> > + * Relevant macros: SIT_JOURNAL_ENTRIES, sit_in_journal, segno_in_journal,
> > + * MAX_SIT_JENTRIES.
> > + */
> > struct sit_journal {
> > - struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
> > - __u8 reserved[SIT_JOURNAL_RESERVED];
> > + struct sit_journal_entry entries[0];
> > } __packed;
> >
> > struct f2fs_extra_info {
> > __le64 kbytes_written;
> > - __u8 reserved[EXTRA_INFO_RESERVED];
> > + __u8 reserved[];
> > } __packed;
> >
> > struct f2fs_journal {
> > @@ -531,11 +526,33 @@ struct f2fs_journal {
> > };
> > } __packed;
> >
> > -/* Block-sized summary block structure */
> > +/*
> > + * Block-sized summary block structure
> > + *
> > + * The f2fs_summary_block structure is a placeholder whose actual size varies
> > + * depending on the use of packed_ssa. Therefore, it must always be accessed
> > + * only through specific sets of macros, and size calculations should use
> > + * size-related macros instead of sizeof().
> > + * Relevant macros: F2FS_SUM_BLKSIZE, ENTRIES_IN_SUM, SUM_ENTRY_SIZE,
> > + * sum_entries, sum_journal, sum_footer.
> > + *
> > + * Summary Block Layout
> > + *
> > + * +-----------------------+ <--- Block Start
> > + * | struct f2fs_summary |
> > + * | entries[0] |
> > + * | ... |
> > + * | entries[N-1] |
> > + * +-----------------------+
> > + * | struct f2fs_journal |
> > + * +-----------------------+
> > + * | struct summary_footer |
> > + * +-----------------------+ <--- Block End
> > + */
> > struct f2fs_summary_block {
> > - struct f2fs_summary entries[ENTRIES_IN_SUM];
> > - struct f2fs_journal journal;
> > - struct summary_footer footer;
> > + struct f2fs_summary entries[0];
> > + // struct f2fs_journal journal;
> > + // struct summary_footer footer;
> > } __packed;
> >
> > /*
>
On 1/10/2026 5:23 AM, Daeho Jeong wrote:
> On Thu, Jan 8, 2026 at 10:52 PM Chao Yu <chao@kernel.org> wrote:
>>
>> On 1/8/2026 9:46 AM, Daeho Jeong wrote:
>>> From: Daeho Jeong <daehojeong@google.com>
>>>
>>> Currently, F2FS requires the packed_ssa feature to be enabled when
>>> utilizing non-4KB block sizes (e.g., 16KB). This restriction limits
>>> the flexibility of filesystem formatting options.
>>>
>>> This patch allows F2FS to support non-4KB block sizes even when the
>>> packed_ssa feature is disabled. It adjusts the SSA calculation logic to
>>> correctly handle summary entries in larger blocks without the packed
>>> layout.
>>
>> Can we consider to add testcases into xfsqa to cover recent revert patch
>> and packed_ssa feature which changes disk layout a bit? not sure, we may
>> miss some corner cases in keep compatibility, e.g. mount old/new image w/
>> new kernel.
>
> Regarding the test cases, I've already verified all combinations
> locally—specifically
> focusing on cross-compatibility between old/new images and the new kernel. The
> results were consistent across the board. While adding them to xfsqa
> is a good idea
> for long-term tracking, I've confirmed that the recent changes don't
> break any of those
> corner cases.
Cool, thanks for the information.
>
>>
>>>
>>> Fixes: 7ee8bc3942f2 ("f2fs: revert summary entry count from 2048 to 512 in 16kb block support")
>>
>> Cc: stable@kernel.org
>>
>>> Signed-off-by: Daeho Jeong <daehojeong@google.com>
>>> ---
>>> fs/f2fs/f2fs.h | 56 +++++++++++++++++++--------
>>> fs/f2fs/gc.c | 23 +++++------
>>> fs/f2fs/node.c | 12 +++---
>>> fs/f2fs/recovery.c | 6 +--
>>> fs/f2fs/segment.c | 86 ++++++++++++++++++++++-------------------
>>> fs/f2fs/segment.h | 10 ++---
>>> fs/f2fs/super.c | 14 -------
>>> include/linux/f2fs_fs.h | 73 ++++++++++++++++++++--------------
>>> 8 files changed, 157 insertions(+), 123 deletions(-)
>>>
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index 20edbb99b814..0ceae7d83a48 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -521,13 +521,36 @@ struct fsync_inode_entry {
>>> #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats))
>>> #define sits_in_cursum(jnl) (le16_to_cpu((jnl)->n_sits))
>>>
>>> -#define nat_in_journal(jnl, i) ((jnl)->nat_j.entries[i].ne)
>>> -#define nid_in_journal(jnl, i) ((jnl)->nat_j.entries[i].nid)
>>> -#define sit_in_journal(jnl, i) ((jnl)->sit_j.entries[i].se)
>>> -#define segno_in_journal(jnl, i) ((jnl)->sit_j.entries[i].segno)
>>> -
>>> -#define MAX_NAT_JENTRIES(jnl) (NAT_JOURNAL_ENTRIES - nats_in_cursum(jnl))
>>> -#define MAX_SIT_JENTRIES(jnl) (SIT_JOURNAL_ENTRIES - sits_in_cursum(jnl))
>>> +#define nat_in_journal(jnl, i) \
>>> + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].ne)
>>> +#define nid_in_journal(jnl, i) \
>>> + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].nid)
>>> +#define sit_in_journal(jnl, i) \
>>> + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].se)
>>> +#define segno_in_journal(jnl, i) \
>>> + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].segno)
>>> +
>>> +#define F2FS_SUM_BLKSIZE(sbi) \
>>> + (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_PACKED_SSA) ? 4096 : (sbi)->blocksize)
>>
>> What about caching F2FS_SUM_BLKSIZE() as sbi->sum_blksize to avoid rundandent
>> calculation in lots of places?
>
> makes sense. Thanks.
>
>>
>>> +#define ENTRIES_IN_SUM(sbi) (F2FS_SUM_BLKSIZE(sbi) / 8)
>>> +#define SUM_ENTRY_SIZE(sbi) (SUMMARY_SIZE * ENTRIES_IN_SUM(sbi))
>>> +#define SUM_JOURNAL_SIZE(sbi) (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE - \
>>> + SUM_ENTRY_SIZE(sbi))
>>> +#define NAT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
>>> + sizeof(struct nat_journal_entry))
>>> +#define SIT_JOURNAL_ENTRIES(sbi) ((SUM_JOURNAL_SIZE(sbi) - 2) / \
>>> + sizeof(struct sit_journal_entry))
>>
>> Ditto?
Oh, I meant we can cache all other frequently used macros into sbi as well,
what do you think?
Thanks,
>>
>> Thanks,
>>
>>> +
>>> +#define sum_entries(sum) ((struct f2fs_summary *)(sum))
>>> +#define sum_journal(sbi, sum) \
>>> + ((struct f2fs_journal *)((char *)(sum) + \
>>> + (ENTRIES_IN_SUM(sbi) * sizeof(struct f2fs_summary))))
>>> +#define sum_footer(sbi, sum) \
>>> + ((struct summary_footer *)((char *)(sum) + F2FS_SUM_BLKSIZE(sbi) - \
>>> + sizeof(struct summary_footer)))
>>> +
>>> +#define MAX_NAT_JENTRIES(sbi, jnl) (NAT_JOURNAL_ENTRIES(sbi) - nats_in_cursum(jnl))
>>> +#define MAX_SIT_JENTRIES(sbi, jnl) (SIT_JOURNAL_ENTRIES(sbi) - sits_in_cursum(jnl))
>>>
>>> static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i)
>>> {
>>> @@ -545,14 +568,6 @@ static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i)
>>> return before;
>>> }
>>>
>>> -static inline bool __has_cursum_space(struct f2fs_journal *journal,
>>> - int size, int type)
>>> -{
>>> - if (type == NAT_JOURNAL)
>>> - return size <= MAX_NAT_JENTRIES(journal);
>>> - return size <= MAX_SIT_JENTRIES(journal);
>>> -}
>>> -
>>> /* for inline stuff */
>>> #define DEF_INLINE_RESERVED_SIZE 1
>>> static inline int get_extra_isize(struct inode *inode);
>>> @@ -2813,6 +2828,14 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
>>> return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
>>> }
>>>
>>> +static inline bool __has_cursum_space(struct f2fs_sb_info *sbi,
>>> + struct f2fs_journal *journal, int size, int type)
>>> +{
>>> + if (type == NAT_JOURNAL)
>>> + return size <= MAX_NAT_JENTRIES(sbi, journal);
>>> + return size <= MAX_SIT_JENTRIES(sbi, journal);
>>> +}
>>> +
>>> extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync);
>>> static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
>>> struct inode *inode, bool is_inode)
>>> @@ -3956,7 +3979,8 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
>>> block_t len);
>>> void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
>>> void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
>>> -int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
>>> +int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
>>> + struct f2fs_journal *journal, int type,
>>> unsigned int val, int alloc);
>>> void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
>>> int f2fs_check_and_fix_write_pointer(struct f2fs_sb_info *sbi);
>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>> index 384fa7e2085b..65c819d08807 100644
>>> --- a/fs/f2fs/gc.c
>>> +++ b/fs/f2fs/gc.c
>>> @@ -1769,8 +1769,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>>>
>>> sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
>>>
>>> - segno = rounddown(segno, SUMS_PER_BLOCK);
>>> - sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK);
>>> + segno = rounddown(segno, SUMS_PER_BLOCK(sbi));
>>> + sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK(sbi));
>>> /* readahead multi ssa blocks those have contiguous address */
>>> if (__is_large_section(sbi))
>>> f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
>>> @@ -1780,17 +1780,17 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>>> while (segno < end_segno) {
>>> struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
>>>
>>> - segno += SUMS_PER_BLOCK;
>>> + segno += SUMS_PER_BLOCK(sbi);
>>> if (IS_ERR(sum_folio)) {
>>> int err = PTR_ERR(sum_folio);
>>>
>>> - end_segno = segno - SUMS_PER_BLOCK;
>>> - segno = rounddown(start_segno, SUMS_PER_BLOCK);
>>> + end_segno = segno - SUMS_PER_BLOCK(sbi);
>>> + segno = rounddown(start_segno, SUMS_PER_BLOCK(sbi));
>>> while (segno < end_segno) {
>>> sum_folio = filemap_get_folio(META_MAPPING(sbi),
>>> GET_SUM_BLOCK(sbi, segno));
>>> folio_put_refs(sum_folio, 2);
>>> - segno += SUMS_PER_BLOCK;
>>> + segno += SUMS_PER_BLOCK(sbi);
>>> }
>>> return err;
>>> }
>>> @@ -1806,8 +1806,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>>> /* find segment summary of victim */
>>> struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
>>> GET_SUM_BLOCK(sbi, segno));
>>> - unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK)
>>> - + SUMS_PER_BLOCK;
>>> + unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK(sbi))
>>> + + SUMS_PER_BLOCK(sbi);
>>>
>>> if (block_end_segno > end_segno)
>>> block_end_segno = end_segno;
>>> @@ -1833,12 +1833,13 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
>>> migrated >= sbi->migration_granularity)
>>> continue;
>>>
>>> - sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno);
>>> - if (type != GET_SUM_TYPE((&sum->footer))) {
>>> + 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 "
>>> "[%d, %d] in SSA and SIT",
>>> cur_segno, type,
>>> - GET_SUM_TYPE((&sum->footer)));
>>> + GET_SUM_TYPE(
>>> + sum_footer(sbi, sum)));
>>> f2fs_stop_checkpoint(sbi, false,
>>> STOP_CP_REASON_CORRUPTED_SUMMARY);
>>> continue;
>>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>>> index 482a362f2625..f78d53ec59d4 100644
>>> --- a/fs/f2fs/node.c
>>> +++ b/fs/f2fs/node.c
>>> @@ -606,7 +606,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
>>> goto retry;
>>> }
>>>
>>> - i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
>>> + i = f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 0);
>>> if (i >= 0) {
>>> ne = nat_in_journal(journal, i);
>>> node_info_from_raw_nat(ni, &ne);
>>> @@ -2937,7 +2937,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
>>> /* scan the node segment */
>>> last_offset = BLKS_PER_SEG(sbi);
>>> addr = START_BLOCK(sbi, segno);
>>> - sum_entry = &sum->entries[0];
>>> + sum_entry = sum_entries(sum);
>>>
>>> for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
>>> nrpages = bio_max_segs(last_offset - i);
>>> @@ -3078,7 +3078,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
>>> * #2, flush nat entries to nat page.
>>> */
>>> if (enabled_nat_bits(sbi, cpc) ||
>>> - !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
>>> + !__has_cursum_space(sbi, journal, set->entry_cnt, NAT_JOURNAL))
>>> to_journal = false;
>>>
>>> if (to_journal) {
>>> @@ -3101,7 +3101,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
>>> f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
>>>
>>> if (to_journal) {
>>> - offset = f2fs_lookup_journal_in_cursum(journal,
>>> + offset = f2fs_lookup_journal_in_cursum(sbi, journal,
>>> NAT_JOURNAL, nid, 1);
>>> f2fs_bug_on(sbi, offset < 0);
>>> raw_ne = &nat_in_journal(journal, offset);
>>> @@ -3172,7 +3172,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
>>> * into nat entry set.
>>> */
>>> if (enabled_nat_bits(sbi, cpc) ||
>>> - !__has_cursum_space(journal,
>>> + !__has_cursum_space(sbi, journal,
>>> nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
>>> remove_nats_in_journal(sbi);
>>>
>>> @@ -3183,7 +3183,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
>>> set_idx = setvec[found - 1]->set + 1;
>>> for (idx = 0; idx < found; idx++)
>>> __adjust_nat_entry_set(setvec[idx], &sets,
>>> - MAX_NAT_JENTRIES(journal));
>>> + MAX_NAT_JENTRIES(sbi, journal));
>>> }
>>>
>>> /* flush dirty nats in nat entry set */
>>> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
>>> index c3415ebb9f50..a6bfc8e759cf 100644
>>> --- a/fs/f2fs/recovery.c
>>> +++ b/fs/f2fs/recovery.c
>>> @@ -514,7 +514,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
>>> struct curseg_info *curseg = CURSEG_I(sbi, i);
>>>
>>> if (curseg->segno == segno) {
>>> - sum = curseg->sum_blk->entries[blkoff];
>>> + sum = sum_entries(curseg->sum_blk)[blkoff];
>>> goto got_it;
>>> }
>>> }
>>> @@ -522,8 +522,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
>>> sum_folio = f2fs_get_sum_folio(sbi, segno);
>>> if (IS_ERR(sum_folio))
>>> return PTR_ERR(sum_folio);
>>> - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno);
>>> - sum = sum_node->entries[blkoff];
>>> + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno);
>>> + sum = sum_entries(sum_node)[blkoff];
>>> f2fs_folio_put(sum_folio, true);
>>> got_it:
>>> /* Use the locked dnode page and inode */
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index c26424f47686..9a73b979b2e6 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -2685,12 +2685,12 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
>>> valid_sum_count += f2fs_curseg_valid_blocks(sbi, i);
>>> }
>>>
>>> - sum_in_page = (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE -
>>> + sum_in_page = (F2FS_SUM_BLKSIZE(sbi) - 2 * SUM_JOURNAL_SIZE(sbi) -
>>> SUM_FOOTER_SIZE) / SUMMARY_SIZE;
>>> if (valid_sum_count <= sum_in_page)
>>> return 1;
>>> else if ((valid_sum_count - sum_in_page) <=
>>> - (PAGE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
>>> + (F2FS_SUM_BLKSIZE(sbi) - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
>>> return 2;
>>> return 3;
>>> }
>>> @@ -2710,7 +2710,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
>>> {
>>> struct folio *folio;
>>>
>>> - if (SUMS_PER_BLOCK == 1)
>>> + if (!f2fs_sb_has_packed_ssa(sbi))
>>> folio = f2fs_grab_meta_folio(sbi, blk_addr);
>>> else
>>> folio = f2fs_get_meta_folio_retry(sbi, blk_addr);
>>> @@ -2728,7 +2728,7 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
>>> {
>>> struct folio *folio;
>>>
>>> - if (SUMS_PER_BLOCK == 1)
>>> + if (!f2fs_sb_has_packed_ssa(sbi))
>>> return f2fs_update_meta_page(sbi, (void *)sum_blk,
>>> GET_SUM_BLOCK(sbi, segno));
>>>
>>> @@ -2736,7 +2736,8 @@ static void write_sum_page(struct f2fs_sb_info *sbi,
>>> if (IS_ERR(folio))
>>> return;
>>>
>>> - memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk));
>>> + memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk,
>>> + F2FS_SUM_BLKSIZE(sbi));
>>> folio_mark_dirty(folio);
>>> f2fs_folio_put(folio, true);
>>> }
>>> @@ -2755,11 +2756,11 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi,
>>> mutex_lock(&curseg->curseg_mutex);
>>>
>>> down_read(&curseg->journal_rwsem);
>>> - memcpy(&dst->journal, curseg->journal, SUM_JOURNAL_SIZE);
>>> + memcpy(sum_journal(sbi, dst), curseg->journal, SUM_JOURNAL_SIZE(sbi));
>>> up_read(&curseg->journal_rwsem);
>>>
>>> - memcpy(dst->entries, src->entries, SUM_ENTRY_SIZE);
>>> - memcpy(&dst->footer, &src->footer, SUM_FOOTER_SIZE);
>>> + memcpy(sum_entries(dst), sum_entries(src), SUM_ENTRY_SIZE(sbi));
>>> + memcpy(sum_footer(sbi, dst), sum_footer(sbi, src), SUM_FOOTER_SIZE);
>>>
>>> mutex_unlock(&curseg->curseg_mutex);
>>>
>>> @@ -2932,7 +2933,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
>>> curseg->next_blkoff = 0;
>>> curseg->next_segno = NULL_SEGNO;
>>>
>>> - sum_footer = &(curseg->sum_blk->footer);
>>> + sum_footer = sum_footer(sbi, curseg->sum_blk);
>>> memset(sum_footer, 0, sizeof(struct summary_footer));
>>>
>>> sanity_check_seg_type(sbi, seg_type);
>>> @@ -3078,11 +3079,11 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
>>> sum_folio = f2fs_get_sum_folio(sbi, new_segno);
>>> if (IS_ERR(sum_folio)) {
>>> /* GC won't be able to use stale summary pages by cp_error */
>>> - memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE);
>>> + memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE(sbi));
>>> return PTR_ERR(sum_folio);
>>> }
>>> - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno);
>>> - memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
>>> + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno);
>>> + memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE(sbi));
>>> f2fs_folio_put(sum_folio, true);
>>> return 0;
>>> }
>>> @@ -3814,7 +3815,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio,
>>>
>>> f2fs_wait_discard_bio(sbi, *new_blkaddr);
>>>
>>> - curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
>>> + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
>>> if (curseg->alloc_type == SSR) {
>>> curseg->next_blkoff = f2fs_find_next_ssr_block(sbi, curseg);
>>> } else {
>>> @@ -4183,7 +4184,7 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
>>> }
>>>
>>> curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
>>> - curseg->sum_blk->entries[curseg->next_blkoff] = *sum;
>>> + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum;
>>>
>>> if (!recover_curseg || recover_newaddr) {
>>> if (!from_gc)
>>> @@ -4303,12 +4304,12 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
>>>
>>> /* Step 1: restore nat cache */
>>> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
>>> - memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE);
>>> + memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE(sbi));
>>>
>>> /* Step 2: restore sit cache */
>>> seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
>>> - memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE);
>>> - offset = 2 * SUM_JOURNAL_SIZE;
>>> + memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE(sbi), SUM_JOURNAL_SIZE(sbi));
>>> + offset = 2 * SUM_JOURNAL_SIZE(sbi);
>>>
>>> /* Step 3: restore summary entries */
>>> for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
>>> @@ -4330,9 +4331,9 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
>>> struct f2fs_summary *s;
>>>
>>> s = (struct f2fs_summary *)(kaddr + offset);
>>> - seg_i->sum_blk->entries[j] = *s;
>>> + sum_entries(seg_i->sum_blk)[j] = *s;
>>> offset += SUMMARY_SIZE;
>>> - if (offset + SUMMARY_SIZE <= PAGE_SIZE -
>>> + if (offset + SUMMARY_SIZE <= F2FS_SUM_BLKSIZE(sbi) -
>>> SUM_FOOTER_SIZE)
>>> continue;
>>>
>>> @@ -4388,7 +4389,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
>>>
>>> if (IS_NODESEG(type)) {
>>> if (__exist_node_summaries(sbi)) {
>>> - struct f2fs_summary *ns = &sum->entries[0];
>>> + struct f2fs_summary *ns = sum_entries(sum);
>>> int i;
>>>
>>> for (i = 0; i < BLKS_PER_SEG(sbi); i++, ns++) {
>>> @@ -4408,11 +4409,13 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
>>>
>>> /* update journal info */
>>> down_write(&curseg->journal_rwsem);
>>> - memcpy(curseg->journal, &sum->journal, SUM_JOURNAL_SIZE);
>>> + memcpy(curseg->journal, sum_journal(sbi, sum), SUM_JOURNAL_SIZE(sbi));
>>> up_write(&curseg->journal_rwsem);
>>>
>>> - memcpy(curseg->sum_blk->entries, sum->entries, SUM_ENTRY_SIZE);
>>> - memcpy(&curseg->sum_blk->footer, &sum->footer, SUM_FOOTER_SIZE);
>>> + memcpy(sum_entries(curseg->sum_blk), sum_entries(sum),
>>> + SUM_ENTRY_SIZE(sbi));
>>> + memcpy(sum_footer(sbi, curseg->sum_blk), sum_footer(sbi, sum),
>>> + SUM_FOOTER_SIZE);
>>> curseg->next_segno = segno;
>>> reset_curseg(sbi, type, 0);
>>> curseg->alloc_type = ckpt->alloc_type[type];
>>> @@ -4456,8 +4459,8 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
>>> }
>>>
>>> /* sanity check for summary blocks */
>>> - if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES ||
>>> - sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) {
>>> + if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES(sbi) ||
>>> + sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES(sbi)) {
>>> f2fs_err(sbi, "invalid journal entries nats %u sits %u",
>>> nats_in_cursum(nat_j), sits_in_cursum(sit_j));
>>> return -EINVAL;
>>> @@ -4481,13 +4484,13 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
>>>
>>> /* Step 1: write nat cache */
>>> seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
>>> - memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE);
>>> - written_size += SUM_JOURNAL_SIZE;
>>> + memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
>>> + written_size += SUM_JOURNAL_SIZE(sbi);
>>>
>>> /* Step 2: write sit cache */
>>> seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
>>> - memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE);
>>> - written_size += SUM_JOURNAL_SIZE;
>>> + memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE(sbi));
>>> + written_size += SUM_JOURNAL_SIZE(sbi);
>>>
>>> /* Step 3: write summary entries */
>>> for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
>>> @@ -4500,7 +4503,7 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
>>> written_size = 0;
>>> }
>>> summary = (struct f2fs_summary *)(kaddr + written_size);
>>> - *summary = seg_i->sum_blk->entries[j];
>>> + *summary = sum_entries(seg_i->sum_blk)[j];
>>> written_size += SUMMARY_SIZE;
>>>
>>> if (written_size + SUMMARY_SIZE <= PAGE_SIZE -
>>> @@ -4545,8 +4548,9 @@ void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
>>> write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
>>> }
>>>
>>> -int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
>>> - unsigned int val, int alloc)
>>> +int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi,
>>> + struct f2fs_journal *journal, int type,
>>> + unsigned int val, int alloc)
>>> {
>>> int i;
>>>
>>> @@ -4555,13 +4559,13 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
>>> if (le32_to_cpu(nid_in_journal(journal, i)) == val)
>>> return i;
>>> }
>>> - if (alloc && __has_cursum_space(journal, 1, NAT_JOURNAL))
>>> + if (alloc && __has_cursum_space(sbi, journal, 1, NAT_JOURNAL))
>>> return update_nats_in_cursum(journal, 1);
>>> } else if (type == SIT_JOURNAL) {
>>> for (i = 0; i < sits_in_cursum(journal); i++)
>>> if (le32_to_cpu(segno_in_journal(journal, i)) == val)
>>> return i;
>>> - if (alloc && __has_cursum_space(journal, 1, SIT_JOURNAL))
>>> + if (alloc && __has_cursum_space(sbi, journal, 1, SIT_JOURNAL))
>>> return update_sits_in_cursum(journal, 1);
>>> }
>>> return -1;
>>> @@ -4709,8 +4713,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
>>> * entries, remove all entries from journal and add and account
>>> * them in sit entry set.
>>> */
>>> - if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL) ||
>>> - !to_journal)
>>> + if (!__has_cursum_space(sbi, journal,
>>> + sit_i->dirty_sentries, SIT_JOURNAL) || !to_journal)
>>> remove_sits_in_journal(sbi);
>>>
>>> /*
>>> @@ -4727,7 +4731,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
>>> unsigned int segno = start_segno;
>>>
>>> if (to_journal &&
>>> - !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL))
>>> + !__has_cursum_space(sbi, journal, ses->entry_cnt,
>>> + SIT_JOURNAL))
>>> to_journal = false;
>>>
>>> if (to_journal) {
>>> @@ -4755,7 +4760,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
>>> }
>>>
>>> if (to_journal) {
>>> - offset = f2fs_lookup_journal_in_cursum(journal,
>>> + offset = f2fs_lookup_journal_in_cursum(sbi, journal,
>>> SIT_JOURNAL, segno, 1);
>>> f2fs_bug_on(sbi, offset < 0);
>>> segno_in_journal(journal, offset) =
>>> @@ -4962,12 +4967,13 @@ static int build_curseg(struct f2fs_sb_info *sbi)
>>>
>>> for (i = 0; i < NO_CHECK_TYPE; i++) {
>>> mutex_init(&array[i].curseg_mutex);
>>> - array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
>>> + array[i].sum_blk = f2fs_kzalloc(sbi, F2FS_SUM_BLKSIZE(sbi),
>>> + GFP_KERNEL);
>>> if (!array[i].sum_blk)
>>> return -ENOMEM;
>>> init_rwsem(&array[i].journal_rwsem);
>>> array[i].journal = f2fs_kzalloc(sbi,
>>> - sizeof(struct f2fs_journal), GFP_KERNEL);
>>> + SUM_JOURNAL_SIZE(sbi), GFP_KERNEL);
>>> if (!array[i].journal)
>>> return -ENOMEM;
>>> array[i].seg_type = log_type_to_seg_type(i);
>>> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
>>> index 07dcbcbeb7c6..8b38f3693b1a 100644
>>> --- a/fs/f2fs/segment.h
>>> +++ b/fs/f2fs/segment.h
>>> @@ -90,12 +90,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))
>>>
>>> -#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE)
>>> +#define SUMS_PER_BLOCK(sbi) ((sbi)->blocksize / F2FS_SUM_BLKSIZE(sbi))
>>> #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)
>>> + (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK(sbi)))
>>> +#define GET_SUM_BLKOFF(sbi, segno) (segno % SUMS_PER_BLOCK(sbi))
>>> +#define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
>>> + (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * F2FS_SUM_BLKSIZE(sbi))
>>>
>>> #define GET_SUM_TYPE(footer) ((footer)->entry_type)
>>> #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>> index c4c225e09dc4..253a23a7b67d 100644
>>> --- a/fs/f2fs/super.c
>>> +++ b/fs/f2fs/super.c
>>> @@ -4080,20 +4080,6 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
>>> if (sanity_check_area_boundary(sbi, folio, index))
>>> return -EFSCORRUPTED;
>>>
>>> - /*
>>> - * 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;
>>> }
>>>
>>> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
>>> index a7880787cad3..394f7af3a102 100644
>>> --- a/include/linux/f2fs_fs.h
>>> +++ b/include/linux/f2fs_fs.h
>>> @@ -17,7 +17,6 @@
>>> #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
>>> #define F2FS_BLKSIZE PAGE_SIZE /* support only block == 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 */
>>>
>>> @@ -442,10 +441,8 @@ struct f2fs_sit_block {
>>> * from node's page's beginning to get a data block address.
>>> * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
>>> */
>>> -#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)
>>>
>>> /* a summary entry for a block in a segment */
>>> struct f2fs_summary {
>>> @@ -468,22 +465,6 @@ struct summary_footer {
>>> __le32 check_sum; /* summary checksum */
>>> } __packed;
>>>
>>> -#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))
>>> -#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
>>> - sizeof(struct nat_journal_entry))
>>> -#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
>>> - sizeof(struct sit_journal_entry))
>>> -#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
>>> - sizeof(struct sit_journal_entry))
>>> -
>>> -/* Reserved area should make size of f2fs_extra_info equals to
>>> - * that of nat_journal and sit_journal.
>>> - */
>>> -#define EXTRA_INFO_RESERVED (SUM_JOURNAL_SIZE - 2 - 8)
>>> -
>>> /*
>>> * frequently updated NAT/SIT entries can be stored in the spare area in
>>> * summary blocks
>>> @@ -498,9 +479,16 @@ struct nat_journal_entry {
>>> struct f2fs_nat_entry ne;
>>> } __packed;
>>>
>>> +/*
>>> + * The nat_journal structure is a placeholder whose actual size varies depending
>>> + * on the use of packed_ssa. Therefore, it must always be accessed only through
>>> + * specific sets of macros, and size calculations should use size-related macros
>>> + * instead of sizeof().
>>> + * Relevant macros: NAT_JOURNAL_ENTRIES, nat_in_journal, nid_in_journal,
>>> + * MAX_NAT_JENTRIES.
>>> + */
>>> struct nat_journal {
>>> - struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
>>> - __u8 reserved[NAT_JOURNAL_RESERVED];
>>> + struct nat_journal_entry entries[0];
>>> } __packed;
>>>
>>> struct sit_journal_entry {
>>> @@ -508,14 +496,21 @@ struct sit_journal_entry {
>>> struct f2fs_sit_entry se;
>>> } __packed;
>>>
>>> +/*
>>> + * The sit_journal structure is a placeholder whose actual size varies depending
>>> + * on the use of packed_ssa. Therefore, it must always be accessed only through
>>> + * specific sets of macros, and size calculations should use size-related macros
>>> + * instead of sizeof().
>>> + * Relevant macros: SIT_JOURNAL_ENTRIES, sit_in_journal, segno_in_journal,
>>> + * MAX_SIT_JENTRIES.
>>> + */
>>> struct sit_journal {
>>> - struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
>>> - __u8 reserved[SIT_JOURNAL_RESERVED];
>>> + struct sit_journal_entry entries[0];
>>> } __packed;
>>>
>>> struct f2fs_extra_info {
>>> __le64 kbytes_written;
>>> - __u8 reserved[EXTRA_INFO_RESERVED];
>>> + __u8 reserved[];
>>> } __packed;
>>>
>>> struct f2fs_journal {
>>> @@ -531,11 +526,33 @@ struct f2fs_journal {
>>> };
>>> } __packed;
>>>
>>> -/* Block-sized summary block structure */
>>> +/*
>>> + * Block-sized summary block structure
>>> + *
>>> + * The f2fs_summary_block structure is a placeholder whose actual size varies
>>> + * depending on the use of packed_ssa. Therefore, it must always be accessed
>>> + * only through specific sets of macros, and size calculations should use
>>> + * size-related macros instead of sizeof().
>>> + * Relevant macros: F2FS_SUM_BLKSIZE, ENTRIES_IN_SUM, SUM_ENTRY_SIZE,
>>> + * sum_entries, sum_journal, sum_footer.
>>> + *
>>> + * Summary Block Layout
>>> + *
>>> + * +-----------------------+ <--- Block Start
>>> + * | struct f2fs_summary |
>>> + * | entries[0] |
>>> + * | ... |
>>> + * | entries[N-1] |
>>> + * +-----------------------+
>>> + * | struct f2fs_journal |
>>> + * +-----------------------+
>>> + * | struct summary_footer |
>>> + * +-----------------------+ <--- Block End
>>> + */
>>> struct f2fs_summary_block {
>>> - struct f2fs_summary entries[ENTRIES_IN_SUM];
>>> - struct f2fs_journal journal;
>>> - struct summary_footer footer;
>>> + struct f2fs_summary entries[0];
>>> + // struct f2fs_journal journal;
>>> + // struct summary_footer footer;
>>> } __packed;
>>>
>>> /*
>>
© 2016 - 2026 Red Hat, Inc.