* [PATCH] f2fs: support non-4KB block size without packed_ssa feature
@ 2026-01-08 1:46 Daeho Jeong
2026-01-09 6:52 ` [f2fs-dev] " Chao Yu
0 siblings, 1 reply; 4+ messages in thread
From: Daeho Jeong @ 2026-01-08 1:46 UTC (permalink / raw)
To: linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong
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
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [f2fs-dev] [PATCH] f2fs: support non-4KB block size without packed_ssa feature 2026-01-08 1:46 [PATCH] f2fs: support non-4KB block size without packed_ssa feature Daeho Jeong @ 2026-01-09 6:52 ` Chao Yu 2026-01-09 21:23 ` Daeho Jeong 0 siblings, 1 reply; 4+ messages in thread From: Chao Yu @ 2026-01-09 6:52 UTC (permalink / raw) To: Daeho Jeong, linux-kernel, linux-f2fs-devel, kernel-team Cc: chao, Daeho Jeong 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; > > /* ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs: support non-4KB block size without packed_ssa feature 2026-01-09 6:52 ` [f2fs-dev] " Chao Yu @ 2026-01-09 21:23 ` Daeho Jeong 2026-01-10 1:32 ` Chao Yu 0 siblings, 1 reply; 4+ messages in thread From: Daeho Jeong @ 2026-01-09 21:23 UTC (permalink / raw) To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel, kernel-team, Daeho Jeong 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; > > > > /* > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs: support non-4KB block size without packed_ssa feature 2026-01-09 21:23 ` Daeho Jeong @ 2026-01-10 1:32 ` Chao Yu 0 siblings, 0 replies; 4+ messages in thread From: Chao Yu @ 2026-01-10 1:32 UTC (permalink / raw) To: Daeho Jeong Cc: chao, linux-kernel, linux-f2fs-devel, kernel-team, Daeho Jeong 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; >>> >>> /* >> ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-01-10 1:32 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-01-08 1:46 [PATCH] f2fs: support non-4KB block size without packed_ssa feature Daeho Jeong 2026-01-09 6:52 ` [f2fs-dev] " Chao Yu 2026-01-09 21:23 ` Daeho Jeong 2026-01-10 1:32 ` Chao Yu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
Powered by JetHome