--- /dev/null
+From e48e16f3e37fac76e2f0c14c58df2b0398a323b0 Mon Sep 17 00:00:00 2001
+From: Daeho Jeong <daehojeong@google.com>
+Date: Sat, 10 Jan 2026 15:54:05 -0800
+Subject: f2fs: support non-4KB block size without packed_ssa feature
+
+From: Daeho Jeong <daehojeong@google.com>
+
+commit e48e16f3e37fac76e2f0c14c58df2b0398a323b0 upstream.
+
+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.
+
+Cc: stable@kernel.org
+Fixes: 7ee8bc3942f2 ("f2fs: revert summary entry count from 2048 to 512 in 16kb block support")
+Signed-off-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h | 52 ++++++++++++++++++++---------
+ fs/f2fs/gc.c | 23 ++++++------
+ fs/f2fs/node.c | 12 +++---
+ fs/f2fs/recovery.c | 6 +--
+ fs/f2fs/segment.c | 86 +++++++++++++++++++++++++-----------------------
+ fs/f2fs/segment.h | 9 ++---
+ fs/f2fs/super.c | 26 ++++++--------
+ include/linux/f2fs_fs.h | 73 +++++++++++++++++++++++++---------------
+ 8 files changed, 165 insertions(+), 122 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -521,13 +521,25 @@ 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 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 sum_entries(sum) ((struct f2fs_summary *)(sum))
++#define sum_journal(sbi, sum) \
++ ((struct f2fs_journal *)((char *)(sum) + \
++ ((sbi)->entries_in_sum * sizeof(struct f2fs_summary))))
++#define sum_footer(sbi, sum) \
++ ((struct summary_footer *)((char *)(sum) + (sbi)->sum_blocksize - \
++ sizeof(struct summary_footer)))
+
+-#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 MAX_NAT_JENTRIES(sbi, jnl) ((sbi)->nat_journal_entries - nats_in_cursum(jnl))
++#define MAX_SIT_JENTRIES(sbi, jnl) ((sbi)->sit_journal_entries - sits_in_cursum(jnl))
+
+ static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i)
+ {
+@@ -545,14 +557,6 @@ static inline int update_sits_in_cursum(
+ 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);
+@@ -1764,6 +1768,15 @@ struct f2fs_sb_info {
+ bool readdir_ra; /* readahead inode in readdir */
+ u64 max_io_bytes; /* max io bytes to merge IOs */
+
++ /* variable summary block units */
++ unsigned int sum_blocksize; /* sum block size */
++ unsigned int sums_per_block; /* sum block count per block */
++ unsigned int entries_in_sum; /* entry count in sum block */
++ unsigned int sum_entry_size; /* total entry size in sum block */
++ unsigned int sum_journal_size; /* journal size in sum block */
++ unsigned int nat_journal_entries; /* nat journal entry count in the journal */
++ unsigned int sit_journal_entries; /* sit journal entry count in the journal */
++
+ block_t user_block_count; /* # of user blocks */
+ block_t total_valid_block_count; /* # of valid blocks */
+ block_t discard_blks; /* discard command candidats */
+@@ -2813,6 +2826,14 @@ static inline block_t __start_sum_addr(s
+ 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 +3977,8 @@ void f2fs_wait_on_block_writeback_range(
+ 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);
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1769,8 +1769,8 @@ static int do_garbage_collect(struct f2f
+
+ 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, sbi->sums_per_block);
++ sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, sbi->sums_per_block);
+ /* readahead multi ssa blocks those have contiguous address */
+ if (__is_large_section(sbi))
+ f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
+@@ -1780,17 +1780,17 @@ static int do_garbage_collect(struct f2f
+ while (segno < end_segno) {
+ struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);
+
+- segno += SUMS_PER_BLOCK;
++ segno += sbi->sums_per_block;
+ 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 - sbi->sums_per_block;
++ segno = rounddown(start_segno, sbi->sums_per_block);
+ 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 += sbi->sums_per_block;
+ }
+ return err;
+ }
+@@ -1806,8 +1806,8 @@ static int do_garbage_collect(struct f2f
+ /* 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, sbi->sums_per_block)
++ + sbi->sums_per_block;
+
+ if (block_end_segno > end_segno)
+ block_end_segno = end_segno;
+@@ -1833,12 +1833,13 @@ static int do_garbage_collect(struct f2f
+ 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;
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -606,7 +606,7 @@ retry:
+ 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);
+@@ -2943,7 +2943,7 @@ int f2fs_restore_node_summary(struct f2f
+ /* 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);
+@@ -3084,7 +3084,7 @@ static int __flush_nat_entry_set(struct
+ * #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) {
+@@ -3107,7 +3107,7 @@ static int __flush_nat_entry_set(struct
+ 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);
+@@ -3178,7 +3178,7 @@ int f2fs_flush_nat_entries(struct f2fs_s
+ * 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);
+
+@@ -3189,7 +3189,7 @@ int f2fs_flush_nat_entries(struct f2fs_s
+ 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 */
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -514,7 +514,7 @@ static int check_index_in_prev_nodes(str
+ 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(str
+ 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 */
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -2685,12 +2685,12 @@ int f2fs_npages_for_summary_flush(struct
+ valid_sum_count += f2fs_curseg_valid_blocks(sbi, i);
+ }
+
+- sum_in_page = (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE -
++ sum_in_page = (sbi->sum_blocksize - 2 * sbi->sum_journal_size -
+ 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)
++ (sbi->sum_blocksize - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
+ return 2;
+ return 3;
+ }
+@@ -2710,7 +2710,7 @@ void f2fs_update_meta_page(struct f2fs_s
+ {
+ 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_s
+ {
+ 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_s
+ 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,
++ sbi->sum_blocksize);
+ folio_mark_dirty(folio);
+ f2fs_folio_put(folio, true);
+ }
+@@ -2755,11 +2756,11 @@ static void write_current_sum_page(struc
+ 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, sbi->sum_journal_size);
+ 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), sbi->sum_entry_size);
++ 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_
+ 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_
+ 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, sbi->sum_entry_size);
+ 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, sbi->sum_entry_size);
+ f2fs_folio_put(sum_folio, true);
+ return 0;
+ }
+@@ -3814,7 +3815,7 @@ int f2fs_allocate_data_block(struct f2fs
+
+ 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_s
+ }
+
+ 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(stru
+
+ /* 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, sbi->sum_journal_size);
+
+ /* 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 + sbi->sum_journal_size, sbi->sum_journal_size);
++ offset = 2 * sbi->sum_journal_size;
+
+ /* Step 3: restore summary entries */
+ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+@@ -4330,9 +4331,9 @@ static int read_compacted_summaries(stru
+ 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 <= sbi->sum_blocksize -
+ SUM_FOOTER_SIZE)
+ continue;
+
+@@ -4388,7 +4389,7 @@ static int read_normal_summaries(struct
+
+ 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
+
+ /* update journal info */
+ down_write(&curseg->journal_rwsem);
+- memcpy(curseg->journal, &sum->journal, SUM_JOURNAL_SIZE);
++ memcpy(curseg->journal, sum_journal(sbi, sum), sbi->sum_journal_size);
+ 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),
++ sbi->sum_entry_size);
++ 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(stru
+ }
+
+ /* 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) > sbi->nat_journal_entries ||
++ sits_in_cursum(sit_j) > sbi->sit_journal_entries) {
+ 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(st
+
+ /* 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, sbi->sum_journal_size);
++ written_size += sbi->sum_journal_size;
+
+ /* 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, sbi->sum_journal_size);
++ written_size += sbi->sum_journal_size;
+
+ /* Step 3: write summary entries */
+ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+@@ -4500,7 +4503,7 @@ static void write_compacted_summaries(st
+ 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 f2
+ 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
+ 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_
+ * 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_
+ 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_
+ }
+
+ 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_i
+
+ 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, sbi->sum_blocksize,
++ 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);
++ sbi->sum_journal_size, GFP_KERNEL);
+ if (!array[i].journal)
+ return -ENOMEM;
+ array[i].seg_type = log_type_to_seg_type(i);
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -90,12 +90,11 @@ static inline void sanity_check_seg_type
+ #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 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 / (sbi)->sums_per_block))
++#define GET_SUM_BLKOFF(sbi, segno) (segno % (sbi)->sums_per_block)
++#define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \
++ (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * (sbi)->sum_blocksize)
+
+ #define GET_SUM_TYPE(footer) ((footer)->entry_type)
+ #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -4080,20 +4080,6 @@ static int sanity_check_raw_super(struct
+ 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;
+ }
+
+@@ -4304,6 +4290,18 @@ static void init_sb_info(struct f2fs_sb_
+ spin_lock_init(&sbi->gc_remaining_trials_lock);
+ atomic64_set(&sbi->current_atomic_write, 0);
+
++ sbi->sum_blocksize = f2fs_sb_has_packed_ssa(sbi) ?
++ 4096 : sbi->blocksize;
++ sbi->sums_per_block = sbi->blocksize / sbi->sum_blocksize;
++ sbi->entries_in_sum = sbi->sum_blocksize / 8;
++ sbi->sum_entry_size = SUMMARY_SIZE * sbi->entries_in_sum;
++ sbi->sum_journal_size = sbi->sum_blocksize - SUM_FOOTER_SIZE -
++ sbi->sum_entry_size;
++ sbi->nat_journal_entries = (sbi->sum_journal_size - 2) /
++ sizeof(struct nat_journal_entry);
++ sbi->sit_journal_entries = (sbi->sum_journal_size - 2) /
++ sizeof(struct sit_journal_entry);
++
+ sbi->dir_level = DEF_DIR_LEVEL;
+ sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
+ sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL;
+--- 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 fields, and size calculations should use
++ * size-related macros instead of sizeof().
++ * Relevant macros: sbi->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 fields, and size calculations should use
++ * size-related macros instead of sizeof().
++ * Relevant macros: sbi->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 fields, and size calculations should
++ * use size-related macros instead of sizeof().
++ * Relevant macros: sbi->sum_blocksize, sbi->entries_in_sum,
++ * sbi->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;
+
+ /*