From: Daeho Jeong <[email protected]>

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 <[email protected]>
---
v2: using sbi->sum_blocksize instead of F2FS_SUM_BLKSIZE()
---
 fs/f2fs/f2fs.h          | 55 ++++++++++++++++++--------
 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         | 16 +-------
 include/linux/f2fs_fs.h | 73 ++++++++++++++++++++--------------
 8 files changed, 158 insertions(+), 123 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 20edbb99b814..cff32c6dbb02 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -521,13 +521,34 @@ 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 ENTRIES_IN_SUM(sbi)    ((sbi)->sum_blocksize / 8)
+#define SUM_ENTRY_SIZE(sbi)    (SUMMARY_SIZE * ENTRIES_IN_SUM(sbi))
+#define SUM_JOURNAL_SIZE(sbi)  ((sbi)->sum_blocksize - 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) + (sbi)->sum_blocksize - \
+       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 +566,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);
@@ -1750,6 +1763,7 @@ struct f2fs_sb_info {
        unsigned int log_sectors_per_block;     /* log2 sectors per block */
        unsigned int log_blocksize;             /* log2 block size */
        unsigned int blocksize;                 /* block size */
+       unsigned int sum_blocksize;             /* summary block size */
        unsigned int root_ino_num;              /* root inode number*/
        unsigned int node_ino_num;              /* node inode number*/
        unsigned int meta_ino_num;              /* meta inode number*/
@@ -2813,6 +2827,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 +3978,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..1968a19f1e3c 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 = (sbi->sum_blocksize - 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)
+               (sbi->sum_blocksize - 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,
+                       sbi->sum_blocksize);
        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 <= sbi->sum_blocksize -
                                                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, 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);
+                               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..0806f9e4ee9c 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 / (sbi)->sum_blocksize)
 #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) * 
(sbi)->sum_blocksize)
 
 #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..cf97a72e96ca 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;
 }
 
@@ -4277,6 +4263,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
                le32_to_cpu(raw_super->log_sectors_per_block);
        sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
        sbi->blocksize = BIT(sbi->log_blocksize);
+       sbi->sum_blocksize = f2fs_sb_has_packed_ssa(sbi) ?
+               4096 : sbi->blocksize;
        sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
        sbi->blocks_per_seg = BIT(sbi->log_blocks_per_seg);
        sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
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.457.g6b5491de43-goog



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to