From nobody Sat Feb 7 22:55:13 2026 Received: from mail-dl1-f52.google.com (mail-dl1-f52.google.com [74.125.82.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D29722BE02C for ; Sat, 10 Jan 2026 23:54:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768089255; cv=none; b=ksLNZOhu2iXz1zFPa0KwdSaC6iUy6JCOBMuwWrAwT3NOmEBQdocsxBKhDNTT4w8G5x2Yj5KcNYL0st5wmv1mOVs6Ytkkafp8nXtu+JJJw+/Nu/L+DSJbgkHmj5bRv27mIYWbrQSnYr4lq+UVJy7e/lVNcWOhccorJ9j/WhXofmE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768089255; c=relaxed/simple; bh=jjgkoYjTESivgZTJ7iJ3u/IwlgViWW2jxf2ZCYB1FNs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=En/YmyxoI6TA8ucjGIJe/AZgQWMupqX+QkuDkaDMG05Ttu+JsbgM+kXkhRVaYzLn8Deh09b+bYF2wxInVq3E0y73HYyqdmQIeEUEysq1MFge4OV/WPbrtMMfHhkhINKvJ9bGXwWAul7Ce6QEMjgHc5wiVn4/LOQgHirVqppSmHI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MaOEPgeE; arc=none smtp.client-ip=74.125.82.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MaOEPgeE" Received: by mail-dl1-f52.google.com with SMTP id a92af1059eb24-11df4458a85so5198192c88.1 for ; Sat, 10 Jan 2026 15:54:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768089252; x=1768694052; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=aOjRxlJDrShDT6RhFnDe4mU4eOX510BVPBsD6io4WZQ=; b=MaOEPgeEjM/CJMP1v/f0ulEM7s+TvbitokrU+dM615vuBQWDJ2Mi6L6PtbPptN6ETD +pyczhQENCosopzrQtwb9ms8pu+vgJS5iy5PTTXcaSv1360VWfT/lU/nOsXv9LcYwzUn 1pZ0CcjfAOsvf2jU34zD4Puvau104BRDi6BNbboIajjVj3iqer33QDow8rmsWTKWU0wd i8S5m4Q2dKPLTOH3mIlPOmQA6Oy6+/bMiCUyt+K2tjkGPUAEllgdd/UfsV+NtZjc+2HI HmWkylkFFt8KxUPAUDkDT6apskWGiuBuIwwOFXsibMy3m+Yhnyd1L0uSsyhYcornQSYB GtNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768089252; x=1768694052; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=aOjRxlJDrShDT6RhFnDe4mU4eOX510BVPBsD6io4WZQ=; b=Q4B6sRBA6uB67IDZML8S70y5hKilt4mOpkgGkVhySza3TTMe8xG5yWvjik0NHPoCOq OrlDcZPuIlt26/dQQ+Jwb3zjNneJtknQjxxMLDpw7uWQZRlQpOVc3EBnFxhKKhGq83VK 0nBnkoY36jTomltENRQpe2NyX28rG3Jqi8saQ4Ml4XB3Ju8ekwr8KgKKCKbJpSzKfWT3 u1i4okyrxAOrjOOQMGJnFJ7sG55tJJdWbWeHTvQgSUYrCHe+uokHEO1p6iUekIWaFND/ c6MeuD5oGhlV21f5omYuNZJc/w2RCS7eD5k2Z3VgyRPa/922mHrTdivUqifUSJDIwE93 UpMw== X-Gm-Message-State: AOJu0YydVS4i0a+JyBHf8XJf9mWNKnZ/1UaPvbarE8lS8PK2SU4eXA9v vBiuJ0wgLpdMjqhtPLhmeB0dyvQAgSO+p/TezSoNjO/4FV5VOXSrm1Ms4bWUPg== X-Gm-Gg: AY/fxX72dk7g1t8LwRTVOQT8fha95MyxtxxlfzEk+nD6kiQQQhhEQGqYnfU6XOJtsQZ t9z3+k8Wsv4FZsY3PQu2FyM+nz9e7mMnkrsZiYmLxeFG3lYFzqnuwRo0B0EvVwkJ9P2+sSMiI4F dfamWnHfAtX4TT02mtoMBQwPYILoVhck1cLgIN8/4ToPJCyJy8ZXeXlxrUakAAyqN9kiCINLKqc O5kDIreuuvFbAIfIYwRrJ+h7NiNE+rYNeZRWD46kUa79XFN/WzP8drYLfjomvkEzTJCap4aPhz0 QdDOirsMqZwv/7DjrpmhoXM93gkPrRcFuHxdmLCMN+OghHJ7UCPzfpuRv7LNjWmsfpBAiy+ccQg 7IRT3pttnmwG0GzHuMCLXssAoM2pR4yCs8wL1Gjcsn6JG/H4JhcFYMpTAEEfHxaRQS0vDJN61Rf QI+fa7+8rdHcYMLtAdieHiYTEfeJPEys235p3T9y7+ksif3PsCynPT/d2D48uq1/3006un+3bvr JUt7q2M9csztWG6FyiDgr3KUt7jqAJcps0JzYI= X-Google-Smtp-Source: AGHT+IFi8UBeqPjhl/dgg/yfdtbwvfdiU4UdULUZ7XIpw2bPV2iZgRpF4N3AWou8shYhRu6EDwZApQ== X-Received: by 2002:a05:7022:438d:b0:11a:641f:ba11 with SMTP id a92af1059eb24-121f8b40c77mr10939062c88.29.1768089251327; Sat, 10 Jan 2026 15:54:11 -0800 (PST) Received: from daehojeong-desktop.mtv.corp.google.com ([2a00:79e0:2e7c:8:4460:6a9c:710a:ac5f]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-121f243ed62sm21479271c88.5.2026.01.10.15.54.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 Jan 2026 15:54:10 -0800 (PST) From: Daeho Jeong To: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, kernel-team@android.com Cc: Daeho Jeong Subject: [PATCH v3] f2fs: support non-4KB block size without packed_ssa feature Date: Sat, 10 Jan 2026 15:54:05 -0800 Message-ID: <20260110235405.2783424-1-daeho43@gmail.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Daeho Jeong 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 Reviewed-by: Chao Yu --- v3: save all calculated summary block related macro values into sbi and reuse them v2: using sbi->sum_blocksize instead of F2FS_SUM_BLKSIZE() --- fs/f2fs/f2fs.h | 54 ++++++++++++++++++-------- 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, 166 insertions(+), 123 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 20edbb99b814..027fc4067119 100644 --- 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)) =20 -#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 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(sbi, jnl) ((sbi)->nat_journal_entries - nats_in_c= ursum(jnl)) +#define MAX_SIT_JENTRIES(sbi, jnl) ((sbi)->sit_journal_entries - sits_in_c= ursum(jnl)) =20 static inline int update_nats_in_cursum(struct f2fs_journal *journal, int = i) { @@ -545,14 +557,6 @@ static inline int update_sits_in_cursum(struct f2fs_jo= urnal *journal, int i) return before; } =20 -static inline bool __has_cursum_space(struct f2fs_journal *journal, - int size, int type) -{ - if (type =3D=3D NAT_JOURNAL) - return size <=3D MAX_NAT_JENTRIES(journal); - return size <=3D 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 */ =20 + /* 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 journ= al */ + unsigned int sit_journal_entries; /* sit journal entry count in the journ= al */ + 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(struct f2fs_s= b_info *sbi) return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum); } =20 +static inline bool __has_cursum_space(struct f2fs_sb_info *sbi, + struct f2fs_journal *journal, int size, int type) +{ + if (type =3D=3D NAT_JOURNAL) + return size <=3D MAX_NAT_JENTRIES(sbi, journal); + return size <=3D 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(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 *c= pc); 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..20da9a1336c5 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1769,8 +1769,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sb= i, =20 sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); =20 - segno =3D rounddown(segno, SUMS_PER_BLOCK); - sum_blk_cnt =3D DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK); + segno =3D rounddown(segno, sbi->sums_per_block); + sum_blk_cnt =3D 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 f2fs_sb_info *= sbi, while (segno < end_segno) { struct folio *sum_folio =3D f2fs_get_sum_folio(sbi, segno); =20 - segno +=3D SUMS_PER_BLOCK; + segno +=3D sbi->sums_per_block; if (IS_ERR(sum_folio)) { int err =3D PTR_ERR(sum_folio); =20 - end_segno =3D segno - SUMS_PER_BLOCK; - segno =3D rounddown(start_segno, SUMS_PER_BLOCK); + end_segno =3D segno - sbi->sums_per_block; + segno =3D rounddown(start_segno, sbi->sums_per_block); while (segno < end_segno) { sum_folio =3D filemap_get_folio(META_MAPPING(sbi), GET_SUM_BLOCK(sbi, segno)); folio_put_refs(sum_folio, 2); - segno +=3D SUMS_PER_BLOCK; + segno +=3D sbi->sums_per_block; } return err; } @@ -1806,8 +1806,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sb= i, /* find segment summary of victim */ struct folio *sum_folio =3D filemap_get_folio(META_MAPPING(sbi), GET_SUM_BLOCK(sbi, segno)); - unsigned int block_end_segno =3D rounddown(segno, SUMS_PER_BLOCK) - + SUMS_PER_BLOCK; + unsigned int block_end_segno =3D rounddown(segno, sbi->sums_per_block) + + sbi->sums_per_block; =20 if (block_end_segno > end_segno) block_end_segno =3D end_segno; @@ -1833,12 +1833,13 @@ static int do_garbage_collect(struct f2fs_sb_info *= sbi, migrated >=3D sbi->migration_granularity) continue; =20 - sum =3D SUM_BLK_PAGE_ADDR(sum_folio, cur_segno); - if (type !=3D GET_SUM_TYPE((&sum->footer))) { + sum =3D SUM_BLK_PAGE_ADDR(sbi, sum_folio, cur_segno); + if (type !=3D 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; } =20 - i =3D f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0); + i =3D f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 0); if (i >=3D 0) { ne =3D 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 *sb= i, /* scan the node segment */ last_offset =3D BLKS_PER_SEG(sbi); addr =3D START_BLOCK(sbi, segno); - sum_entry =3D &sum->entries[0]; + sum_entry =3D sum_entries(sum); =20 for (i =3D 0; i < last_offset; i +=3D nrpages, addr +=3D nrpages) { nrpages =3D 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 =3D false; =20 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) =3D=3D NEW_ADDR); =20 if (to_journal) { - offset =3D f2fs_lookup_journal_in_cursum(journal, + offset =3D f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 1); f2fs_bug_on(sbi, offset < 0); raw_ne =3D &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); =20 @@ -3183,7 +3183,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, = struct cp_control *cpc) set_idx =3D setvec[found - 1]->set + 1; for (idx =3D 0; idx < found; idx++) __adjust_nat_entry_set(setvec[idx], &sets, - MAX_NAT_JENTRIES(journal)); + MAX_NAT_JENTRIES(sbi, journal)); } =20 /* 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_inf= o *sbi, struct curseg_info *curseg =3D CURSEG_I(sbi, i); =20 if (curseg->segno =3D=3D segno) { - sum =3D curseg->sum_blk->entries[blkoff]; + sum =3D sum_entries(curseg->sum_blk)[blkoff]; goto got_it; } } @@ -522,8 +522,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_inf= o *sbi, sum_folio =3D f2fs_get_sum_folio(sbi, segno); if (IS_ERR(sum_folio)) return PTR_ERR(sum_folio); - sum_node =3D SUM_BLK_PAGE_ADDR(sum_folio, segno); - sum =3D sum_node->entries[blkoff]; + sum_node =3D SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno); + sum =3D 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..f317abebdb92 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2685,12 +2685,12 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_in= fo *sbi, bool for_ra) valid_sum_count +=3D f2fs_curseg_valid_blocks(sbi, i); } =20 - sum_in_page =3D (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE - + sum_in_page =3D (sbi->sum_blocksize - 2 * sbi->sum_journal_size - SUM_FOOTER_SIZE) / SUMMARY_SIZE; if (valid_sum_count <=3D sum_in_page) return 1; else if ((valid_sum_count - sum_in_page) <=3D - (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; =20 - if (SUMS_PER_BLOCK =3D=3D 1) + if (!f2fs_sb_has_packed_ssa(sbi)) folio =3D f2fs_grab_meta_folio(sbi, blk_addr); else folio =3D 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; =20 - if (SUMS_PER_BLOCK =3D=3D 1) + if (!f2fs_sb_has_packed_ssa(sbi)) return f2fs_update_meta_page(sbi, (void *)sum_blk, GET_SUM_BLOCK(sbi, segno)); =20 @@ -2736,7 +2736,8 @@ static void write_sum_page(struct f2fs_sb_info *sbi, if (IS_ERR(folio)) return; =20 - 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_i= nfo *sbi, mutex_lock(&curseg->curseg_mutex); =20 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); =20 - 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); =20 mutex_unlock(&curseg->curseg_mutex); =20 @@ -2932,7 +2933,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, in= t type, int modified) curseg->next_blkoff =3D 0; curseg->next_segno =3D NULL_SEGNO; =20 - sum_footer =3D &(curseg->sum_blk->footer); + sum_footer =3D sum_footer(sbi, curseg->sum_blk); memset(sum_footer, 0, sizeof(struct summary_footer)); =20 sanity_check_seg_type(sbi, seg_type); @@ -3078,11 +3079,11 @@ static int change_curseg(struct f2fs_sb_info *sbi, = int type) sum_folio =3D 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 =3D SUM_BLK_PAGE_ADDR(sum_folio, new_segno); - memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); + sum_node =3D 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_sb_info *sbi= , struct folio *folio, =20 f2fs_wait_discard_bio(sbi, *new_blkaddr); =20 - curseg->sum_blk->entries[curseg->next_blkoff] =3D *sum; + sum_entries(curseg->sum_blk)[curseg->next_blkoff] =3D *sum; if (curseg->alloc_type =3D=3D SSR) { curseg->next_blkoff =3D 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, } =20 curseg->next_blkoff =3D GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr); - curseg->sum_blk->entries[curseg->next_blkoff] =3D *sum; + sum_entries(curseg->sum_blk)[curseg->next_blkoff] =3D *sum; =20 if (!recover_curseg || recover_newaddr) { if (!from_gc) @@ -4303,12 +4304,12 @@ static int read_compacted_summaries(struct f2fs_sb_= info *sbi) =20 /* Step 1: restore nat cache */ seg_i =3D CURSEG_I(sbi, CURSEG_HOT_DATA); - memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE); + memcpy(seg_i->journal, kaddr, sbi->sum_journal_size); =20 /* Step 2: restore sit cache */ seg_i =3D CURSEG_I(sbi, CURSEG_COLD_DATA); - memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE); - offset =3D 2 * SUM_JOURNAL_SIZE; + memcpy(seg_i->journal, kaddr + sbi->sum_journal_size, sbi->sum_journal_si= ze); + offset =3D 2 * sbi->sum_journal_size; =20 /* Step 3: restore summary entries */ for (i =3D CURSEG_HOT_DATA; i <=3D CURSEG_COLD_DATA; i++) { @@ -4330,9 +4331,9 @@ static int read_compacted_summaries(struct f2fs_sb_in= fo *sbi) struct f2fs_summary *s; =20 s =3D (struct f2fs_summary *)(kaddr + offset); - seg_i->sum_blk->entries[j] =3D *s; + sum_entries(seg_i->sum_blk)[j] =3D *s; offset +=3D SUMMARY_SIZE; - if (offset + SUMMARY_SIZE <=3D PAGE_SIZE - + if (offset + SUMMARY_SIZE <=3D sbi->sum_blocksize - SUM_FOOTER_SIZE) continue; =20 @@ -4388,7 +4389,7 @@ static int read_normal_summaries(struct f2fs_sb_info = *sbi, int type) =20 if (IS_NODESEG(type)) { if (__exist_node_summaries(sbi)) { - struct f2fs_summary *ns =3D &sum->entries[0]; + struct f2fs_summary *ns =3D sum_entries(sum); int i; =20 for (i =3D 0; i < BLKS_PER_SEG(sbi); i++, ns++) { @@ -4408,11 +4409,13 @@ static int read_normal_summaries(struct f2fs_sb_inf= o *sbi, int type) =20 /* 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); =20 - 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 =3D segno; reset_curseg(sbi, type, 0); curseg->alloc_type =3D ckpt->alloc_type[type]; @@ -4456,8 +4459,8 @@ static int restore_curseg_summaries(struct f2fs_sb_in= fo *sbi) } =20 /* 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(struct f2fs_s= b_info *sbi, block_t blkaddr) =20 /* Step 1: write nat cache */ seg_i =3D CURSEG_I(sbi, CURSEG_HOT_DATA); - memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE); - written_size +=3D SUM_JOURNAL_SIZE; + memcpy(kaddr, seg_i->journal, sbi->sum_journal_size); + written_size +=3D sbi->sum_journal_size; =20 /* Step 2: write sit cache */ seg_i =3D CURSEG_I(sbi, CURSEG_COLD_DATA); - memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE); - written_size +=3D SUM_JOURNAL_SIZE; + memcpy(kaddr + written_size, seg_i->journal, sbi->sum_journal_size); + written_size +=3D sbi->sum_journal_size; =20 /* Step 3: write summary entries */ for (i =3D CURSEG_HOT_DATA; i <=3D CURSEG_COLD_DATA; i++) { @@ -4500,7 +4503,7 @@ static void write_compacted_summaries(struct f2fs_sb_= info *sbi, block_t blkaddr) written_size =3D 0; } summary =3D (struct f2fs_summary *)(kaddr + written_size); - *summary =3D seg_i->sum_blk->entries[j]; + *summary =3D sum_entries(seg_i->sum_blk)[j]; written_size +=3D SUMMARY_SIZE; =20 if (written_size + SUMMARY_SIZE <=3D PAGE_SIZE - @@ -4545,8 +4548,9 @@ void f2fs_write_node_summaries(struct f2fs_sb_info *s= bi, block_t start_blk) write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); } =20 -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; =20 @@ -4555,13 +4559,13 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journ= al *journal, int type, if (le32_to_cpu(nid_in_journal(journal, i)) =3D=3D 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 =3D=3D SIT_JOURNAL) { for (i =3D 0; i < sits_in_cursum(journal); i++) if (le32_to_cpu(segno_in_journal(journal, i)) =3D=3D 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); =20 /* @@ -4727,7 +4731,8 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi,= struct cp_control *cpc) unsigned int segno =3D start_segno; =20 if (to_journal && - !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL)) + !__has_cursum_space(sbi, journal, ses->entry_cnt, + SIT_JOURNAL)) to_journal =3D false; =20 if (to_journal) { @@ -4755,7 +4760,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi,= struct cp_control *cpc) } =20 if (to_journal) { - offset =3D f2fs_lookup_journal_in_cursum(journal, + offset =3D f2fs_lookup_journal_in_cursum(sbi, journal, SIT_JOURNAL, segno, 1); f2fs_bug_on(sbi, offset < 0); segno_in_journal(journal, offset) =3D @@ -4962,12 +4967,13 @@ static int build_curseg(struct f2fs_sb_info *sbi) =20 for (i =3D 0; i < NO_CHECK_TYPE; i++) { mutex_init(&array[i].curseg_mutex); - array[i].sum_blk =3D f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL); + array[i].sum_blk =3D f2fs_kzalloc(sbi, sbi->sum_blocksize, + GFP_KERNEL); if (!array[i].sum_blk) return -ENOMEM; init_rwsem(&array[i].journal_rwsem); array[i].journal =3D 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 =3D log_type_to_seg_type(i); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 07dcbcbeb7c6..3094f2de37b6 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -90,12 +90,11 @@ static inline void sanity_check_seg_type(struct f2fs_sb= _info *sbi, #define GET_ZONE_FROM_SEG(sbi, segno) \ GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno)) =20 -#define 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) =20 #define GET_SUM_TYPE(footer) ((footer)->entry_type) #define SET_SUM_TYPE(footer, type) ((footer)->entry_type =3D (type)) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index c4c225e09dc4..554ccd1990df 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4080,20 +4080,6 @@ static int sanity_check_raw_super(struct f2fs_sb_inf= o *sbi, if (sanity_check_area_boundary(sbi, folio, index)) return -EFSCORRUPTED; =20 - /* - * Check for legacy summary layout on 16KB+ block devices. - * Modern f2fs-tools packs multiple 4KB summary areas into one block, - * whereas legacy versions used one block per summary, leading - * to a much larger SSA. - */ - if (SUMS_PER_BLOCK > 1 && - !(__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_PACKED_SSA))) { - f2fs_info(sbi, "Error: Device formatted with a legacy version. " - "Please reformat with a tool supporting the packed ssa " - "feature for block sizes larger than 4kb."); - return -EOPNOTSUPP; - } - return 0; } =20 @@ -4304,6 +4290,18 @@ static void init_sb_info(struct f2fs_sb_info *sbi) spin_lock_init(&sbi->gc_remaining_trials_lock); atomic64_set(&sbi->current_atomic_write, 0); =20 + sbi->sum_blocksize =3D f2fs_sb_has_packed_ssa(sbi) ? + 4096 : sbi->blocksize; + sbi->sums_per_block =3D sbi->blocksize / sbi->sum_blocksize; + sbi->entries_in_sum =3D sbi->sum_blocksize / 8; + sbi->sum_entry_size =3D SUMMARY_SIZE * sbi->entries_in_sum; + sbi->sum_journal_size =3D sbi->sum_blocksize - SUM_FOOTER_SIZE - + sbi->sum_entry_size; + sbi->nat_journal_entries =3D (sbi->sum_journal_size - 2) / + sizeof(struct nat_journal_entry); + sbi->sit_journal_entries =3D (sbi->sum_journal_size - 2) / + sizeof(struct sit_journal_entry); + sbi->dir_level =3D DEF_DIR_LEVEL; sbi->interval_time[CP_TIME] =3D DEF_CP_INTERVAL; sbi->interval_time[REQ_TIME] =3D DEF_IDLE_INTERVAL; diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index a7880787cad3..dc41722fcc9d 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 sect= or/blk */ #define F2FS_BLKSIZE PAGE_SIZE /* support only block =3D=3D page */ #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ -#define F2FS_SUM_BLKSIZE 4096 /* only support 4096 byte sum block */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ #define F2FS_EXTENSION_LEN 8 /* max size of extension */ =20 @@ -442,10 +441,8 @@ struct f2fs_sit_block { * from node's page's beginning to get a data block address. * ex) data_blkaddr =3D (block_t)(nodepage_start_address + ofs_in_node) */ -#define ENTRIES_IN_SUM (F2FS_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) =20 /* 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; =20 -#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; =20 +/* + * The nat_journal structure is a placeholder whose actual size varies dep= ending + * on the use of packed_ssa. Therefore, it must always be accessed only th= rough + * 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; =20 struct sit_journal_entry { @@ -508,14 +496,21 @@ struct sit_journal_entry { struct f2fs_sit_entry se; } __packed; =20 +/* + * The sit_journal structure is a placeholder whose actual size varies dep= ending + * on the use of packed_ssa. Therefore, it must always be accessed only th= rough + * 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; =20 struct f2fs_extra_info { __le64 kbytes_written; - __u8 reserved[EXTRA_INFO_RESERVED]; + __u8 reserved[]; } __packed; =20 struct f2fs_journal { @@ -531,11 +526,33 @@ struct f2fs_journal { }; } __packed; =20 -/* Block-sized summary block structure */ +/* + * Block-sized summary block structure + * + * The f2fs_summary_block structure is a placeholder whose actual size var= ies + * depending on the use of packed_ssa. Therefore, it must always be access= ed + * 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; =20 /* --=20 2.52.0.457.g6b5491de43-goog