* [f2fs-dev] [PATCH v7 01/11] f2fs: initialize sb_info early in f2fs_fill_super
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
@ 2026-08-31 22:05 ` Kelvin Zhang
2026-09-01 0:48 ` Chao Yu via Linux-f2fs-devel
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 02/11] f2fs: describe SIT block layout dynamically Kelvin Zhang
` (9 subsequent siblings)
10 siblings, 1 reply; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:05 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
Previously, init_sb_info() was invoked late in f2fs_fill_super(), after
processing superblock error tracking, mount options, and sb->s_maxbytes.
However, read_raw_super_block() reads the superblock folio directly
from the block device mapping using folio page offsets. This makes the
initial static sb_set_blocksize(sb, F2FS_BLKSIZE) call redundant.
Move init_sb_info() to execute immediately after sbi->raw_super is
attached, allowing the block device block size to be set dynamically via
sb_set_blocksize(sb, sbi->blocksize).
This early initialization also prepares for upcoming patches that add
dynamically computed filesystem geometry fields, such as
sbi->addrs_per_block and sbi->nids_per_block, to init_sb_info(). These
fields are required by earlier initialization steps, including mount option
consistency checks and sb->s_maxbytes computation.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/super.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 253a579e9d5b..2d9f5b77f815 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -5125,12 +5125,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
}
mutex_init(&sbi->flush_lock);
- /* set a block size */
- if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) {
- f2fs_err(sbi, "unable to set blocksize");
- goto free_sbi;
- }
-
err = read_raw_super_block(sbi, &raw_super, &valid_super_block,
&recovery);
if (err)
@@ -5138,6 +5132,14 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_fs_info = sbi;
sbi->raw_super = raw_super;
+ init_sb_info(sbi);
+
+ /* set a block size */
+ if (!sb_set_blocksize(sb, sbi->blocksize)) {
+ f2fs_err(sbi, "unable to set blocksize %u", sbi->blocksize);
+ err = -EINVAL;
+ goto free_sb_buf;
+ }
sbi->max_atc_write_bio_size = UINT_MAX;
INIT_WORK(&sbi->s_error_work, f2fs_record_error_work);
@@ -5217,8 +5219,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
if (err)
goto free_bio_info;
- init_sb_info(sbi);
-
err = f2fs_init_iostat(sbi);
if (err)
goto free_bio_info;
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 01/11] f2fs: initialize sb_info early in f2fs_fill_super
2026-08-31 22:05 ` [f2fs-dev] [PATCH v7 01/11] f2fs: initialize sb_info early in f2fs_fill_super Kelvin Zhang
@ 2026-09-01 0:48 ` Chao Yu via Linux-f2fs-devel
2026-09-01 16:38 ` Xinping Zhang
0 siblings, 1 reply; 30+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2026-09-01 0:48 UTC (permalink / raw)
To: Kelvin Zhang, linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
On 9/1/26 06:05, Kelvin Zhang wrote:
> Previously, init_sb_info() was invoked late in f2fs_fill_super(), after
> processing superblock error tracking, mount options, and sb->s_maxbytes.
>
> However, read_raw_super_block() reads the superblock folio directly
> from the block device mapping using folio page offsets. This makes the
> initial static sb_set_blocksize(sb, F2FS_BLKSIZE) call redundant.
>
> Move init_sb_info() to execute immediately after sbi->raw_super is
> attached, allowing the block device block size to be set dynamically via
> sb_set_blocksize(sb, sbi->blocksize).
>
> This early initialization also prepares for upcoming patches that add
> dynamically computed filesystem geometry fields, such as
> sbi->addrs_per_block and sbi->nids_per_block, to init_sb_info(). These
> fields are required by earlier initialization steps, including mount option
> consistency checks and sb->s_maxbytes computation.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/super.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 253a579e9d5b..2d9f5b77f815 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -5125,12 +5125,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> }
> mutex_init(&sbi->flush_lock);
>
> - /* set a block size */
> - if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) {
> - f2fs_err(sbi, "unable to set blocksize");
> - goto free_sbi;
> - }
> -
> err = read_raw_super_block(sbi, &raw_super, &valid_super_block,
> &recovery);
> if (err)
> @@ -5138,6 +5132,14 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
>
> sb->s_fs_info = sbi;
> sbi->raw_super = raw_super;
> + init_sb_info(sbi);
> +
> + /* set a block size */
> + if (!sb_set_blocksize(sb, sbi->blocksize)) {
It's better to keep unlikely.
if (unlikely(!sb_set_blocksize(sb, sbi->blocksize))) {
Thanks,
> + f2fs_err(sbi, "unable to set blocksize %u", sbi->blocksize);
> + err = -EINVAL;
> + goto free_sb_buf;
> + }
> sbi->max_atc_write_bio_size = UINT_MAX;
>
> INIT_WORK(&sbi->s_error_work, f2fs_record_error_work);
> @@ -5217,8 +5219,6 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> if (err)
> goto free_bio_info;
>
> - init_sb_info(sbi);
> -
> err = f2fs_init_iostat(sbi);
> if (err)
> goto free_bio_info;
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 02/11] f2fs: describe SIT block layout dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
2026-08-31 22:05 ` [f2fs-dev] [PATCH v7 01/11] f2fs: initialize sb_info early in f2fs_fill_super Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 03/11] f2fs: describe NAT " Kelvin Zhang
` (8 subsequent siblings)
10 siblings, 0 replies; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
An SIT block consists of an on-disk array of struct f2fs_sit_entry elements
whose total capacity depends on the filesystem block size. The existing
fixed SIT_ENTRY_PER_BLOCK macro hardcodes a 4KB block size.
Convert the entries array in struct f2fs_sit_block into a C flexible array
member, and calculate sbi->sit_entries_per_block dynamically in
init_sb_info().
Parameterize SIT indexing helpers (SIT_ENTRY_PER_BLOCK, SIT_BLOCK_OFFSET,
SIT_BLK_CNT, and f2fs_start_segno) to take struct f2fs_sb_info *sbi, and
update all call sites across segment management, checkpointing, and mount.
This is a layout-only change; valid 4KB filesystems retain identical
runtime geometry and behavior.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/checkpoint.c | 2 +-
fs/f2fs/f2fs.h | 3 +++
fs/f2fs/segment.c | 15 ++++++++-------
fs/f2fs/segment.h | 22 +++++++++++++---------
fs/f2fs/super.c | 4 +++-
include/linux/f2fs_fs.h | 9 ++++++---
6 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 4b59f30ef45d..47c4a5c83a70 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -487,7 +487,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
goto out;
/* get sit block addr */
fio.new_blkaddr = current_sit_addr(sbi,
- blkno * SIT_ENTRY_PER_BLOCK);
+ blkno * SIT_ENTRY_PER_BLOCK(sbi));
break;
case META_SSA:
case META_CP:
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 16720f1f0a9c..035863d513ab 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1863,6 +1863,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 sit_entries_per_block; /* SIT entries in a block */
unsigned int root_ino_num; /* root inode number*/
unsigned int node_ino_num; /* node inode number*/
unsigned int meta_ino_num; /* meta inode number*/
@@ -2251,6 +2252,8 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
return F2FS_M_SB(folio->mapping);
}
+#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
+
static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
{
return (struct f2fs_super_block *)(sbi->raw_super);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 1e7e745be71d..b3bf1b62cdad 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4708,7 +4708,7 @@ static struct folio *get_next_sit_folio(struct f2fs_sb_info *sbi,
seg_info_to_sit_folio(sbi, folio, start);
folio_mark_dirty(folio);
- set_to_next_sit(sit_i, start);
+ set_to_next_sit(sbi, sit_i, start);
return folio;
}
@@ -4747,10 +4747,11 @@ static void adjust_sit_entry_set(struct sit_entry_set *ses,
list_move_tail(&ses->set_list, head);
}
-static void add_sit_entry(unsigned int segno, struct list_head *head)
+static void add_sit_entry(struct f2fs_sb_info *sbi, unsigned int segno,
+ struct list_head *head)
{
struct sit_entry_set *ses;
- unsigned int start_segno = START_SEGNO(segno);
+ unsigned int start_segno = f2fs_start_segno(sbi, segno);
list_for_each_entry(ses, head, set_list) {
if (ses->start_segno == start_segno) {
@@ -4775,7 +4776,7 @@ static void add_sits_in_set(struct f2fs_sb_info *sbi)
unsigned int segno;
for_each_set_bit(segno, bitmap, MAIN_SEGS(sbi))
- add_sit_entry(segno, set_list);
+ add_sit_entry(sbi, segno, set_list);
}
static void remove_sits_in_journal(struct f2fs_sb_info *sbi)
@@ -4793,7 +4794,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info *sbi)
dirtied = __mark_sit_entry_dirty(sbi, segno);
if (!dirtied)
- add_sit_entry(segno, &SM_I(sbi)->sit_entry_set);
+ add_sit_entry(sbi, segno, &SM_I(sbi)->sit_entry_set);
}
update_sits_in_cursum(journal, -i);
up_write(&curseg->journal_rwsem);
@@ -4843,7 +4844,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
struct folio *folio = NULL;
struct f2fs_sit_block *raw_sit = NULL;
unsigned int start_segno = ses->start_segno;
- unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK,
+ unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK(sbi),
(unsigned long)MAIN_SEGS(sbi));
unsigned int segno = start_segno;
@@ -5008,7 +5009,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
sit_i->written_valid_blocks = 0;
sit_i->bitmap_size = sit_bitmap_size;
sit_i->dirty_sentries = 0;
- sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
+ sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK(sbi);
sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
sit_i->mounted_time = ktime_get_boottime_seconds();
init_rwsem(&sit_i->sentry_lock);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 5949aa5200ac..534e376cbc92 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -102,12 +102,15 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
#define SIT_ENTRY_OFFSET(sit_i, segno) \
((segno) % (sit_i)->sents_per_block)
-#define SIT_BLOCK_OFFSET(segno) \
- ((segno) / SIT_ENTRY_PER_BLOCK)
-#define START_SEGNO(segno) \
- (SIT_BLOCK_OFFSET(segno) * SIT_ENTRY_PER_BLOCK)
+#define SIT_BLOCK_OFFSET(sbi, segno) \
+ ((segno) / SIT_ENTRY_PER_BLOCK(sbi))
+static inline unsigned int
+f2fs_start_segno(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+ return SIT_BLOCK_OFFSET(sbi, segno) * SIT_ENTRY_PER_BLOCK(sbi);
+}
#define SIT_BLK_CNT(sbi) \
- DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK)
+ DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK(sbi))
#define f2fs_bitmap_size(nr) \
(BITS_TO_LONGS(nr) * sizeof(unsigned long))
@@ -424,7 +427,7 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
struct f2fs_sit_block *raw_sit;
struct seg_entry *se;
struct f2fs_sit_entry *rs;
- unsigned int end = min(start + SIT_ENTRY_PER_BLOCK,
+ unsigned int end = min(start + SIT_ENTRY_PER_BLOCK(sbi),
(unsigned long)MAIN_SEGS(sbi));
int i;
@@ -869,7 +872,7 @@ static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
unsigned int start)
{
struct sit_info *sit_i = SIT_I(sbi);
- unsigned int offset = SIT_BLOCK_OFFSET(start);
+ unsigned int offset = SIT_BLOCK_OFFSET(sbi, start);
block_t blk_addr = sit_i->sit_base_addr + offset;
f2fs_bug_on(sbi, !valid_main_segno(sbi, start));
@@ -894,9 +897,10 @@ static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
return block_addr + sit_i->sit_base_addr;
}
-static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
+static inline void set_to_next_sit(struct f2fs_sb_info *sbi,
+ struct sit_info *sit_i, unsigned int start)
{
- unsigned int block_off = SIT_BLOCK_OFFSET(start);
+ unsigned int block_off = SIT_BLOCK_OFFSET(sbi, start);
f2fs_change_bit(block_off, sit_i->sit_bitmap);
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 2d9f5b77f815..4bd1c9fb1f7f 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4329,7 +4329,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
return 1;
}
- sit_blk_cnt = DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK);
+ sit_blk_cnt = DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK(sbi));
if (sit_bitmap_size * 8 < sit_blk_cnt) {
f2fs_err(sbi, "Wrong bitmap size: sit: %u, sit_blk_cnt:%u",
sit_bitmap_size, sit_blk_cnt);
@@ -4382,6 +4382,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->sit_entries_per_block = sbi->blocksize /
+ sizeof(struct f2fs_sit_entry);
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 bb2b6cd5d507..ecd6694af572 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -396,8 +396,6 @@ struct f2fs_nat_block {
* Not allow to change this.
*/
#define SIT_VBLOCK_MAP_SIZE 64
-#define SIT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_sit_entry))
-
/*
* F2FS uses 4 bytes to represent block address. As a result, supported size of
* disk is 16 TB for a 4K page size and 64 TB for a 16K page size and it equals
@@ -424,8 +422,13 @@ struct f2fs_sit_entry {
__le64 mtime; /* segment age for cleaning */
} __packed;
+/*
+ * The on-disk SIT block is a filesystem-block-sized array of SIT entries.
+ * Its entry count depends on the filesystem block size, so it must be
+ * calculated by the caller rather than implied by this C structure.
+ */
struct f2fs_sit_block {
- struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
+ DECLARE_FLEX_ARRAY(struct f2fs_sit_entry, entries);
} __packed;
/*
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* [f2fs-dev] [PATCH v7 03/11] f2fs: describe NAT block layout dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
2026-08-31 22:05 ` [f2fs-dev] [PATCH v7 01/11] f2fs: initialize sb_info early in f2fs_fill_super Kelvin Zhang
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 02/11] f2fs: describe SIT block layout dynamically Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-09-01 0:38 ` Daeho Jeong
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 04/11] f2fs: describe orphan " Kelvin Zhang
` (7 subsequent siblings)
10 siblings, 1 reply; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
A NAT block is a filesystem-block-sized array of struct f2fs_nat_entry
elements. The compile-time NAT_ENTRY_PER_BLOCK definition hardcodes the
NAT capacity to a 4KB block size.
Replace the fixed array in struct f2fs_nat_block with a C flexible
array member, and calculate sbi->nat_entries_per_block dynamically in
init_sb_info().
Parameterize NAT geometry helpers (NAT_ENTRY_PER_BLOCK,
NAT_BLOCK_OFFSET, f2fs_start_nid, NAT_BLK_CNT, and
f2fs_nat_bitmap_size) with sbi. Update call sites across node management,
checkpointing, GC, and sysfs.
This is a layout-only change without behavioral differences for 4KB
blocks.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/checkpoint.c | 4 +--
fs/f2fs/debug.c | 2 +-
fs/f2fs/f2fs.h | 2 ++
fs/f2fs/gc.c | 4 +--
fs/f2fs/node.c | 77 +++++++++++++++++++++--------------------
fs/f2fs/node.h | 22 ++++++++----
fs/f2fs/segment.c | 4 +--
fs/f2fs/shrinker.c | 2 +-
fs/f2fs/super.c | 4 ++-
include/linux/f2fs_fs.h | 5 ++-
10 files changed, 71 insertions(+), 55 deletions(-)
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 47c4a5c83a70..3ecced9b4d57 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -476,11 +476,11 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
switch (type) {
case META_NAT:
if (unlikely(blkno >=
- NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid)))
+ NAT_BLOCK_OFFSET(sbi, NM_I(sbi)->max_nid)))
blkno = 0;
/* get nat block addr */
fio.new_blkaddr = current_nat_addr(sbi,
- blkno * NAT_ENTRY_PER_BLOCK);
+ blkno * NAT_ENTRY_PER_BLOCK(sbi));
break;
case META_SIT:
if (unlikely(blkno >= TOTAL_SEGS(sbi)))
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index ff379aff4472..5980b9d79afb 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -345,7 +345,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
si->base_mem += F2FS_BLK_TO_BYTES(NM_I(sbi)->nat_bits_blocks);
si->base_mem += NM_I(sbi)->nat_blocks *
- f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK);
+ f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi));
si->base_mem += NM_I(sbi)->nat_blocks / 8;
si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 035863d513ab..8e6000e7d766 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1863,6 +1863,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 nat_entries_per_block; /* NAT entries in a block */
unsigned int sit_entries_per_block; /* SIT entries in a block */
unsigned int root_ino_num; /* root inode number*/
unsigned int node_ino_num; /* node inode number*/
@@ -2253,6 +2254,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
}
#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
+#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
{
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 0a00180c21dc..c15c6ba91597 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1066,7 +1066,7 @@ static int gc_node_segment(struct f2fs_sb_info *sbi,
continue;
if (phase == 0) {
- f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), 1,
META_NAT, true);
continue;
}
@@ -1614,7 +1614,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
continue;
if (phase == 0) {
- f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), 1,
META_NAT, true);
continue;
}
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 86c2e67e43b6..960c6657d0d6 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -169,7 +169,7 @@ static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
folio_mark_dirty(dst_folio);
f2fs_folio_put(src_folio, true);
- set_to_next_nat(nm_i, nid);
+ set_to_next_nat(sbi, nm_i, nid);
return dst_folio;
}
@@ -254,10 +254,11 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
__free_nat_entry(e);
}
-static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
+static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_sb_info *sbi,
+ struct f2fs_nm_info *nm_i,
struct nat_entry *ne)
{
- nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid);
+ nid_t set = NAT_BLOCK_OFFSET(sbi, ne->ni.nid);
struct nat_entry_set *head;
head = radix_tree_lookup(&nm_i->nat_set_root, set);
@@ -274,14 +275,15 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
return head;
}
-static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
+static void __set_nat_cache_dirty(struct f2fs_sb_info *sbi,
+ struct f2fs_nm_info *nm_i,
struct nat_entry *ne, bool init_dirty)
{
struct nat_entry_set *head;
bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
if (!new_ne)
- head = __grab_nat_entry_set(nm_i, ne);
+ head = __grab_nat_entry_set(sbi, nm_i, ne);
/*
* update entry_cnt in below condition:
@@ -527,7 +529,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
nat_set_blkaddr(e, new_blkaddr);
if (!__is_valid_data_blkaddr(new_blkaddr))
set_nat_flag(e, IS_CHECKPOINTED, false);
- __set_nat_cache_dirty(nm_i, e, init_dirty);
+ __set_nat_cache_dirty(sbi, nm_i, e, init_dirty);
/* update fsync_mark if its inode nat entry is still alive */
if (ni->nid != ni->ino)
@@ -578,7 +580,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_journal *journal = curseg->journal;
- nid_t start_nid = START_NID(nid);
+ nid_t start_nid = f2fs_start_nid(sbi, nid);
struct f2fs_nat_block *nat_blk;
struct folio *folio = NULL;
struct f2fs_nat_entry ne;
@@ -2403,8 +2405,8 @@ static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
bool set, bool build)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
- unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid);
- unsigned int nid_ofs = nid - START_NID(nid);
+ unsigned int nat_ofs = NAT_BLOCK_OFFSET(sbi, nid);
+ unsigned int nid_ofs = nid - f2fs_start_nid(sbi, nid);
if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap))
return;
@@ -2524,14 +2526,14 @@ static int scan_nat_page(struct f2fs_sb_info *sbi,
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
block_t blk_addr;
- unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid);
+ unsigned int nat_ofs = NAT_BLOCK_OFFSET(sbi, start_nid);
int i;
__set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
- i = start_nid % NAT_ENTRY_PER_BLOCK;
+ i = start_nid % NAT_ENTRY_PER_BLOCK(sbi);
- for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
+ for (; i < NAT_ENTRY_PER_BLOCK(sbi); i++, start_nid++) {
if (unlikely(start_nid >= nm_i->max_nid))
break;
@@ -2587,16 +2589,16 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi)
continue;
if (!nm_i->free_nid_count[i])
continue;
- for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) {
+ for (idx = 0; idx < NAT_ENTRY_PER_BLOCK(sbi); idx++) {
idx = find_next_bit_le(nm_i->free_nid_bitmap[i],
- NAT_ENTRY_PER_BLOCK, idx);
- if (idx >= NAT_ENTRY_PER_BLOCK)
+ NAT_ENTRY_PER_BLOCK(sbi), idx);
+ if (idx >= NAT_ENTRY_PER_BLOCK(sbi))
break;
- nid = i * NAT_ENTRY_PER_BLOCK + idx;
+ nid = i * NAT_ENTRY_PER_BLOCK(sbi) + idx;
add_free_nid(sbi, nid, true, false);
- if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS)
+ if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS(sbi))
goto out;
}
}
@@ -2617,11 +2619,11 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
if (unlikely(nid >= nm_i->max_nid))
nid = 0;
- if (unlikely(nid % NAT_ENTRY_PER_BLOCK))
- nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK;
+ if (unlikely(nid % NAT_ENTRY_PER_BLOCK(sbi)))
+ nid = NAT_BLOCK_OFFSET(sbi, nid) * NAT_ENTRY_PER_BLOCK(sbi);
/* Enough entries */
- if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
+ if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK(sbi))
return 0;
if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS))
@@ -2631,18 +2633,18 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
/* try to find free nids in free_nid_bitmap */
scan_free_nid_bits(sbi);
- if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
+ if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK(sbi))
return 0;
}
/* readahead nat pages to be scanned */
- f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), FREE_NID_PAGES,
META_NAT, true);
f2fs_down_read_trace(&nm_i->nat_tree_lock, &lc);
while (1) {
- if (!test_bit_le(NAT_BLOCK_OFFSET(nid),
+ if (!test_bit_le(NAT_BLOCK_OFFSET(sbi, nid),
nm_i->nat_block_bitmap)) {
struct folio *folio = get_current_nat_folio(sbi, nid);
@@ -2668,7 +2670,8 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
}
}
- nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
+ nid += NAT_ENTRY_PER_BLOCK(sbi) -
+ (nid % NAT_ENTRY_PER_BLOCK(sbi));
if (unlikely(nid >= nm_i->max_nid))
nid = 0;
@@ -2684,7 +2687,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
f2fs_up_read_trace(&nm_i->nat_tree_lock, &lc);
- f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nm_i->next_scan_nid),
nm_i->ra_nid_pages, META_NAT, false);
return 0;
@@ -2811,20 +2814,20 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
struct f2fs_nm_info *nm_i = NM_I(sbi);
int nr = nr_shrink;
- if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS)
+ if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS(sbi))
return 0;
if (!mutex_trylock(&nm_i->build_lock))
return 0;
- while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS) {
+ while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS(sbi)) {
struct free_nid *i, *next;
unsigned int batch = SHRINK_NID_BATCH_SIZE;
spin_lock(&nm_i->nid_list_lock);
list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) {
if (!nr_shrink || !batch ||
- nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS)
+ nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS(sbi))
break;
__remove_free_nid(sbi, i, FREE_NID);
kmem_cache_free(free_nid_slab, i);
@@ -3074,7 +3077,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
spin_unlock(&nm_i->nid_list_lock);
}
- __set_nat_cache_dirty(nm_i, ne, init_dirty);
+ __set_nat_cache_dirty(sbi, nm_i, ne, init_dirty);
}
update_nats_in_cursum(journal, -i);
up_write(&curseg->journal_rwsem);
@@ -3102,7 +3105,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
const struct f2fs_nat_block *nat_blk)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
- unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK;
+ unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK(sbi);
int valid = 0;
int i = 0;
@@ -3113,7 +3116,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
valid = 1;
i = 1;
}
- for (; i < NAT_ENTRY_PER_BLOCK; i++) {
+ for (; i < NAT_ENTRY_PER_BLOCK(sbi); i++) {
if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR)
valid++;
}
@@ -3124,7 +3127,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
}
__clear_bit_le(nat_index, nm_i->empty_nat_bits);
- if (valid == NAT_ENTRY_PER_BLOCK)
+ if (valid == NAT_ENTRY_PER_BLOCK(sbi))
__set_bit_le(nat_index, nm_i->full_nat_bits);
else
__clear_bit_le(nat_index, nm_i->full_nat_bits);
@@ -3135,7 +3138,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
{
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_journal *journal = curseg->journal;
- nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK;
+ nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK(sbi);
bool to_journal = true;
struct f2fs_nat_block *nat_blk;
struct nat_entry *ne, *cur;
@@ -3342,8 +3345,8 @@ static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
__set_bit_le(i, nm_i->nat_block_bitmap);
- nid = i * NAT_ENTRY_PER_BLOCK;
- last_nid = nid + NAT_ENTRY_PER_BLOCK;
+ nid = i * NAT_ENTRY_PER_BLOCK(sbi);
+ last_nid = nid + NAT_ENTRY_PER_BLOCK(sbi);
spin_lock(&NM_I(sbi)->nid_list_lock);
for (; nid < last_nid; nid++)
@@ -3373,7 +3376,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
/* segment_count_nat includes pair segment so divide to 2. */
nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
- nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks;
+ nm_i->max_nid = NAT_ENTRY_PER_BLOCK(sbi) * nm_i->nat_blocks;
/* not used nids: 0, node, meta, (and root counted as valid node) */
nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count -
@@ -3436,7 +3439,7 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
for (i = 0; i < nm_i->nat_blocks; i++) {
nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi,
- f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL);
+ f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi)), GFP_KERNEL);
if (!nm_i->free_nid_bitmap[i])
return -ENOMEM;
}
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 5e114f352099..0dce97aac5fc 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -6,14 +6,23 @@
* http://www.samsung.com/
*/
/* start node id of a node block dedicated to the given node id */
-#define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
+static inline nid_t f2fs_start_nid(struct f2fs_sb_info *sbi, nid_t nid)
+{
+ unsigned int entries = NAT_ENTRY_PER_BLOCK(sbi);
+
+ return (nid / entries) * entries;
+}
+
+#define START_NID(sbi, nid) f2fs_start_nid(sbi, nid)
/* node block offset on the NAT area dedicated to the given start node id */
-#define NAT_BLOCK_OFFSET(start_nid) ((start_nid) / NAT_ENTRY_PER_BLOCK)
+#define NAT_BLOCK_OFFSET(sbi, start_nid) \
+ ((start_nid) / NAT_ENTRY_PER_BLOCK(sbi))
/* # of pages to perform synchronous readahead before building free nids */
#define FREE_NID_PAGES 8
-#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
+#define MAX_FREE_NIDS(sbi) ((unsigned long)NAT_ENTRY_PER_BLOCK(sbi) * \
+ FREE_NID_PAGES)
/* size of free nid batch when shrinking */
#define SHRINK_NID_BATCH_SIZE 8
@@ -208,7 +217,7 @@ static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
* OLD = (segment_off * 512) * 2 + off_in_segment
* NEW = 2 * (segment_off * 512 + off_in_segment) - off_in_segment
*/
- block_off = NAT_BLOCK_OFFSET(start);
+ block_off = NAT_BLOCK_OFFSET(sbi, start);
block_addr = (pgoff_t)(nm_i->nat_blkaddr +
(block_off << 1) -
@@ -230,9 +239,10 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
return block_addr + nm_i->nat_blkaddr;
}
-static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
+static inline void set_to_next_nat(struct f2fs_sb_info *sbi,
+ struct f2fs_nm_info *nm_i, nid_t start_nid)
{
- unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
+ unsigned int block_off = NAT_BLOCK_OFFSET(sbi, start_nid);
f2fs_change_bit(block_off, nm_i->nat_bitmap);
#ifdef CONFIG_F2FS_CHECK_FS
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index b3bf1b62cdad..b29df65ab5b7 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -512,10 +512,10 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
/* check the # of cached NAT entries */
if (!f2fs_available_free_memory(sbi, NAT_ENTRIES))
- f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK);
+ f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK(sbi));
if (!f2fs_available_free_memory(sbi, FREE_NIDS))
- f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS);
+ f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS(sbi));
else
f2fs_build_free_nids(sbi, false, false);
diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c
index 4f6bf5926de4..e3e0a7e89406 100644
--- a/fs/f2fs/shrinker.c
+++ b/fs/f2fs/shrinker.c
@@ -23,7 +23,7 @@ static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)
static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
{
- long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS;
+ long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS(sbi);
return count > 0 ? count : 0;
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 4bd1c9fb1f7f..fdc2b0c51c06 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4382,6 +4382,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->nat_entries_per_block = sbi->blocksize /
+ sizeof(struct f2fs_nat_entry);
sbi->sit_entries_per_block = sbi->blocksize /
sizeof(struct f2fs_sit_entry);
sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
@@ -4391,7 +4393,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->total_sections = le32_to_cpu(raw_super->section_count);
sbi->total_node_count = SEGS_TO_BLKS(sbi,
((le32_to_cpu(raw_super->segment_count_nat) / 2) *
- NAT_ENTRY_PER_BLOCK));
+ NAT_ENTRY_PER_BLOCK(sbi)));
sbi->allocate_section_hint = le32_to_cpu(raw_super->section_count);
sbi->allocate_section_policy = ALLOCATE_FORWARD_NOHINT;
F2FS_ROOT_INO(sbi) = le32_to_cpu(raw_super->root_ino);
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index ecd6694af572..061f906a7b94 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -375,8 +375,6 @@ struct f2fs_node {
/*
* For NAT entries
*/
-#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_nat_entry))
-
struct f2fs_nat_entry {
__u8 version; /* latest version of cached nat entry */
__le32 ino; /* inode number */
@@ -384,7 +382,8 @@ struct f2fs_nat_entry {
} __packed;
struct f2fs_nat_block {
- struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
+ /* The entry count depends on the filesystem block size. */
+ DECLARE_FLEX_ARRAY(struct f2fs_nat_entry, entries);
} __packed;
/*
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 03/11] f2fs: describe NAT block layout dynamically
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 03/11] f2fs: describe NAT " Kelvin Zhang
@ 2026-09-01 0:38 ` Daeho Jeong
2026-09-01 16:38 ` Xinping Zhang
0 siblings, 1 reply; 30+ messages in thread
From: Daeho Jeong @ 2026-09-01 0:38 UTC (permalink / raw)
To: Kelvin Zhang; +Cc: jaegeuk, linux-kernel, linux-f2fs-devel
On Mon, Aug 31, 2026 at 3:09 PM Kelvin Zhang <zhangxp1998@gmail.com> wrote:
>
> A NAT block is a filesystem-block-sized array of struct f2fs_nat_entry
> elements. The compile-time NAT_ENTRY_PER_BLOCK definition hardcodes the
> NAT capacity to a 4KB block size.
>
> Replace the fixed array in struct f2fs_nat_block with a C flexible
> array member, and calculate sbi->nat_entries_per_block dynamically in
> init_sb_info().
>
> Parameterize NAT geometry helpers (NAT_ENTRY_PER_BLOCK,
> NAT_BLOCK_OFFSET, f2fs_start_nid, NAT_BLK_CNT, and
> f2fs_nat_bitmap_size) with sbi. Update call sites across node management,
> checkpointing, GC, and sysfs.
>
> This is a layout-only change without behavioral differences for 4KB
> blocks.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/checkpoint.c | 4 +--
> fs/f2fs/debug.c | 2 +-
> fs/f2fs/f2fs.h | 2 ++
> fs/f2fs/gc.c | 4 +--
> fs/f2fs/node.c | 77 +++++++++++++++++++++--------------------
> fs/f2fs/node.h | 22 ++++++++----
> fs/f2fs/segment.c | 4 +--
> fs/f2fs/shrinker.c | 2 +-
> fs/f2fs/super.c | 4 ++-
> include/linux/f2fs_fs.h | 5 ++-
> 10 files changed, 71 insertions(+), 55 deletions(-)
>
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 47c4a5c83a70..3ecced9b4d57 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -476,11 +476,11 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
> switch (type) {
> case META_NAT:
> if (unlikely(blkno >=
> - NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid)))
> + NAT_BLOCK_OFFSET(sbi, NM_I(sbi)->max_nid)))
> blkno = 0;
> /* get nat block addr */
> fio.new_blkaddr = current_nat_addr(sbi,
> - blkno * NAT_ENTRY_PER_BLOCK);
> + blkno * NAT_ENTRY_PER_BLOCK(sbi));
> break;
> case META_SIT:
> if (unlikely(blkno >= TOTAL_SEGS(sbi)))
> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> index ff379aff4472..5980b9d79afb 100644
> --- a/fs/f2fs/debug.c
> +++ b/fs/f2fs/debug.c
> @@ -345,7 +345,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
> si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
> si->base_mem += F2FS_BLK_TO_BYTES(NM_I(sbi)->nat_bits_blocks);
> si->base_mem += NM_I(sbi)->nat_blocks *
> - f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK);
> + f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi));
> si->base_mem += NM_I(sbi)->nat_blocks / 8;
> si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 035863d513ab..8e6000e7d766 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1863,6 +1863,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 nat_entries_per_block; /* NAT entries in a block */
> unsigned int sit_entries_per_block; /* SIT entries in a block */
> unsigned int root_ino_num; /* root inode number*/
> unsigned int node_ino_num; /* node inode number*/
> @@ -2253,6 +2254,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
> }
>
> #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
> +#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
>
> static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
> {
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 0a00180c21dc..c15c6ba91597 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1066,7 +1066,7 @@ static int gc_node_segment(struct f2fs_sb_info *sbi,
> continue;
>
> if (phase == 0) {
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
> + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), 1,
> META_NAT, true);
> continue;
> }
> @@ -1614,7 +1614,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
> continue;
>
> if (phase == 0) {
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
> + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), 1,
> META_NAT, true);
> continue;
> }
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 86c2e67e43b6..960c6657d0d6 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -169,7 +169,7 @@ static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
> folio_mark_dirty(dst_folio);
> f2fs_folio_put(src_folio, true);
>
> - set_to_next_nat(nm_i, nid);
> + set_to_next_nat(sbi, nm_i, nid);
>
> return dst_folio;
> }
> @@ -254,10 +254,11 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
> __free_nat_entry(e);
> }
>
> -static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
> +static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_sb_info *sbi,
> + struct f2fs_nm_info *nm_i,
> struct nat_entry *ne)
> {
> - nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid);
> + nid_t set = NAT_BLOCK_OFFSET(sbi, ne->ni.nid);
> struct nat_entry_set *head;
>
> head = radix_tree_lookup(&nm_i->nat_set_root, set);
> @@ -274,14 +275,15 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
> return head;
> }
>
> -static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
> +static void __set_nat_cache_dirty(struct f2fs_sb_info *sbi,
> + struct f2fs_nm_info *nm_i,
> struct nat_entry *ne, bool init_dirty)
> {
> struct nat_entry_set *head;
> bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
>
> if (!new_ne)
> - head = __grab_nat_entry_set(nm_i, ne);
> + head = __grab_nat_entry_set(sbi, nm_i, ne);
>
> /*
> * update entry_cnt in below condition:
> @@ -527,7 +529,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
> nat_set_blkaddr(e, new_blkaddr);
> if (!__is_valid_data_blkaddr(new_blkaddr))
> set_nat_flag(e, IS_CHECKPOINTED, false);
> - __set_nat_cache_dirty(nm_i, e, init_dirty);
> + __set_nat_cache_dirty(sbi, nm_i, e, init_dirty);
>
> /* update fsync_mark if its inode nat entry is still alive */
> if (ni->nid != ni->ino)
> @@ -578,7 +580,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
> struct f2fs_journal *journal = curseg->journal;
> - nid_t start_nid = START_NID(nid);
> + nid_t start_nid = f2fs_start_nid(sbi, nid);
> struct f2fs_nat_block *nat_blk;
> struct folio *folio = NULL;
> struct f2fs_nat_entry ne;
> @@ -2403,8 +2405,8 @@ static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
> bool set, bool build)
> {
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> - unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid);
> - unsigned int nid_ofs = nid - START_NID(nid);
> + unsigned int nat_ofs = NAT_BLOCK_OFFSET(sbi, nid);
> + unsigned int nid_ofs = nid - f2fs_start_nid(sbi, nid);
>
> if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap))
> return;
> @@ -2524,14 +2526,14 @@ static int scan_nat_page(struct f2fs_sb_info *sbi,
> {
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> block_t blk_addr;
> - unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid);
> + unsigned int nat_ofs = NAT_BLOCK_OFFSET(sbi, start_nid);
> int i;
>
> __set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
>
> - i = start_nid % NAT_ENTRY_PER_BLOCK;
> + i = start_nid % NAT_ENTRY_PER_BLOCK(sbi);
>
> - for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
> + for (; i < NAT_ENTRY_PER_BLOCK(sbi); i++, start_nid++) {
> if (unlikely(start_nid >= nm_i->max_nid))
> break;
>
> @@ -2587,16 +2589,16 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi)
> continue;
> if (!nm_i->free_nid_count[i])
> continue;
> - for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) {
> + for (idx = 0; idx < NAT_ENTRY_PER_BLOCK(sbi); idx++) {
> idx = find_next_bit_le(nm_i->free_nid_bitmap[i],
> - NAT_ENTRY_PER_BLOCK, idx);
> - if (idx >= NAT_ENTRY_PER_BLOCK)
> + NAT_ENTRY_PER_BLOCK(sbi), idx);
> + if (idx >= NAT_ENTRY_PER_BLOCK(sbi))
> break;
>
> - nid = i * NAT_ENTRY_PER_BLOCK + idx;
> + nid = i * NAT_ENTRY_PER_BLOCK(sbi) + idx;
> add_free_nid(sbi, nid, true, false);
>
> - if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS)
> + if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS(sbi))
> goto out;
> }
> }
> @@ -2617,11 +2619,11 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> if (unlikely(nid >= nm_i->max_nid))
> nid = 0;
>
> - if (unlikely(nid % NAT_ENTRY_PER_BLOCK))
> - nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK;
> + if (unlikely(nid % NAT_ENTRY_PER_BLOCK(sbi)))
> + nid = NAT_BLOCK_OFFSET(sbi, nid) * NAT_ENTRY_PER_BLOCK(sbi);
>
> /* Enough entries */
> - if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
> + if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK(sbi))
> return 0;
>
> if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS))
> @@ -2631,18 +2633,18 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> /* try to find free nids in free_nid_bitmap */
> scan_free_nid_bits(sbi);
>
> - if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
> + if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK(sbi))
> return 0;
> }
>
> /* readahead nat pages to be scanned */
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
> + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), FREE_NID_PAGES,
> META_NAT, true);
>
> f2fs_down_read_trace(&nm_i->nat_tree_lock, &lc);
>
> while (1) {
> - if (!test_bit_le(NAT_BLOCK_OFFSET(nid),
> + if (!test_bit_le(NAT_BLOCK_OFFSET(sbi, nid),
> nm_i->nat_block_bitmap)) {
> struct folio *folio = get_current_nat_folio(sbi, nid);
>
> @@ -2668,7 +2670,8 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
> }
> }
>
> - nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
> + nid += NAT_ENTRY_PER_BLOCK(sbi) -
> + (nid % NAT_ENTRY_PER_BLOCK(sbi));
> if (unlikely(nid >= nm_i->max_nid))
> nid = 0;
>
> @@ -2684,7 +2687,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
>
> f2fs_up_read_trace(&nm_i->nat_tree_lock, &lc);
>
> - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
> + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nm_i->next_scan_nid),
> nm_i->ra_nid_pages, META_NAT, false);
>
> return 0;
> @@ -2811,20 +2814,20 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> int nr = nr_shrink;
>
> - if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS)
> + if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS(sbi))
> return 0;
>
> if (!mutex_trylock(&nm_i->build_lock))
> return 0;
>
> - while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS) {
> + while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS(sbi)) {
> struct free_nid *i, *next;
> unsigned int batch = SHRINK_NID_BATCH_SIZE;
>
> spin_lock(&nm_i->nid_list_lock);
> list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) {
> if (!nr_shrink || !batch ||
> - nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS)
> + nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS(sbi))
> break;
> __remove_free_nid(sbi, i, FREE_NID);
> kmem_cache_free(free_nid_slab, i);
> @@ -3074,7 +3077,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
> spin_unlock(&nm_i->nid_list_lock);
> }
>
> - __set_nat_cache_dirty(nm_i, ne, init_dirty);
> + __set_nat_cache_dirty(sbi, nm_i, ne, init_dirty);
> }
> update_nats_in_cursum(journal, -i);
> up_write(&curseg->journal_rwsem);
> @@ -3102,7 +3105,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
> const struct f2fs_nat_block *nat_blk)
> {
> struct f2fs_nm_info *nm_i = NM_I(sbi);
> - unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK;
> + unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK(sbi);
> int valid = 0;
> int i = 0;
>
> @@ -3113,7 +3116,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
> valid = 1;
> i = 1;
> }
> - for (; i < NAT_ENTRY_PER_BLOCK; i++) {
> + for (; i < NAT_ENTRY_PER_BLOCK(sbi); i++) {
> if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR)
> valid++;
> }
> @@ -3124,7 +3127,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
> }
>
> __clear_bit_le(nat_index, nm_i->empty_nat_bits);
> - if (valid == NAT_ENTRY_PER_BLOCK)
> + if (valid == NAT_ENTRY_PER_BLOCK(sbi))
> __set_bit_le(nat_index, nm_i->full_nat_bits);
> else
> __clear_bit_le(nat_index, nm_i->full_nat_bits);
> @@ -3135,7 +3138,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
> {
> struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
> struct f2fs_journal *journal = curseg->journal;
> - nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK;
> + nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK(sbi);
> bool to_journal = true;
> struct f2fs_nat_block *nat_blk;
> struct nat_entry *ne, *cur;
> @@ -3342,8 +3345,8 @@ static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
>
> __set_bit_le(i, nm_i->nat_block_bitmap);
>
> - nid = i * NAT_ENTRY_PER_BLOCK;
> - last_nid = nid + NAT_ENTRY_PER_BLOCK;
> + nid = i * NAT_ENTRY_PER_BLOCK(sbi);
> + last_nid = nid + NAT_ENTRY_PER_BLOCK(sbi);
>
> spin_lock(&NM_I(sbi)->nid_list_lock);
> for (; nid < last_nid; nid++)
> @@ -3373,7 +3376,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
> /* segment_count_nat includes pair segment so divide to 2. */
> nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
> nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
> - nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks;
> + nm_i->max_nid = NAT_ENTRY_PER_BLOCK(sbi) * nm_i->nat_blocks;
>
> /* not used nids: 0, node, meta, (and root counted as valid node) */
> nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count -
> @@ -3436,7 +3439,7 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
>
> for (i = 0; i < nm_i->nat_blocks; i++) {
> nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi,
> - f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL);
> + f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi)), GFP_KERNEL);
> if (!nm_i->free_nid_bitmap[i])
> return -ENOMEM;
> }
> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
> index 5e114f352099..0dce97aac5fc 100644
> --- a/fs/f2fs/node.h
> +++ b/fs/f2fs/node.h
> @@ -6,14 +6,23 @@
> * http://www.samsung.com/
> */
> /* start node id of a node block dedicated to the given node id */
> -#define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
> +static inline nid_t f2fs_start_nid(struct f2fs_sb_info *sbi, nid_t nid)
> +{
> + unsigned int entries = NAT_ENTRY_PER_BLOCK(sbi);
> +
> + return (nid / entries) * entries;
> +}
> +
> +#define START_NID(sbi, nid) f2fs_start_nid(sbi, nid)
Do we still need START_NID()? Otherwise, plz, remove it.
Thanks,
>
> /* node block offset on the NAT area dedicated to the given start node id */
> -#define NAT_BLOCK_OFFSET(start_nid) ((start_nid) / NAT_ENTRY_PER_BLOCK)
> +#define NAT_BLOCK_OFFSET(sbi, start_nid) \
> + ((start_nid) / NAT_ENTRY_PER_BLOCK(sbi))
>
> /* # of pages to perform synchronous readahead before building free nids */
> #define FREE_NID_PAGES 8
> -#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
> +#define MAX_FREE_NIDS(sbi) ((unsigned long)NAT_ENTRY_PER_BLOCK(sbi) * \
> + FREE_NID_PAGES)
>
> /* size of free nid batch when shrinking */
> #define SHRINK_NID_BATCH_SIZE 8
> @@ -208,7 +217,7 @@ static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
> * OLD = (segment_off * 512) * 2 + off_in_segment
> * NEW = 2 * (segment_off * 512 + off_in_segment) - off_in_segment
> */
> - block_off = NAT_BLOCK_OFFSET(start);
> + block_off = NAT_BLOCK_OFFSET(sbi, start);
>
> block_addr = (pgoff_t)(nm_i->nat_blkaddr +
> (block_off << 1) -
> @@ -230,9 +239,10 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
> return block_addr + nm_i->nat_blkaddr;
> }
>
> -static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
> +static inline void set_to_next_nat(struct f2fs_sb_info *sbi,
> + struct f2fs_nm_info *nm_i, nid_t start_nid)
> {
> - unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
> + unsigned int block_off = NAT_BLOCK_OFFSET(sbi, start_nid);
>
> f2fs_change_bit(block_off, nm_i->nat_bitmap);
> #ifdef CONFIG_F2FS_CHECK_FS
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index b3bf1b62cdad..b29df65ab5b7 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -512,10 +512,10 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
>
> /* check the # of cached NAT entries */
> if (!f2fs_available_free_memory(sbi, NAT_ENTRIES))
> - f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK);
> + f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK(sbi));
>
> if (!f2fs_available_free_memory(sbi, FREE_NIDS))
> - f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS);
> + f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS(sbi));
> else
> f2fs_build_free_nids(sbi, false, false);
>
> diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c
> index 4f6bf5926de4..e3e0a7e89406 100644
> --- a/fs/f2fs/shrinker.c
> +++ b/fs/f2fs/shrinker.c
> @@ -23,7 +23,7 @@ static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)
>
> static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
> {
> - long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS;
> + long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS(sbi);
>
> return count > 0 ? count : 0;
> }
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 4bd1c9fb1f7f..fdc2b0c51c06 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4382,6 +4382,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->nat_entries_per_block = sbi->blocksize /
> + sizeof(struct f2fs_nat_entry);
> sbi->sit_entries_per_block = sbi->blocksize /
> sizeof(struct f2fs_sit_entry);
> sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> @@ -4391,7 +4393,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
> sbi->total_sections = le32_to_cpu(raw_super->section_count);
> sbi->total_node_count = SEGS_TO_BLKS(sbi,
> ((le32_to_cpu(raw_super->segment_count_nat) / 2) *
> - NAT_ENTRY_PER_BLOCK));
> + NAT_ENTRY_PER_BLOCK(sbi)));
> sbi->allocate_section_hint = le32_to_cpu(raw_super->section_count);
> sbi->allocate_section_policy = ALLOCATE_FORWARD_NOHINT;
> F2FS_ROOT_INO(sbi) = le32_to_cpu(raw_super->root_ino);
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index ecd6694af572..061f906a7b94 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -375,8 +375,6 @@ struct f2fs_node {
> /*
> * For NAT entries
> */
> -#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_nat_entry))
> -
> struct f2fs_nat_entry {
> __u8 version; /* latest version of cached nat entry */
> __le32 ino; /* inode number */
> @@ -384,7 +382,8 @@ struct f2fs_nat_entry {
> } __packed;
>
> struct f2fs_nat_block {
> - struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
> + /* The entry count depends on the filesystem block size. */
> + DECLARE_FLEX_ARRAY(struct f2fs_nat_entry, entries);
> } __packed;
>
> /*
> --
> 2.53.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 04/11] f2fs: describe orphan block layout dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (2 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 03/11] f2fs: describe NAT " Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-09-01 11:34 ` Chao Yu via Linux-f2fs-devel
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 05/11] f2fs: describe dentry " Kelvin Zhang
` (6 subsequent siblings)
10 siblings, 1 reply; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
An on-disk orphan block contains a variable-length array of 32-bit
inode numbers followed by a fixed footer at the end of the block. A
compile-time whole-block structure cannot represent the footer position
when the block size varies at runtime.
Remove struct f2fs_orphan_block, introduce
struct f2fs_orphan_block_footer, and compute sbi->orphans_per_block
dynamically in init_sb_info(). Add helpers to access the inode entry array
and footer from a block buffer.
Update orphan inode recovery, checkpointing, and mount paths to use the
parameterized helpers. This preserves the on-disk format while decoupling
orphan handling from compile-time constants.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/checkpoint.c | 44 ++++++++++++++++++++++-------------------
fs/f2fs/f2fs.h | 12 +++++++++++
fs/f2fs/super.c | 2 ++
include/linux/f2fs_fs.h | 18 ++++++++++-------
4 files changed, 49 insertions(+), 27 deletions(-)
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 3ecced9b4d57..37a72b693545 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -1041,7 +1041,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
for (i = 0; i < orphan_blocks; i++) {
struct folio *folio;
- struct f2fs_orphan_block *orphan_blk;
+ __le32 *orphan_inos;
+ struct f2fs_orphan_footer *footer;
unsigned int entry_count;
folio = f2fs_get_meta_folio(sbi, start_blk + i);
@@ -1050,9 +1051,10 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
goto out;
}
- orphan_blk = folio_address(folio);
- entry_count = le32_to_cpu(orphan_blk->entry_count);
- if (entry_count > F2FS_ORPHANS_PER_BLOCK) {
+ orphan_inos = folio_address(folio);
+ footer = f2fs_orphan_footer(orphan_inos, sbi);
+ entry_count = le32_to_cpu(footer->entry_count);
+ if (entry_count > F2FS_ORPHANS_PER_BLOCK(sbi)) {
f2fs_err(sbi, "invalid orphan inode entry count %u",
entry_count);
set_sbi_flag(sbi, SBI_NEED_FSCK);
@@ -1063,7 +1065,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
}
for (j = 0; j < entry_count; j++) {
- nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
+ nid_t ino = le32_to_cpu(orphan_inos[j]);
err = recover_orphan_inode(sbi, ino);
if (err) {
@@ -1084,7 +1086,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
{
struct list_head *head;
- struct f2fs_orphan_block *orphan_blk = NULL;
+ __le32 *orphan_inos = NULL;
+ struct f2fs_orphan_footer *footer = NULL;
unsigned int nentries = 0;
unsigned short index = 1;
unsigned short orphan_blocks;
@@ -1092,7 +1095,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
struct ino_entry *orphan = NULL;
struct inode_management *im = &sbi->im[ORPHAN_INO];
- orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num);
+ orphan_blocks = GET_ORPHAN_BLOCKS(sbi, im->ino_num);
/*
* we don't need to do spin_lock(&im->ino_lock) here, since all the
@@ -1105,21 +1108,22 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
list_for_each_entry(orphan, head, list) {
if (!folio) {
folio = f2fs_grab_meta_folio(sbi, start_blk++);
- orphan_blk = folio_address(folio);
- memset(orphan_blk, 0, sizeof(*orphan_blk));
+ orphan_inos = folio_address(folio);
+ footer = f2fs_orphan_footer(orphan_inos, sbi);
+ memset(orphan_inos, 0, sbi->blocksize);
}
- orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
+ orphan_inos[nentries++] = cpu_to_le32(orphan->ino);
- if (nentries == F2FS_ORPHANS_PER_BLOCK) {
+ if (nentries == F2FS_ORPHANS_PER_BLOCK(sbi)) {
/*
- * an orphan block is full of 1020 entries,
+ * an orphan block is full,
* then we need to flush current orphan blocks
* and bring another one in memory
*/
- orphan_blk->blk_addr = cpu_to_le16(index);
- orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
- orphan_blk->entry_count = cpu_to_le32(nentries);
+ footer->blk_addr = cpu_to_le16(index);
+ footer->blk_count = cpu_to_le16(orphan_blocks);
+ footer->entry_count = cpu_to_le32(nentries);
folio_mark_dirty(folio);
f2fs_folio_put(folio, true);
index++;
@@ -1129,9 +1133,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
}
if (folio) {
- orphan_blk->blk_addr = cpu_to_le16(index);
- orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
- orphan_blk->entry_count = cpu_to_le32(nentries);
+ footer->blk_addr = cpu_to_le16(index);
+ footer->blk_count = cpu_to_le16(orphan_blocks);
+ footer->entry_count = cpu_to_le32(nentries);
folio_mark_dirty(folio);
f2fs_folio_put(folio, true);
}
@@ -1824,7 +1828,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
__clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
spin_unlock_irqrestore(&sbi->cp_lock, flags);
- orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num);
+ orphan_blocks = GET_ORPHAN_BLOCKS(sbi, orphan_num);
ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
orphan_blocks);
@@ -2080,7 +2084,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
sbi->max_orphans = (BLKS_PER_SEG(sbi) - F2FS_CP_PACKS -
NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
- F2FS_ORPHANS_PER_BLOCK;
+ F2FS_ORPHANS_PER_BLOCK(sbi);
}
int __init f2fs_create_checkpoint_caches(void)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8e6000e7d766..2a4ba7d4ec0e 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1865,6 +1865,7 @@ struct f2fs_sb_info {
unsigned int blocksize; /* block size */
unsigned int nat_entries_per_block; /* NAT entries in a block */
unsigned int sit_entries_per_block; /* SIT entries in a block */
+ unsigned int orphans_per_block; /* orphan inodes in a block */
unsigned int root_ino_num; /* root inode number*/
unsigned int node_ino_num; /* node inode number*/
unsigned int meta_ino_num; /* meta inode number*/
@@ -2255,6 +2256,17 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
+#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
+#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
+ F2FS_ORPHANS_PER_BLOCK(sbi))
+
+static inline struct f2fs_orphan_footer *
+f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi)
+{
+ return (struct f2fs_orphan_footer *)
+ ((char *)orphan_block + sbi->blocksize -
+ sizeof(struct f2fs_orphan_footer));
+}
static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
{
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index fdc2b0c51c06..f9811d571ae5 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4386,6 +4386,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sizeof(struct f2fs_nat_entry);
sbi->sit_entries_per_block = sbi->blocksize /
sizeof(struct f2fs_sit_entry);
+ sbi->orphans_per_block = (sbi->blocksize -
+ sizeof(struct f2fs_orphan_footer)) / sizeof(__le32);
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 061f906a7b94..7d2cbceb42d5 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -220,14 +220,18 @@ struct f2fs_checkpoint {
/*
* For orphan inode management
+ *
+ * An orphan block has no fixed-size C structure because the number of inode
+ * entries depends on the filesystem block size. Its exact on-disk layout is:
+ *
+ * 0 blocksize - 16 blocksize
+ * +--------------------------+--------------------------+
+ * | ino[0] ... ino[n - 1] | struct f2fs_orphan_footer |
+ * +--------------------------+--------------------------+
+ *
+ * n = (blocksize - sizeof(struct f2fs_orphan_footer)) / sizeof(__le32)
*/
-#define F2FS_ORPHANS_PER_BLOCK ((F2FS_BLKSIZE - 4 * sizeof(__le32)) / sizeof(__le32))
-
-#define GET_ORPHAN_BLOCKS(n) (((n) + F2FS_ORPHANS_PER_BLOCK - 1) / \
- F2FS_ORPHANS_PER_BLOCK)
-
-struct f2fs_orphan_block {
- __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */
+struct f2fs_orphan_footer {
__le32 reserved; /* reserved */
__le16 blk_addr; /* block index in current CP */
__le16 blk_count; /* Number of orphan inode blocks in CP */
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 04/11] f2fs: describe orphan block layout dynamically
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 04/11] f2fs: describe orphan " Kelvin Zhang
@ 2026-09-01 11:34 ` Chao Yu via Linux-f2fs-devel
2026-09-01 16:38 ` Xinping Zhang
0 siblings, 1 reply; 30+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2026-09-01 11:34 UTC (permalink / raw)
To: Kelvin Zhang, linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
On 9/1/26 06:08, Kelvin Zhang wrote:
> An on-disk orphan block contains a variable-length array of 32-bit
> inode numbers followed by a fixed footer at the end of the block. A
> compile-time whole-block structure cannot represent the footer position
> when the block size varies at runtime.
>
> Remove struct f2fs_orphan_block, introduce
> struct f2fs_orphan_block_footer, and compute sbi->orphans_per_block
> dynamically in init_sb_info(). Add helpers to access the inode entry array
> and footer from a block buffer.
>
> Update orphan inode recovery, checkpointing, and mount paths to use the
> parameterized helpers. This preserves the on-disk format while decoupling
> orphan handling from compile-time constants.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/checkpoint.c | 44 ++++++++++++++++++++++-------------------
> fs/f2fs/f2fs.h | 12 +++++++++++
> fs/f2fs/super.c | 2 ++
> include/linux/f2fs_fs.h | 18 ++++++++++-------
> 4 files changed, 49 insertions(+), 27 deletions(-)
>
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 3ecced9b4d57..37a72b693545 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -1041,7 +1041,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
>
> for (i = 0; i < orphan_blocks; i++) {
> struct folio *folio;
> - struct f2fs_orphan_block *orphan_blk;
> + __le32 *orphan_inos;
> + struct f2fs_orphan_footer *footer;
> unsigned int entry_count;
>
> folio = f2fs_get_meta_folio(sbi, start_blk + i);
> @@ -1050,9 +1051,10 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> goto out;
> }
>
> - orphan_blk = folio_address(folio);
> - entry_count = le32_to_cpu(orphan_blk->entry_count);
> - if (entry_count > F2FS_ORPHANS_PER_BLOCK) {
> + orphan_inos = folio_address(folio);
> + footer = f2fs_orphan_footer(orphan_inos, sbi);
> + entry_count = le32_to_cpu(footer->entry_count);
> + if (entry_count > F2FS_ORPHANS_PER_BLOCK(sbi)) {
> f2fs_err(sbi, "invalid orphan inode entry count %u",
> entry_count);
> set_sbi_flag(sbi, SBI_NEED_FSCK);
> @@ -1063,7 +1065,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> }
>
> for (j = 0; j < entry_count; j++) {
> - nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
> + nid_t ino = le32_to_cpu(orphan_inos[j]);
>
> err = recover_orphan_inode(sbi, ino);
> if (err) {
> @@ -1084,7 +1086,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
> static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> {
> struct list_head *head;
> - struct f2fs_orphan_block *orphan_blk = NULL;
> + __le32 *orphan_inos = NULL;
> + struct f2fs_orphan_footer *footer = NULL;
> unsigned int nentries = 0;
> unsigned short index = 1;
> unsigned short orphan_blocks;
> @@ -1092,7 +1095,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> struct ino_entry *orphan = NULL;
> struct inode_management *im = &sbi->im[ORPHAN_INO];
>
> - orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num);
> + orphan_blocks = GET_ORPHAN_BLOCKS(sbi, im->ino_num);
>
> /*
> * we don't need to do spin_lock(&im->ino_lock) here, since all the
> @@ -1105,21 +1108,22 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> list_for_each_entry(orphan, head, list) {
> if (!folio) {
> folio = f2fs_grab_meta_folio(sbi, start_blk++);
> - orphan_blk = folio_address(folio);
> - memset(orphan_blk, 0, sizeof(*orphan_blk));
> + orphan_inos = folio_address(folio);
> + footer = f2fs_orphan_footer(orphan_inos, sbi);
> + memset(orphan_inos, 0, sbi->blocksize);
> }
>
> - orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
> + orphan_inos[nentries++] = cpu_to_le32(orphan->ino);
>
> - if (nentries == F2FS_ORPHANS_PER_BLOCK) {
> + if (nentries == F2FS_ORPHANS_PER_BLOCK(sbi)) {
> /*
> - * an orphan block is full of 1020 entries,
> + * an orphan block is full,
> * then we need to flush current orphan blocks
> * and bring another one in memory
> */
> - orphan_blk->blk_addr = cpu_to_le16(index);
> - orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
> - orphan_blk->entry_count = cpu_to_le32(nentries);
> + footer->blk_addr = cpu_to_le16(index);
> + footer->blk_count = cpu_to_le16(orphan_blocks);
> + footer->entry_count = cpu_to_le32(nentries);
> folio_mark_dirty(folio);
> f2fs_folio_put(folio, true);
> index++;
> @@ -1129,9 +1133,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> }
>
> if (folio) {
> - orphan_blk->blk_addr = cpu_to_le16(index);
> - orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
> - orphan_blk->entry_count = cpu_to_le32(nentries);
> + footer->blk_addr = cpu_to_le16(index);
> + footer->blk_count = cpu_to_le16(orphan_blocks);
> + footer->entry_count = cpu_to_le32(nentries);
> folio_mark_dirty(folio);
> f2fs_folio_put(folio, true);
> }
> @@ -1824,7 +1828,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> __clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
> spin_unlock_irqrestore(&sbi->cp_lock, flags);
>
> - orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num);
> + orphan_blocks = GET_ORPHAN_BLOCKS(sbi, orphan_num);
> ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
> orphan_blocks);
>
> @@ -2080,7 +2084,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
>
> sbi->max_orphans = (BLKS_PER_SEG(sbi) - F2FS_CP_PACKS -
> NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
> - F2FS_ORPHANS_PER_BLOCK;
> + F2FS_ORPHANS_PER_BLOCK(sbi);
> }
>
> int __init f2fs_create_checkpoint_caches(void)
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 8e6000e7d766..2a4ba7d4ec0e 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1865,6 +1865,7 @@ struct f2fs_sb_info {
> unsigned int blocksize; /* block size */
> unsigned int nat_entries_per_block; /* NAT entries in a block */
> unsigned int sit_entries_per_block; /* SIT entries in a block */
> + unsigned int orphans_per_block; /* orphan inodes in a block */
> unsigned int root_ino_num; /* root inode number*/
> unsigned int node_ino_num; /* node inode number*/
> unsigned int meta_ino_num; /* meta inode number*/
> @@ -2255,6 +2256,17 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
>
> #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
> #define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
> +#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
> +#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
> + F2FS_ORPHANS_PER_BLOCK(sbi))
> +
> +static inline struct f2fs_orphan_footer *
> +f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi)
> +{
> + return (struct f2fs_orphan_footer *)
> + ((char *)orphan_block + sbi->blocksize -
> + sizeof(struct f2fs_orphan_footer));
> +}
>
> static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
> {
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index fdc2b0c51c06..f9811d571ae5 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4386,6 +4386,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
> sizeof(struct f2fs_nat_entry);
> sbi->sit_entries_per_block = sbi->blocksize /
> sizeof(struct f2fs_sit_entry);
> + sbi->orphans_per_block = (sbi->blocksize -
> + sizeof(struct f2fs_orphan_footer)) / sizeof(__le32);
> 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 061f906a7b94..7d2cbceb42d5 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -220,14 +220,18 @@ struct f2fs_checkpoint {
>
> /*
> * For orphan inode management
> + *
> + * An orphan block has no fixed-size C structure because the number of inode
> + * entries depends on the filesystem block size. Its exact on-disk layout is:
> + *
> + * 0 blocksize - 16 blocksize
> + * +--------------------------+--------------------------+
> + * | ino[0] ... ino[n - 1] | struct f2fs_orphan_footer |
> + * +--------------------------+--------------------------+
> + *
> + * n = (blocksize - sizeof(struct f2fs_orphan_footer)) / sizeof(__le32)
> */
> -#define F2FS_ORPHANS_PER_BLOCK ((F2FS_BLKSIZE - 4 * sizeof(__le32)) / sizeof(__le32))
> -
> -#define GET_ORPHAN_BLOCKS(n) (((n) + F2FS_ORPHANS_PER_BLOCK - 1) / \
> - F2FS_ORPHANS_PER_BLOCK)
> -
> -struct f2fs_orphan_block {
> - __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */
Oh, maybe we can leave this structure like we did for f2fs_{nat,sit}_block ?
struct f2fs_sit_block {
- struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
+ DECLARE_FLEX_ARRAY(struct f2fs_sit_entry, entries);
} __packed;
Something like this:
struct f2fs_orphan_block {
DECLARE_FLEX_ARRAY(__le32, ino);
} __packed;
> +struct f2fs_orphan_footer {
> __le32 reserved; /* reserved */
> __le16 blk_addr; /* block index in current CP */
> __le16 blk_count; /* Number of orphan inode blocks in CP */
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 05/11] f2fs: describe dentry block layout dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (3 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 04/11] f2fs: describe orphan " Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node " Kelvin Zhang
` (5 subsequent siblings)
10 siblings, 0 replies; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
An on-disk directory block contains a bitmap, reserved padding, an
array of directory entries (struct f2fs_dir_entry), and matching filename
slots. A fixed compile-time structure couples their offsets to 4KB blocks
and relies on static reserved-space definitions.
Remove struct f2fs_dentry_block and compute region offsets (bitmap
bytes, directory-entry count, and filename slots) dynamically from the
filesystem block size. Access directory blocks through
struct f2fs_dentry_ptr views initialized with the runtime geometry.
Update directory operations, inline dentry handling, and recovery paths
to use the dynamic block layout. No functional change is introduced for
4KB blocks.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/dir.c | 51 +++++++++++++++++++++--------------------
fs/f2fs/f2fs.h | 31 ++++++++++++++++---------
fs/f2fs/inline.c | 2 +-
fs/f2fs/super.c | 6 +++++
include/linux/f2fs_fs.h | 31 ++++++++++++-------------
5 files changed, 68 insertions(+), 53 deletions(-)
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index fd0e2cd31a81..75ff36a13f60 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -195,7 +195,7 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
int *max_slots,
bool use_hash)
{
- struct f2fs_dentry_block *dentry_blk;
+ void *dentry_blk;
struct f2fs_dentry_ptr d;
dentry_blk = folio_address(dentry_folio);
@@ -518,7 +518,7 @@ static int make_empty_dir(struct inode *inode,
struct inode *parent, struct folio *folio)
{
struct folio *dentry_folio;
- struct f2fs_dentry_block *dentry_blk;
+ void *dentry_blk;
struct f2fs_dentry_ptr d;
if (f2fs_has_inline_dentry(inode))
@@ -530,7 +530,7 @@ static int make_empty_dir(struct inode *inode,
dentry_blk = folio_address(dentry_folio);
- make_dentry_ptr_block(NULL, &d, dentry_blk);
+ make_dentry_ptr_block(inode, &d, dentry_blk);
f2fs_do_make_empty_dir(inode, parent, &d);
folio_mark_dirty(dentry_folio);
@@ -690,7 +690,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname,
unsigned long bidx, block;
unsigned int nbucket, nblock;
struct folio *dentry_folio = NULL;
- struct f2fs_dentry_block *dentry_blk = NULL;
+ void *dentry_blk = NULL;
struct f2fs_dentry_ptr d;
struct folio *folio = NULL;
int slots, err = 0;
@@ -727,9 +727,9 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname,
return PTR_ERR(dentry_folio);
dentry_blk = folio_address(dentry_folio);
- bit_pos = f2fs_room_for_filename(&dentry_blk->dentry_bitmap,
- slots, NR_DENTRY_IN_BLOCK);
- if (bit_pos < NR_DENTRY_IN_BLOCK)
+ make_dentry_ptr_block(dir, &d, dentry_blk);
+ bit_pos = f2fs_room_for_filename(d.bitmap, slots, d.max);
+ if (bit_pos < d.max)
goto add_dentry;
f2fs_folio_put(dentry_folio, true);
@@ -750,7 +750,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname,
}
}
- make_dentry_ptr_block(NULL, &d, dentry_blk);
f2fs_update_dentry(ino, mode, &d, &fname->disk_name, fname->hash,
bit_pos);
@@ -887,7 +886,8 @@ void f2fs_drop_nlink(struct inode *dir, struct inode *inode)
void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct folio *folio,
struct inode *dir, struct inode *inode)
{
- struct f2fs_dentry_block *dentry_blk;
+ void *dentry_blk;
+ struct f2fs_dentry_ptr d;
unsigned int bit_pos;
int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
pgoff_t index = folio->index;
@@ -905,18 +905,17 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct folio *folio,
f2fs_folio_wait_writeback(folio, DATA, true, true);
dentry_blk = folio_address(folio);
- bit_pos = dentry - dentry_blk->dentry;
+ make_dentry_ptr_block(dir, &d, dentry_blk);
+ bit_pos = dentry - d.dentry;
for (i = 0; i < slots; i++)
- __clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+ __clear_bit_le(bit_pos + i, d.bitmap);
/* Let's check and deallocate this dentry page */
- bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
- NR_DENTRY_IN_BLOCK,
- 0);
+ bit_pos = find_next_bit_le(d.bitmap, d.max, 0);
folio_mark_dirty(folio);
- if (bit_pos == NR_DENTRY_IN_BLOCK &&
- !f2fs_truncate_hole(dir, index, index + 1)) {
+ if (bit_pos == d.max &&
+ !f2fs_truncate_hole(dir, index, index + 1)) {
f2fs_clear_page_cache_dirty_tag(folio);
folio_clear_dirty_for_io(folio);
folio_clear_uptodate(folio);
@@ -938,7 +937,8 @@ bool f2fs_empty_dir(struct inode *dir)
{
unsigned long bidx = 0;
unsigned int bit_pos;
- struct f2fs_dentry_block *dentry_blk;
+ void *dentry_blk;
+ struct f2fs_dentry_ptr d;
unsigned long nblock = dir_blocks(dir);
if (f2fs_has_inline_dentry(dir))
@@ -959,17 +959,16 @@ bool f2fs_empty_dir(struct inode *dir)
}
dentry_blk = folio_address(dentry_folio);
+ make_dentry_ptr_block(dir, &d, dentry_blk);
if (bidx == 0)
bit_pos = 2;
else
bit_pos = 0;
- bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
- NR_DENTRY_IN_BLOCK,
- bit_pos);
+ bit_pos = find_next_bit_le(d.bitmap, d.max, bit_pos);
f2fs_folio_put(dentry_folio, false);
- if (bit_pos < NR_DENTRY_IN_BLOCK)
+ if (bit_pos < d.max)
return false;
bidx++;
@@ -1066,10 +1065,12 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(file);
unsigned long npages = dir_blocks(inode);
- struct f2fs_dentry_block *dentry_blk = NULL;
+ void *dentry_blk = NULL;
struct file_ra_state *ra = &file->f_ra;
loff_t start_pos = ctx->pos;
- unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK);
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ unsigned int entries = sbi->dentries_per_block;
+ unsigned int n = (unsigned long)ctx->pos / entries;
struct f2fs_dentry_ptr d;
struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
int err = 0;
@@ -1089,7 +1090,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
goto out_free;
}
- for (; n < npages; ctx->pos = n * NR_DENTRY_IN_BLOCK) {
+ for (; n < npages; ctx->pos = n * entries) {
struct folio *dentry_folio;
pgoff_t next_pgofs;
@@ -1122,7 +1123,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
make_dentry_ptr_block(inode, &d, dentry_blk);
err = f2fs_fill_dentries(ctx, &d,
- n * NR_DENTRY_IN_BLOCK, &fstr);
+ n * entries, &fstr);
f2fs_folio_put(dentry_folio, false);
if (err)
break;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 2a4ba7d4ec0e..d2e54573ed34 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -669,17 +669,6 @@ struct f2fs_dentry_ptr {
int nr_bitmap;
};
-static inline void make_dentry_ptr_block(struct inode *inode,
- struct f2fs_dentry_ptr *d, struct f2fs_dentry_block *t)
-{
- d->inode = inode;
- d->max = NR_DENTRY_IN_BLOCK;
- d->nr_bitmap = SIZE_OF_DENTRY_BITMAP;
- d->bitmap = t->dentry_bitmap;
- d->dentry = t->dentry;
- d->filename = t->filename;
-}
-
static inline void make_dentry_ptr_inline(struct inode *inode,
struct f2fs_dentry_ptr *d, void *t)
{
@@ -1866,6 +1855,9 @@ struct f2fs_sb_info {
unsigned int nat_entries_per_block; /* NAT entries in a block */
unsigned int sit_entries_per_block; /* SIT entries in a block */
unsigned int orphans_per_block; /* orphan inodes in a block */
+ unsigned int dentries_per_block; /* dentries in a block */
+ unsigned int dentry_bitmap_size; /* dentry bitmap size in bytes */
+ unsigned int dentry_reserved_size; /* dentry reserved bytes */
unsigned int root_ino_num; /* root inode number*/
unsigned int node_ino_num; /* node inode number*/
unsigned int meta_ino_num; /* meta inode number*/
@@ -2268,6 +2260,23 @@ f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi)
sizeof(struct f2fs_orphan_footer));
}
+static inline void make_dentry_ptr_block(struct inode *inode,
+ struct f2fs_dentry_ptr *d, void *t)
+{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ unsigned int entries = sbi->dentries_per_block;
+ unsigned int bitmap_size = sbi->dentry_bitmap_size;
+ unsigned int reserved_size = sbi->dentry_reserved_size;
+
+ d->inode = inode;
+ d->max = entries;
+ d->nr_bitmap = bitmap_size;
+ d->bitmap = t;
+ d->dentry = t + bitmap_size + reserved_size;
+ d->filename = t + bitmap_size + reserved_size +
+ SIZE_OF_DIR_ENTRY * entries;
+}
+
static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
{
return (struct f2fs_super_block *)(sbi->raw_super);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index aec06fb4fd76..718dd785865a 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -415,7 +415,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio,
{
struct folio *folio;
struct dnode_of_data dn;
- struct f2fs_dentry_block *dentry_blk;
+ void *dentry_blk;
struct f2fs_dentry_ptr src, dst;
int err;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index f9811d571ae5..8d2224e585d3 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4388,6 +4388,12 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sizeof(struct f2fs_sit_entry);
sbi->orphans_per_block = (sbi->blocksize -
sizeof(struct f2fs_orphan_footer)) / sizeof(__le32);
+ sbi->dentries_per_block = (BITS_PER_BYTE * sbi->blocksize) /
+ ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1);
+ sbi->dentry_bitmap_size = DIV_ROUND_UP(sbi->dentries_per_block,
+ BITS_PER_BYTE);
+ sbi->dentry_reserved_size = sbi->blocksize - sbi->dentry_bitmap_size -
+ (SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * sbi->dentries_per_block;
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 7d2cbceb42d5..d1059a27e1b9 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -601,15 +601,7 @@ typedef __le32 f2fs_hash_t;
* dentry, when converting inline dentry we should handle this carefully.
*/
-/* the number of dentry in a block */
-#define NR_DENTRY_IN_BLOCK ((BITS_PER_BYTE * F2FS_BLKSIZE) / \
- ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1))
#define SIZE_OF_DIR_ENTRY 11 /* by byte */
-#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
- BITS_PER_BYTE)
-#define SIZE_OF_RESERVED (F2FS_BLKSIZE - ((SIZE_OF_DIR_ENTRY + \
- F2FS_SLOT_LEN) * \
- NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
#define MIN_INLINE_DENTRY_SIZE 40 /* just include '.' and '..' entries */
/* One directory entry slot representing F2FS_SLOT_LEN-sized file name */
@@ -620,14 +612,21 @@ struct f2fs_dir_entry {
__u8 file_type; /* file type */
} __packed;
-/* Block-sized directory entry block */
-struct f2fs_dentry_block {
- /* validity bitmap for directory entries in each block */
- __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
- __u8 reserved[SIZE_OF_RESERVED];
- struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
- __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
-} __packed;
+/*
+ * A dentry block is laid out as follows, where the number of entries and all
+ * offsets are determined by the filesystem block size at runtime:
+ *
+ * 0 blocksize
+ * +--------+----------+-------------------+-----------------------+
+ * | bitmap | reserved | dir_entry[entries]| filename[entries][8] |
+ * +--------+----------+-------------------+-----------------------+
+ *
+ * entries = (BITS_PER_BYTE * blocksize) /
+ * ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1)
+ * bitmap_size = DIV_ROUND_UP(entries, BITS_PER_BYTE)
+ * reserved_size = blocksize - bitmap_size -
+ * (SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * entries
+ */
#define F2FS_DEF_PROJID 0 /* default project ID */
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node block layout dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (4 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 05/11] f2fs: describe dentry " Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-09-01 0:56 ` Daeho Jeong
` (2 more replies)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 07/11] f2fs: describe xattr " Kelvin Zhang
` (4 subsequent siblings)
10 siblings, 3 replies; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
An inode block ends with five i_nid entries followed by a node footer.
Data block address pointers (i_addr[]) precede them. Similarly, direct and
indirect node blocks contain data addresses or node IDs followed by a node
footer at the end of the block.
Describe struct f2fs_inode, struct direct_node, and
struct indirect_node using flexible array members. Compute the locations
of i_nid and node footers dynamically from the filesystem block size.
Introduce F2FS_INODE_NIDS() and F2FS_NODE_FOOTER() helpers to access these
tail fields.
Compute sbi->addrs_per_inode, sbi->addrs_per_block, and
sbi->nids_per_block in init_sb_info(), and update node management, file
mapping, and recovery paths accordingly.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/data.c | 2 +-
fs/f2fs/f2fs.h | 32 ++++++++++++++++++-------
fs/f2fs/gc.c | 2 +-
fs/f2fs/inline.c | 3 +--
fs/f2fs/inode.c | 5 ++--
fs/f2fs/node.c | 4 +---
fs/f2fs/node.h | 53 +++++++++++++++++++----------------------
fs/f2fs/super.c | 5 ++++
include/linux/f2fs_fs.h | 26 +++++++++++++++-----
9 files changed, 79 insertions(+), 53 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 6ae0eb37d20f..751b7a457d9a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2027,7 +2027,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
offset = offsetof(struct f2fs_inode, i_addr) +
- sizeof(__le32) * (DEF_ADDRS_PER_INODE -
+ sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) -
get_inline_xattr_addrs(inode));
phys += offset;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d2e54573ed34..247e56522441 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1853,6 +1853,9 @@ struct f2fs_sb_info {
unsigned int log_blocksize; /* log2 block size */
unsigned int blocksize; /* block size */
unsigned int nat_entries_per_block; /* NAT entries in a block */
+ unsigned int addrs_per_inode; /* addresses in an inode block */
+ unsigned int addrs_per_block; /* addresses in a direct node block */
+ unsigned int nids_per_block; /* node IDs in an indirect node block */
unsigned int sit_entries_per_block; /* SIT entries in a block */
unsigned int orphans_per_block; /* orphan inodes in a block */
unsigned int dentries_per_block; /* dentries in a block */
@@ -2248,6 +2251,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
+#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode)
#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
F2FS_ORPHANS_PER_BLOCK(sbi))
@@ -2297,6 +2301,12 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
return (struct f2fs_checkpoint *)(sbi->ckpt);
}
+static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio)
+{
+ return folio_address(folio) + F2FS_BLKSIZE -
+ sizeof(struct node_footer);
+}
+
static inline struct f2fs_node *F2FS_NODE(const struct folio *folio)
{
return (struct f2fs_node *)folio_address(folio);
@@ -2307,6 +2317,12 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio)
return &((struct f2fs_node *)folio_address(folio))->i;
}
+static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio)
+{
+ return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) -
+ SIZE_OF_I_NID;
+}
+
static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
{
return (struct f2fs_nm_info *)(sbi->nm_info);
@@ -3277,13 +3293,11 @@ static inline void f2fs_radix_tree_insert(struct radix_tree_root *root,
cond_resched();
}
-#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino)
-
static inline bool IS_INODE(const struct folio *folio)
{
- struct f2fs_node *p = F2FS_NODE(folio);
+ struct node_footer *footer = F2FS_NODE_FOOTER(folio);
- return RAW_IS_INODE(p);
+ return footer->nid == footer->ino;
}
static inline int offset_in_addr(struct f2fs_inode *i)
@@ -3292,9 +3306,11 @@ static inline int offset_in_addr(struct f2fs_inode *i)
(le16_to_cpu(i->i_extra_isize) / sizeof(__le32)) : 0;
}
-static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
+static inline __le32 *blkaddr_in_node(const struct folio *folio)
{
- return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
+ struct f2fs_node *node = F2FS_NODE(folio);
+
+ return IS_INODE(folio) ? node->i.i_addr : node->dn.addr;
}
static inline int f2fs_has_extra_attr(struct inode *inode);
@@ -3311,7 +3327,7 @@ static inline unsigned int get_dnode_base(struct inode *inode,
static inline __le32 *get_dnode_addr(struct inode *inode,
struct folio *node_folio)
{
- return blkaddr_in_node(F2FS_NODE(node_folio)) +
+ return blkaddr_in_node(node_folio) +
get_dnode_base(inode, node_folio);
}
@@ -3639,7 +3655,7 @@ void *inline_xattr_addr(struct inode *inode, const struct folio *folio)
{
struct f2fs_inode *ri = F2FS_INODE(folio);
- return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE -
+ return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE_SBI(F2FS_I_SB(inode)) -
get_inline_xattr_addrs(inode)]);
}
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index c15c6ba91597..f15ab07a7347 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1176,7 +1176,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
if (IS_INODE(node_folio)) {
base = offset_in_addr(F2FS_INODE(node_folio));
- max_addrs = DEF_ADDRS_PER_INODE;
+ max_addrs = DEF_ADDRS_PER_INODE_SBI(sbi);
} else {
base = 0;
max_addrs = DEF_ADDRS_PER_BLOCK;
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 718dd785865a..73cd9b6ddcc5 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -36,14 +36,13 @@ bool f2fs_may_inline_data(struct inode *inode)
static bool inode_has_blocks(struct inode *inode, struct folio *ifolio)
{
- struct f2fs_inode *ri = F2FS_INODE(ifolio);
int i;
if (F2FS_HAS_BLOCKS(inode))
return true;
for (i = 0; i < DEF_NIDS_PER_INODE; i++) {
- if (ri->i_nid[i])
+ if (F2FS_INODE_NIDS(ifolio)[i])
return true;
}
return false;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 96cc0e777567..fda9ee3bfc61 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -150,9 +150,8 @@ bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
{
- struct f2fs_node *node = F2FS_NODE(folio);
- struct f2fs_inode *ri = &node->i;
- __le32 ino = node->footer.ino;
+ struct f2fs_inode *ri = F2FS_INODE(folio);
+ __le32 ino = F2FS_NODE_FOOTER(folio)->ino;
__le32 gen = ri->i_generation;
__u32 chksum, chksum_seed;
__u32 dummy_cs = 0;
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 960c6657d0d6..e3f594f7bcce 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -3001,7 +3001,6 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
unsigned int segno, struct f2fs_summary_block *sum)
{
- struct f2fs_node *rn;
struct f2fs_summary *sum_entry;
block_t addr;
int i, idx, last_offset, nrpages;
@@ -3023,8 +3022,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
if (IS_ERR(folio))
return PTR_ERR(folio);
- rn = F2FS_NODE(folio);
- sum_entry->nid = rn->footer.nid;
+ sum_entry->nid = F2FS_NODE_FOOTER(folio)->nid;
sum_entry->version = 0;
sum_entry->ofs_in_node = 0;
sum_entry++;
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 0dce97aac5fc..6a2b7c63f4a3 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -252,73 +252,68 @@ static inline void set_to_next_nat(struct f2fs_sb_info *sbi,
static inline nid_t ino_of_node(const struct folio *node_folio)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le32_to_cpu(rn->footer.ino);
+ return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->ino);
}
static inline nid_t nid_of_node(const struct folio *node_folio)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le32_to_cpu(rn->footer.nid);
+ return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->nid);
}
static inline unsigned int ofs_of_node(const struct folio *node_folio)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- unsigned flag = le32_to_cpu(rn->footer.flag);
+ unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->flag);
return flag >> OFFSET_BIT_SHIFT;
}
static inline __u64 cpver_of_node(const struct folio *node_folio)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le64_to_cpu(rn->footer.cp_ver);
+ return le64_to_cpu(F2FS_NODE_FOOTER(node_folio)->cp_ver);
}
static inline block_t next_blkaddr_of_node(const struct folio *node_folio)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le32_to_cpu(rn->footer.next_blkaddr);
+ return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->next_blkaddr);
}
static inline void fill_node_footer(const struct folio *folio, nid_t nid,
nid_t ino, unsigned int ofs, bool reset)
{
struct f2fs_node *rn = F2FS_NODE(folio);
+ struct node_footer *footer = F2FS_NODE_FOOTER(folio);
unsigned int old_flag = 0;
if (reset)
- memset(rn, 0, sizeof(*rn));
+ memset(rn, 0, F2FS_BLKSIZE);
else
- old_flag = le32_to_cpu(rn->footer.flag);
+ old_flag = le32_to_cpu(footer->flag);
- rn->footer.nid = cpu_to_le32(nid);
- rn->footer.ino = cpu_to_le32(ino);
+ footer->nid = cpu_to_le32(nid);
+ footer->ino = cpu_to_le32(ino);
/* should remain old flag bits such as COLD_BIT_SHIFT */
- rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
+ footer->flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
(old_flag & OFFSET_BIT_MASK));
}
static inline void copy_node_footer(const struct folio *dst,
const struct folio *src)
{
- struct f2fs_node *src_rn = F2FS_NODE(src);
- struct f2fs_node *dst_rn = F2FS_NODE(dst);
- memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
+ memcpy(F2FS_NODE_FOOTER(dst), F2FS_NODE_FOOTER(src),
+ sizeof(struct node_footer));
}
static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
- struct f2fs_node *rn = F2FS_NODE(folio);
+ struct node_footer *footer = F2FS_NODE_FOOTER(folio);
__u64 cp_ver = cur_cp_version(ckpt);
if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
cp_ver |= (cur_cp_crc(ckpt) << 32);
- rn->footer.cp_ver = cpu_to_le64(cp_ver);
- rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
+ footer->cp_ver = cpu_to_le64(cp_ver);
+ footer->next_blkaddr = cpu_to_le32(blkaddr);
}
static inline bool is_recoverable_dnode(const struct folio *folio)
@@ -378,11 +373,12 @@ static inline bool IS_DNODE(const struct folio *node_folio)
static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
{
struct f2fs_node *rn = F2FS_NODE(folio);
+ __le32 *inode_nids = F2FS_INODE_NIDS(folio);
f2fs_folio_wait_writeback(folio, NODE, true, true);
if (i)
- rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
+ inode_nids[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
else
rn->in.nid[off] = cpu_to_le32(nid);
return folio_mark_dirty(folio);
@@ -391,9 +387,10 @@ static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
static inline nid_t get_nid(const struct folio *folio, int off, bool i)
{
struct f2fs_node *rn = F2FS_NODE(folio);
+ const __le32 *inode_nids = F2FS_INODE_NIDS(folio);
if (i)
- return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
+ return le32_to_cpu(inode_nids[off - NODE_DIR1_BLOCK]);
return le32_to_cpu(rn->in.nid[off]);
}
@@ -406,8 +403,7 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i)
static inline int is_node(const struct folio *folio, int type)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
- return le32_to_cpu(rn->footer.flag) & BIT(type);
+ return le32_to_cpu(F2FS_NODE_FOOTER(folio)->flag) & BIT(type);
}
#define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT)
@@ -416,14 +412,13 @@ static inline int is_node(const struct folio *folio, int type)
static inline void __set_mark(const struct folio *folio, bool mark, int type)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
- unsigned int flag = le32_to_cpu(rn->footer.flag);
-
+ struct node_footer *footer = F2FS_NODE_FOOTER(folio);
+ unsigned int flag = le32_to_cpu(footer->flag);
if (mark)
flag |= BIT(type);
else
flag &= ~BIT(type);
- rn->footer.flag = cpu_to_le32(flag);
+ footer->flag = cpu_to_le32(flag);
}
static inline void set_cold_node(const struct folio *folio, bool is_dir)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 8d2224e585d3..fcaeaacaab33 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4384,6 +4384,11 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->blocksize = BIT(sbi->log_blocksize);
sbi->nat_entries_per_block = sbi->blocksize /
sizeof(struct f2fs_nat_entry);
+ sbi->addrs_per_inode = (sbi->blocksize - OFFSET_OF_END_OF_I_EXT -
+ SIZE_OF_I_NID - sizeof(struct node_footer)) / sizeof(__le32);
+ sbi->addrs_per_block = (sbi->blocksize -
+ sizeof(struct node_footer)) / sizeof(__le32);
+ sbi->nids_per_block = sbi->addrs_per_block;
sbi->sit_entries_per_block = sbi->blocksize /
sizeof(struct f2fs_sit_entry);
sbi->orphans_per_block = (sbi->blocksize -
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index d1059a27e1b9..3d0fe2c78e12 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -16,6 +16,7 @@
#define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
#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_MAX_BLKSIZE PAGE_SIZE
#define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
#define F2FS_MAX_EXTENSION 64 /* # of extension entries */
#define F2FS_EXTENSION_LEN 8 /* max size of extension */
@@ -343,18 +344,25 @@ struct f2fs_inode {
*/
__le32 i_extra_end[0]; /* for attribute size calculation */
} __packed;
- __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
+ DECLARE_FLEX_ARRAY(__le32, i_addr); /* data block pointers */
};
- __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2),
- double_indirect(1) node id */
+ /*
+ * __le32 i_nid[DEF_NIDS_PER_INODE];
+ *
+ * It is stored immediately before the node footer at the end of the
+ * filesystem block. Its offset depends on the filesystem block size, so
+ * locate it dynamically with F2FS_INODE_NIDS().
+ */
} __packed;
struct direct_node {
- __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */
+ /* The address count depends on the filesystem block size. */
+ DECLARE_FLEX_ARRAY(__le32, addr); /* array of data block address */
} __packed;
struct indirect_node {
- __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */
+ /* The node ID count depends on the filesystem block size. */
+ DECLARE_FLEX_ARRAY(__le32, nid); /* array of data block address */
} __packed;
enum {
@@ -373,7 +381,13 @@ struct f2fs_node {
struct direct_node dn;
struct indirect_node in;
};
- struct node_footer footer;
+ /*
+ * struct node_footer footer;
+ *
+ * It is stored at the end of the filesystem block, after the inode or
+ * direct/indirect node data. Its offset depends on the filesystem block
+ * size, so locate it dynamically with F2FS_NODE_FOOTER().
+ */
} __packed;
/*
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node block layout dynamically
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node " Kelvin Zhang
@ 2026-09-01 0:56 ` Daeho Jeong
2026-09-01 16:38 ` Xinping Zhang
2026-09-01 11:48 ` Chao Yu via Linux-f2fs-devel
2026-09-02 23:52 ` Xinping Zhang
2 siblings, 1 reply; 30+ messages in thread
From: Daeho Jeong @ 2026-09-01 0:56 UTC (permalink / raw)
To: Kelvin Zhang; +Cc: jaegeuk, linux-kernel, linux-f2fs-devel
On Mon, Aug 31, 2026 at 3:12 PM Kelvin Zhang <zhangxp1998@gmail.com> wrote:
>
> An inode block ends with five i_nid entries followed by a node footer.
> Data block address pointers (i_addr[]) precede them. Similarly, direct and
> indirect node blocks contain data addresses or node IDs followed by a node
> footer at the end of the block.
>
> Describe struct f2fs_inode, struct direct_node, and
> struct indirect_node using flexible array members. Compute the locations
> of i_nid and node footers dynamically from the filesystem block size.
> Introduce F2FS_INODE_NIDS() and F2FS_NODE_FOOTER() helpers to access these
> tail fields.
>
> Compute sbi->addrs_per_inode, sbi->addrs_per_block, and
> sbi->nids_per_block in init_sb_info(), and update node management, file
> mapping, and recovery paths accordingly.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/data.c | 2 +-
> fs/f2fs/f2fs.h | 32 ++++++++++++++++++-------
> fs/f2fs/gc.c | 2 +-
> fs/f2fs/inline.c | 3 +--
> fs/f2fs/inode.c | 5 ++--
> fs/f2fs/node.c | 4 +---
> fs/f2fs/node.h | 53 +++++++++++++++++++----------------------
> fs/f2fs/super.c | 5 ++++
> include/linux/f2fs_fs.h | 26 +++++++++++++++-----
> 9 files changed, 79 insertions(+), 53 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 6ae0eb37d20f..751b7a457d9a 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -2027,7 +2027,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
>
> phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
> offset = offsetof(struct f2fs_inode, i_addr) +
> - sizeof(__le32) * (DEF_ADDRS_PER_INODE -
> + sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) -
> get_inline_xattr_addrs(inode));
>
> phys += offset;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index d2e54573ed34..247e56522441 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1853,6 +1853,9 @@ struct f2fs_sb_info {
> unsigned int log_blocksize; /* log2 block size */
> unsigned int blocksize; /* block size */
> unsigned int nat_entries_per_block; /* NAT entries in a block */
> + unsigned int addrs_per_inode; /* addresses in an inode block */
> + unsigned int addrs_per_block; /* addresses in a direct node block */
> + unsigned int nids_per_block; /* node IDs in an indirect node block */
> unsigned int sit_entries_per_block; /* SIT entries in a block */
> unsigned int orphans_per_block; /* orphan inodes in a block */
> unsigned int dentries_per_block; /* dentries in a block */
> @@ -2248,6 +2251,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
>
> #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
> #define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
> +#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode)
The awkward `_SBI` suffix in DEF_ADDRS_PER_INODE_SBI(sbi) was introduced because
DEF_ADDRS_PER_INODE(inode) was already defined in include/linux/f2fs_fs.h using
the kernel VFS helper i_blocksize(inode).
However:
1. include/linux/f2fs_fs.h is a shared UAPI/on-disk header (synced
with f2fs-tools),
so embedding kernel VFS helpers like `i_blocksize(inode)` does not
belong there?
2. All other geometry macros in fs/f2fs/f2fs.h consistently take
`(sbi)` and return
the precomputed cached values (e.g. DEF_ADDRS_PER_BLOCK(sbi),
NIDS_PER_BLOCK(sbi),
SIT_ENTRY_PER_BLOCK(sbi), NAT_ENTRY_PER_BLOCK(sbi)).
To make the interface clean and consistent:
1) In include/linux/f2fs_fs.h (formula parameterized by blocksize for
tools/generic use):
#define F2FS_DEF_ADDRS_PER_INODE(bs) \
(((bs) - OFFSET_OF_END_OF_I_EXT - SIZE_OF_I_NID - \
sizeof(struct node_footer)) / sizeof(__le32))
2) In fs/f2fs/f2fs.h (kernel fast-path lookup, matching other macros):
#define DEF_ADDRS_PER_INODE(sbi) ((sbi)->addrs_per_inode)
#define DEF_ADDRS_PER_BLOCK(sbi) ((sbi)->addrs_per_block)
#define NIDS_PER_BLOCK(sbi) ((sbi)->nids_per_block)
This eliminates the awkward DEF_ADDRS_PER_INODE_SBI() macro completely and keeps
macro naming consistent across the entire subsystem.
> #define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
> #define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
> F2FS_ORPHANS_PER_BLOCK(sbi))
> @@ -2297,6 +2301,12 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
> return (struct f2fs_checkpoint *)(sbi->ckpt);
> }
>
> +static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio)
> +{
> + return folio_address(folio) + F2FS_BLKSIZE -
> + sizeof(struct node_footer);
> +}
> +
> static inline struct f2fs_node *F2FS_NODE(const struct folio *folio)
> {
> return (struct f2fs_node *)folio_address(folio);
> @@ -2307,6 +2317,12 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio)
> return &((struct f2fs_node *)folio_address(folio))->i;
> }
>
> +static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio)
> +{
> + return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) -
> + SIZE_OF_I_NID;
> +}
> +
> static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
> {
> return (struct f2fs_nm_info *)(sbi->nm_info);
> @@ -3277,13 +3293,11 @@ static inline void f2fs_radix_tree_insert(struct radix_tree_root *root,
> cond_resched();
> }
>
> -#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino)
> -
> static inline bool IS_INODE(const struct folio *folio)
> {
> - struct f2fs_node *p = F2FS_NODE(folio);
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
>
> - return RAW_IS_INODE(p);
> + return footer->nid == footer->ino;
> }
>
> static inline int offset_in_addr(struct f2fs_inode *i)
> @@ -3292,9 +3306,11 @@ static inline int offset_in_addr(struct f2fs_inode *i)
> (le16_to_cpu(i->i_extra_isize) / sizeof(__le32)) : 0;
> }
>
> -static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
> +static inline __le32 *blkaddr_in_node(const struct folio *folio)
> {
> - return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
> + struct f2fs_node *node = F2FS_NODE(folio);
> +
> + return IS_INODE(folio) ? node->i.i_addr : node->dn.addr;
> }
>
> static inline int f2fs_has_extra_attr(struct inode *inode);
> @@ -3311,7 +3327,7 @@ static inline unsigned int get_dnode_base(struct inode *inode,
> static inline __le32 *get_dnode_addr(struct inode *inode,
> struct folio *node_folio)
> {
> - return blkaddr_in_node(F2FS_NODE(node_folio)) +
> + return blkaddr_in_node(node_folio) +
> get_dnode_base(inode, node_folio);
> }
>
> @@ -3639,7 +3655,7 @@ void *inline_xattr_addr(struct inode *inode, const struct folio *folio)
> {
> struct f2fs_inode *ri = F2FS_INODE(folio);
>
> - return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE -
> + return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE_SBI(F2FS_I_SB(inode)) -
> get_inline_xattr_addrs(inode)]);
> }
>
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index c15c6ba91597..f15ab07a7347 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1176,7 +1176,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
>
> if (IS_INODE(node_folio)) {
> base = offset_in_addr(F2FS_INODE(node_folio));
> - max_addrs = DEF_ADDRS_PER_INODE;
> + max_addrs = DEF_ADDRS_PER_INODE_SBI(sbi);
> } else {
> base = 0;
> max_addrs = DEF_ADDRS_PER_BLOCK;
> diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
> index 718dd785865a..73cd9b6ddcc5 100644
> --- a/fs/f2fs/inline.c
> +++ b/fs/f2fs/inline.c
> @@ -36,14 +36,13 @@ bool f2fs_may_inline_data(struct inode *inode)
>
> static bool inode_has_blocks(struct inode *inode, struct folio *ifolio)
> {
> - struct f2fs_inode *ri = F2FS_INODE(ifolio);
> int i;
>
> if (F2FS_HAS_BLOCKS(inode))
> return true;
>
> for (i = 0; i < DEF_NIDS_PER_INODE; i++) {
> - if (ri->i_nid[i])
> + if (F2FS_INODE_NIDS(ifolio)[i])
> return true;
> }
> return false;
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index 96cc0e777567..fda9ee3bfc61 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -150,9 +150,8 @@ bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
>
> static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
> {
> - struct f2fs_node *node = F2FS_NODE(folio);
> - struct f2fs_inode *ri = &node->i;
> - __le32 ino = node->footer.ino;
> + struct f2fs_inode *ri = F2FS_INODE(folio);
> + __le32 ino = F2FS_NODE_FOOTER(folio)->ino;
> __le32 gen = ri->i_generation;
> __u32 chksum, chksum_seed;
> __u32 dummy_cs = 0;
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 960c6657d0d6..e3f594f7bcce 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -3001,7 +3001,6 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
> int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> unsigned int segno, struct f2fs_summary_block *sum)
> {
> - struct f2fs_node *rn;
> struct f2fs_summary *sum_entry;
> block_t addr;
> int i, idx, last_offset, nrpages;
> @@ -3023,8 +3022,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> if (IS_ERR(folio))
> return PTR_ERR(folio);
>
> - rn = F2FS_NODE(folio);
> - sum_entry->nid = rn->footer.nid;
> + sum_entry->nid = F2FS_NODE_FOOTER(folio)->nid;
> sum_entry->version = 0;
> sum_entry->ofs_in_node = 0;
> sum_entry++;
> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
> index 0dce97aac5fc..6a2b7c63f4a3 100644
> --- a/fs/f2fs/node.h
> +++ b/fs/f2fs/node.h
> @@ -252,73 +252,68 @@ static inline void set_to_next_nat(struct f2fs_sb_info *sbi,
>
> static inline nid_t ino_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le32_to_cpu(rn->footer.ino);
> + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->ino);
> }
>
> static inline nid_t nid_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le32_to_cpu(rn->footer.nid);
> + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->nid);
> }
>
> static inline unsigned int ofs_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - unsigned flag = le32_to_cpu(rn->footer.flag);
> + unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->flag);
> return flag >> OFFSET_BIT_SHIFT;
> }
>
> static inline __u64 cpver_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le64_to_cpu(rn->footer.cp_ver);
> + return le64_to_cpu(F2FS_NODE_FOOTER(node_folio)->cp_ver);
> }
>
> static inline block_t next_blkaddr_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le32_to_cpu(rn->footer.next_blkaddr);
> + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->next_blkaddr);
> }
>
> static inline void fill_node_footer(const struct folio *folio, nid_t nid,
> nid_t ino, unsigned int ofs, bool reset)
> {
> struct f2fs_node *rn = F2FS_NODE(folio);
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
> unsigned int old_flag = 0;
>
> if (reset)
> - memset(rn, 0, sizeof(*rn));
> + memset(rn, 0, F2FS_BLKSIZE);
> else
> - old_flag = le32_to_cpu(rn->footer.flag);
> + old_flag = le32_to_cpu(footer->flag);
>
> - rn->footer.nid = cpu_to_le32(nid);
> - rn->footer.ino = cpu_to_le32(ino);
> + footer->nid = cpu_to_le32(nid);
> + footer->ino = cpu_to_le32(ino);
>
> /* should remain old flag bits such as COLD_BIT_SHIFT */
> - rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
> + footer->flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
> (old_flag & OFFSET_BIT_MASK));
> }
>
> static inline void copy_node_footer(const struct folio *dst,
> const struct folio *src)
> {
> - struct f2fs_node *src_rn = F2FS_NODE(src);
> - struct f2fs_node *dst_rn = F2FS_NODE(dst);
> - memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
> + memcpy(F2FS_NODE_FOOTER(dst), F2FS_NODE_FOOTER(src),
> + sizeof(struct node_footer));
> }
>
> static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr)
> {
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
> - struct f2fs_node *rn = F2FS_NODE(folio);
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
> __u64 cp_ver = cur_cp_version(ckpt);
>
> if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
> cp_ver |= (cur_cp_crc(ckpt) << 32);
>
> - rn->footer.cp_ver = cpu_to_le64(cp_ver);
> - rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
> + footer->cp_ver = cpu_to_le64(cp_ver);
> + footer->next_blkaddr = cpu_to_le32(blkaddr);
> }
>
> static inline bool is_recoverable_dnode(const struct folio *folio)
> @@ -378,11 +373,12 @@ static inline bool IS_DNODE(const struct folio *node_folio)
> static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
> {
> struct f2fs_node *rn = F2FS_NODE(folio);
> + __le32 *inode_nids = F2FS_INODE_NIDS(folio);
>
> f2fs_folio_wait_writeback(folio, NODE, true, true);
>
> if (i)
> - rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
> + inode_nids[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
> else
> rn->in.nid[off] = cpu_to_le32(nid);
> return folio_mark_dirty(folio);
> @@ -391,9 +387,10 @@ static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
> static inline nid_t get_nid(const struct folio *folio, int off, bool i)
> {
> struct f2fs_node *rn = F2FS_NODE(folio);
> + const __le32 *inode_nids = F2FS_INODE_NIDS(folio);
>
> if (i)
> - return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
> + return le32_to_cpu(inode_nids[off - NODE_DIR1_BLOCK]);
> return le32_to_cpu(rn->in.nid[off]);
> }
>
> @@ -406,8 +403,7 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i)
>
> static inline int is_node(const struct folio *folio, int type)
> {
> - struct f2fs_node *rn = F2FS_NODE(folio);
> - return le32_to_cpu(rn->footer.flag) & BIT(type);
> + return le32_to_cpu(F2FS_NODE_FOOTER(folio)->flag) & BIT(type);
> }
>
> #define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT)
> @@ -416,14 +412,13 @@ static inline int is_node(const struct folio *folio, int type)
>
> static inline void __set_mark(const struct folio *folio, bool mark, int type)
> {
> - struct f2fs_node *rn = F2FS_NODE(folio);
> - unsigned int flag = le32_to_cpu(rn->footer.flag);
> -
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
> + unsigned int flag = le32_to_cpu(footer->flag);
> if (mark)
> flag |= BIT(type);
> else
> flag &= ~BIT(type);
> - rn->footer.flag = cpu_to_le32(flag);
> + footer->flag = cpu_to_le32(flag);
> }
>
> static inline void set_cold_node(const struct folio *folio, bool is_dir)
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 8d2224e585d3..fcaeaacaab33 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4384,6 +4384,11 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
> sbi->blocksize = BIT(sbi->log_blocksize);
> sbi->nat_entries_per_block = sbi->blocksize /
> sizeof(struct f2fs_nat_entry);
> + sbi->addrs_per_inode = (sbi->blocksize - OFFSET_OF_END_OF_I_EXT -
> + SIZE_OF_I_NID - sizeof(struct node_footer)) / sizeof(__le32);
> + sbi->addrs_per_block = (sbi->blocksize -
> + sizeof(struct node_footer)) / sizeof(__le32);
> + sbi->nids_per_block = sbi->addrs_per_block;
> sbi->sit_entries_per_block = sbi->blocksize /
> sizeof(struct f2fs_sit_entry);
> sbi->orphans_per_block = (sbi->blocksize -
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index d1059a27e1b9..3d0fe2c78e12 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -16,6 +16,7 @@
> #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
> #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_MAX_BLKSIZE PAGE_SIZE
> #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
> #define F2FS_MAX_EXTENSION 64 /* # of extension entries */
> #define F2FS_EXTENSION_LEN 8 /* max size of extension */
> @@ -343,18 +344,25 @@ struct f2fs_inode {
> */
> __le32 i_extra_end[0]; /* for attribute size calculation */
> } __packed;
> - __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
> + DECLARE_FLEX_ARRAY(__le32, i_addr); /* data block pointers */
> };
> - __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2),
> - double_indirect(1) node id */
> + /*
> + * __le32 i_nid[DEF_NIDS_PER_INODE];
> + *
> + * It is stored immediately before the node footer at the end of the
> + * filesystem block. Its offset depends on the filesystem block size, so
> + * locate it dynamically with F2FS_INODE_NIDS().
> + */
> } __packed;
>
> struct direct_node {
> - __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */
> + /* The address count depends on the filesystem block size. */
> + DECLARE_FLEX_ARRAY(__le32, addr); /* array of data block address */
> } __packed;
>
> struct indirect_node {
> - __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */
> + /* The node ID count depends on the filesystem block size. */
> + DECLARE_FLEX_ARRAY(__le32, nid); /* array of data block address */
> } __packed;
>
> enum {
> @@ -373,7 +381,13 @@ struct f2fs_node {
> struct direct_node dn;
> struct indirect_node in;
> };
> - struct node_footer footer;
> + /*
> + * struct node_footer footer;
> + *
> + * It is stored at the end of the filesystem block, after the inode or
> + * direct/indirect node data. Its offset depends on the filesystem block
> + * size, so locate it dynamically with F2FS_NODE_FOOTER().
> + */
> } __packed;
>
> /*
> --
> 2.53.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node block layout dynamically
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node " Kelvin Zhang
2026-09-01 0:56 ` Daeho Jeong
@ 2026-09-01 11:48 ` Chao Yu via Linux-f2fs-devel
2026-09-01 16:38 ` Xinping Zhang
2026-09-02 23:52 ` Xinping Zhang
2 siblings, 1 reply; 30+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2026-09-01 11:48 UTC (permalink / raw)
To: Kelvin Zhang, linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
On 9/1/26 06:08, Kelvin Zhang wrote:
> An inode block ends with five i_nid entries followed by a node footer.
> Data block address pointers (i_addr[]) precede them. Similarly, direct and
> indirect node blocks contain data addresses or node IDs followed by a node
> footer at the end of the block.
>
> Describe struct f2fs_inode, struct direct_node, and
> struct indirect_node using flexible array members. Compute the locations
> of i_nid and node footers dynamically from the filesystem block size.
> Introduce F2FS_INODE_NIDS() and F2FS_NODE_FOOTER() helpers to access these
> tail fields.
>
> Compute sbi->addrs_per_inode, sbi->addrs_per_block, and
> sbi->nids_per_block in init_sb_info(), and update node management, file
> mapping, and recovery paths accordingly.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/data.c | 2 +-
> fs/f2fs/f2fs.h | 32 ++++++++++++++++++-------
> fs/f2fs/gc.c | 2 +-
> fs/f2fs/inline.c | 3 +--
> fs/f2fs/inode.c | 5 ++--
> fs/f2fs/node.c | 4 +---
> fs/f2fs/node.h | 53 +++++++++++++++++++----------------------
> fs/f2fs/super.c | 5 ++++
> include/linux/f2fs_fs.h | 26 +++++++++++++++-----
> 9 files changed, 79 insertions(+), 53 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 6ae0eb37d20f..751b7a457d9a 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -2027,7 +2027,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
>
> phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
> offset = offsetof(struct f2fs_inode, i_addr) +
> - sizeof(__le32) * (DEF_ADDRS_PER_INODE -
> + sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) -
> get_inline_xattr_addrs(inode));
>
> phys += offset;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index d2e54573ed34..247e56522441 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1853,6 +1853,9 @@ struct f2fs_sb_info {
> unsigned int log_blocksize; /* log2 block size */
> unsigned int blocksize; /* block size */
> unsigned int nat_entries_per_block; /* NAT entries in a block */
> + unsigned int addrs_per_inode; /* addresses in an inode block */
> + unsigned int addrs_per_block; /* addresses in a direct node block */
> + unsigned int nids_per_block; /* node IDs in an indirect node block */
> unsigned int sit_entries_per_block; /* SIT entries in a block */
> unsigned int orphans_per_block; /* orphan inodes in a block */
> unsigned int dentries_per_block; /* dentries in a block */
> @@ -2248,6 +2251,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
>
> #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
> #define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
> +#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode)
#define DEF_ADDRS_PER_INODE
> #define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
> #define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
> F2FS_ORPHANS_PER_BLOCK(sbi))
> @@ -2297,6 +2301,12 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
> return (struct f2fs_checkpoint *)(sbi->ckpt);
> }
>
> +static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio)
> +{
> + return folio_address(folio) + F2FS_BLKSIZE -
> + sizeof(struct node_footer);
> +}
> +
> static inline struct f2fs_node *F2FS_NODE(const struct folio *folio)
> {
> return (struct f2fs_node *)folio_address(folio);
> @@ -2307,6 +2317,12 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio)
> return &((struct f2fs_node *)folio_address(folio))->i;
> }
>
> +static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio)
> +{
> + return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) -
> + SIZE_OF_I_NID;
> +}
> +
> static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
> {
> return (struct f2fs_nm_info *)(sbi->nm_info);
> @@ -3277,13 +3293,11 @@ static inline void f2fs_radix_tree_insert(struct radix_tree_root *root,
> cond_resched();
> }
>
> -#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino)
> -
> static inline bool IS_INODE(const struct folio *folio)
> {
> - struct f2fs_node *p = F2FS_NODE(folio);
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
>
> - return RAW_IS_INODE(p);
> + return footer->nid == footer->ino;
> }
>
> static inline int offset_in_addr(struct f2fs_inode *i)
> @@ -3292,9 +3306,11 @@ static inline int offset_in_addr(struct f2fs_inode *i)
> (le16_to_cpu(i->i_extra_isize) / sizeof(__le32)) : 0;
> }
>
> -static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
> +static inline __le32 *blkaddr_in_node(const struct folio *folio)
> {
> - return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
> + struct f2fs_node *node = F2FS_NODE(folio);
> +
> + return IS_INODE(folio) ? node->i.i_addr : node->dn.addr;
> }
>
> static inline int f2fs_has_extra_attr(struct inode *inode);
> @@ -3311,7 +3327,7 @@ static inline unsigned int get_dnode_base(struct inode *inode,
> static inline __le32 *get_dnode_addr(struct inode *inode,
> struct folio *node_folio)
> {
> - return blkaddr_in_node(F2FS_NODE(node_folio)) +
> + return blkaddr_in_node(node_folio) +
> get_dnode_base(inode, node_folio);
> }
>
> @@ -3639,7 +3655,7 @@ void *inline_xattr_addr(struct inode *inode, const struct folio *folio)
> {
> struct f2fs_inode *ri = F2FS_INODE(folio);
>
> - return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE -
> + return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE_SBI(F2FS_I_SB(inode)) -
> get_inline_xattr_addrs(inode)]);
> }
>
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index c15c6ba91597..f15ab07a7347 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1176,7 +1176,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
>
> if (IS_INODE(node_folio)) {
> base = offset_in_addr(F2FS_INODE(node_folio));
> - max_addrs = DEF_ADDRS_PER_INODE;
> + max_addrs = DEF_ADDRS_PER_INODE_SBI(sbi);
> } else {
> base = 0;
> max_addrs = DEF_ADDRS_PER_BLOCK;
> diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
> index 718dd785865a..73cd9b6ddcc5 100644
> --- a/fs/f2fs/inline.c
> +++ b/fs/f2fs/inline.c
> @@ -36,14 +36,13 @@ bool f2fs_may_inline_data(struct inode *inode)
>
> static bool inode_has_blocks(struct inode *inode, struct folio *ifolio)
> {
> - struct f2fs_inode *ri = F2FS_INODE(ifolio);
> int i;
>
> if (F2FS_HAS_BLOCKS(inode))
> return true;
>
> for (i = 0; i < DEF_NIDS_PER_INODE; i++) {
> - if (ri->i_nid[i])
> + if (F2FS_INODE_NIDS(ifolio)[i])
> return true;
> }
> return false;
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index 96cc0e777567..fda9ee3bfc61 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -150,9 +150,8 @@ bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
>
> static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
> {
> - struct f2fs_node *node = F2FS_NODE(folio);
> - struct f2fs_inode *ri = &node->i;
> - __le32 ino = node->footer.ino;
> + struct f2fs_inode *ri = F2FS_INODE(folio);
> + __le32 ino = F2FS_NODE_FOOTER(folio)->ino;
> __le32 gen = ri->i_generation;
> __u32 chksum, chksum_seed;
> __u32 dummy_cs = 0;
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 960c6657d0d6..e3f594f7bcce 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -3001,7 +3001,6 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio)
> int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> unsigned int segno, struct f2fs_summary_block *sum)
> {
> - struct f2fs_node *rn;
> struct f2fs_summary *sum_entry;
> block_t addr;
> int i, idx, last_offset, nrpages;
> @@ -3023,8 +3022,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
> if (IS_ERR(folio))
> return PTR_ERR(folio);
>
> - rn = F2FS_NODE(folio);
> - sum_entry->nid = rn->footer.nid;
> + sum_entry->nid = F2FS_NODE_FOOTER(folio)->nid;
> sum_entry->version = 0;
> sum_entry->ofs_in_node = 0;
> sum_entry++;
> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
> index 0dce97aac5fc..6a2b7c63f4a3 100644
> --- a/fs/f2fs/node.h
> +++ b/fs/f2fs/node.h
> @@ -252,73 +252,68 @@ static inline void set_to_next_nat(struct f2fs_sb_info *sbi,
>
> static inline nid_t ino_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le32_to_cpu(rn->footer.ino);
> + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->ino);
> }
>
> static inline nid_t nid_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le32_to_cpu(rn->footer.nid);
> + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->nid);
> }
>
> static inline unsigned int ofs_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - unsigned flag = le32_to_cpu(rn->footer.flag);
> + unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->flag);
> return flag >> OFFSET_BIT_SHIFT;
> }
>
> static inline __u64 cpver_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le64_to_cpu(rn->footer.cp_ver);
> + return le64_to_cpu(F2FS_NODE_FOOTER(node_folio)->cp_ver);
> }
>
> static inline block_t next_blkaddr_of_node(const struct folio *node_folio)
> {
> - struct f2fs_node *rn = F2FS_NODE(node_folio);
> - return le32_to_cpu(rn->footer.next_blkaddr);
> + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->next_blkaddr);
> }
>
> static inline void fill_node_footer(const struct folio *folio, nid_t nid,
> nid_t ino, unsigned int ofs, bool reset)
> {
> struct f2fs_node *rn = F2FS_NODE(folio);
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
> unsigned int old_flag = 0;
>
> if (reset)
> - memset(rn, 0, sizeof(*rn));
> + memset(rn, 0, F2FS_BLKSIZE);
> else
> - old_flag = le32_to_cpu(rn->footer.flag);
> + old_flag = le32_to_cpu(footer->flag);
>
> - rn->footer.nid = cpu_to_le32(nid);
> - rn->footer.ino = cpu_to_le32(ino);
> + footer->nid = cpu_to_le32(nid);
> + footer->ino = cpu_to_le32(ino);
>
> /* should remain old flag bits such as COLD_BIT_SHIFT */
> - rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
> + footer->flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
> (old_flag & OFFSET_BIT_MASK));
> }
>
> static inline void copy_node_footer(const struct folio *dst,
> const struct folio *src)
> {
> - struct f2fs_node *src_rn = F2FS_NODE(src);
> - struct f2fs_node *dst_rn = F2FS_NODE(dst);
> - memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
> + memcpy(F2FS_NODE_FOOTER(dst), F2FS_NODE_FOOTER(src),
> + sizeof(struct node_footer));
> }
>
> static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr)
> {
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
> - struct f2fs_node *rn = F2FS_NODE(folio);
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
> __u64 cp_ver = cur_cp_version(ckpt);
>
> if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
> cp_ver |= (cur_cp_crc(ckpt) << 32);
>
> - rn->footer.cp_ver = cpu_to_le64(cp_ver);
> - rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
> + footer->cp_ver = cpu_to_le64(cp_ver);
> + footer->next_blkaddr = cpu_to_le32(blkaddr);
> }
>
> static inline bool is_recoverable_dnode(const struct folio *folio)
> @@ -378,11 +373,12 @@ static inline bool IS_DNODE(const struct folio *node_folio)
> static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
> {
> struct f2fs_node *rn = F2FS_NODE(folio);
> + __le32 *inode_nids = F2FS_INODE_NIDS(folio);
>
> f2fs_folio_wait_writeback(folio, NODE, true, true);
>
> if (i)
> - rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
> + inode_nids[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
> else
> rn->in.nid[off] = cpu_to_le32(nid);
> return folio_mark_dirty(folio);
> @@ -391,9 +387,10 @@ static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
> static inline nid_t get_nid(const struct folio *folio, int off, bool i)
> {
> struct f2fs_node *rn = F2FS_NODE(folio);
> + const __le32 *inode_nids = F2FS_INODE_NIDS(folio);
>
> if (i)
> - return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
> + return le32_to_cpu(inode_nids[off - NODE_DIR1_BLOCK]);
> return le32_to_cpu(rn->in.nid[off]);
> }
>
> @@ -406,8 +403,7 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i)
>
> static inline int is_node(const struct folio *folio, int type)
> {
> - struct f2fs_node *rn = F2FS_NODE(folio);
> - return le32_to_cpu(rn->footer.flag) & BIT(type);
> + return le32_to_cpu(F2FS_NODE_FOOTER(folio)->flag) & BIT(type);
> }
>
> #define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT)
> @@ -416,14 +412,13 @@ static inline int is_node(const struct folio *folio, int type)
>
> static inline void __set_mark(const struct folio *folio, bool mark, int type)
> {
> - struct f2fs_node *rn = F2FS_NODE(folio);
> - unsigned int flag = le32_to_cpu(rn->footer.flag);
> -
> + struct node_footer *footer = F2FS_NODE_FOOTER(folio);
> + unsigned int flag = le32_to_cpu(footer->flag);
> if (mark)
> flag |= BIT(type);
> else
> flag &= ~BIT(type);
> - rn->footer.flag = cpu_to_le32(flag);
> + footer->flag = cpu_to_le32(flag);
> }
>
> static inline void set_cold_node(const struct folio *folio, bool is_dir)
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 8d2224e585d3..fcaeaacaab33 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4384,6 +4384,11 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
> sbi->blocksize = BIT(sbi->log_blocksize);
> sbi->nat_entries_per_block = sbi->blocksize /
> sizeof(struct f2fs_nat_entry);
> + sbi->addrs_per_inode = (sbi->blocksize - OFFSET_OF_END_OF_I_EXT -
> + SIZE_OF_I_NID - sizeof(struct node_footer)) / sizeof(__le32);
> + sbi->addrs_per_block = (sbi->blocksize -
> + sizeof(struct node_footer)) / sizeof(__le32);
> + sbi->nids_per_block = sbi->addrs_per_block;
> sbi->sit_entries_per_block = sbi->blocksize /
> sizeof(struct f2fs_sit_entry);
> sbi->orphans_per_block = (sbi->blocksize -
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index d1059a27e1b9..3d0fe2c78e12 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -16,6 +16,7 @@
> #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
> #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_MAX_BLKSIZE PAGE_SIZE
It's unused in this patch?
> #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
> #define F2FS_MAX_EXTENSION 64 /* # of extension entries */
> #define F2FS_EXTENSION_LEN 8 /* max size of extension */
> @@ -343,18 +344,25 @@ struct f2fs_inode {
> */
> __le32 i_extra_end[0]; /* for attribute size calculation */
> } __packed;
> - __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
> + DECLARE_FLEX_ARRAY(__le32, i_addr); /* data block pointers */
> };
> - __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2),
> - double_indirect(1) node id */
Can you please keep the comments?
/* direct(2), indirect(2), double_indirect(1) node id */
> + /*
> + * __le32 i_nid[DEF_NIDS_PER_INODE];
> + *
> + * It is stored immediately before the node footer at the end of the
> + * filesystem block. Its offset depends on the filesystem block size, so
> + * locate it dynamically with F2FS_INODE_NIDS().
> + */
> } __packed;
>
> struct direct_node {
> - __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */
> + /* The address count depends on the filesystem block size. */
> + DECLARE_FLEX_ARRAY(__le32, addr); /* array of data block address */
> } __packed;
>
> struct indirect_node {
> - __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */
> + /* The node ID count depends on the filesystem block size. */
> + DECLARE_FLEX_ARRAY(__le32, nid); /* array of data block address */
> } __packed;
>
> enum {
> @@ -373,7 +381,13 @@ struct f2fs_node {
> struct direct_node dn;
> struct indirect_node in;
> };
> - struct node_footer footer;
> + /*
> + * struct node_footer footer;
> + *
> + * It is stored at the end of the filesystem block, after the inode or
> + * direct/indirect node data. Its offset depends on the filesystem block
> + * size, so locate it dynamically with F2FS_NODE_FOOTER().
> + */
> } __packed;
>
> /*
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node block layout dynamically
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node " Kelvin Zhang
2026-09-01 0:56 ` Daeho Jeong
2026-09-01 11:48 ` Chao Yu via Linux-f2fs-devel
@ 2026-09-02 23:52 ` Xinping Zhang
2026-09-03 1:55 ` Chao Yu via Linux-f2fs-devel
2 siblings, 1 reply; 30+ messages in thread
From: Xinping Zhang @ 2026-09-02 23:52 UTC (permalink / raw)
To: chao; +Cc: linux-f2fs-devel
Hi Chao,
The 0-day build failure on feature/subpage (lkp report; 6/11,
include/linux/f2fs_fs.h:355: "expected specifier-qualifier-list before
'*' token") is a nested comment in struct f2fs_inode.
The applied commit keeps the old inline comment "/* direct(2)... node
id */" inside the new block comment, so the inner "*/" closes the comment
early and the following lines get parsed as struct members:
/*
* __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2),
* double_indirect(1) node id */
*
* It is stored immediately before the node footer ...
*/
That's a hard compile error on every arch, not just m68k-allmodconfig.
The version I posted in v7 6/11 doesn't have this; it drops the old
inline comment. The applied commit (35efac5) looks like an earlier
revision -- its subject is "{i, d, id}node" (with spaces) vs
"{i,d,id}node" in v7. Could you re-apply v7's 6/11, or de-nest the
comment, e.g.:
/*
* __le32 i_nid[DEF_NIDS_PER_INODE];
* direct(2), indirect(2), double_indirect(1) node IDs
*
* It is stored immediately before the node footer at the end of
* the filesystem block. Its offset depends on the filesystem block
* size, so locate it dynamically with F2FS_INODE_NIDS().
*/
Thanks,
Kelvin
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node block layout dynamically
2026-09-02 23:52 ` Xinping Zhang
@ 2026-09-03 1:55 ` Chao Yu via Linux-f2fs-devel
0 siblings, 0 replies; 30+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2026-09-03 1:55 UTC (permalink / raw)
To: Xinping Zhang; +Cc: linux-f2fs-devel
Kelvin,
On 9/3/26 07:52, Xinping Zhang wrote:
> Hi Chao,
>
> The 0-day build failure on feature/subpage (lkp report; 6/11,
> include/linux/f2fs_fs.h:355: "expected specifier-qualifier-list before
> '*' token") is a nested comment in struct f2fs_inode.
>
> The applied commit keeps the old inline comment "/* direct(2)... node
> id */" inside the new block comment, so the inner "*/" closes the comment
> early and the following lines get parsed as struct members:
>
> /*
> * __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2),
> * double_indirect(1) node id */
> *
> * It is stored immediately before the node footer ...
> */
>
> That's a hard compile error on every arch, not just m68k-allmodconfig.
>
> The version I posted in v7 6/11 doesn't have this; it drops the old
> inline comment. The applied commit (35efac5) looks like an earlier
> revision -- its subject is "{i, d, id}node" (with spaces) vs
> "{i,d,id}node" in v7. Could you re-apply v7's 6/11, or de-nest the
> comment, e.g.:
>
> /*
> * __le32 i_nid[DEF_NIDS_PER_INODE];
> * direct(2), indirect(2), double_indirect(1) node IDs
> *
> * It is stored immediately before the node footer at the end of
> * the filesystem block. Its offset depends on the filesystem block
> * size, so locate it dynamically with F2FS_INODE_NIDS().
> */
Done, let me know if you have a new version, I can help to cache in my tree
for lkp build test.
Thanks,
>
> Thanks,
> Kelvin
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 07/11] f2fs: describe xattr block layout dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (5 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node " Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-09-01 1:10 ` Daeho Jeong
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 08/11] f2fs: parameterize sector conversion macros Kelvin Zhang
` (3 subsequent siblings)
10 siblings, 1 reply; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
The usable capacity of dedicated on-disk extended attribute blocks and
inline xattr regions scales with the filesystem block size.
Parameterize VALID_XATTR_BLOCK_SIZE and MAX_INLINE_XATTR_SIZE to
calculate usable xattr limits dynamically from sbi->blocksize rather than
hardcoding PAGE_SIZE or DEF_ADDRS_PER_INODE.
Update mount option consistency validation for inline_xattr_size to
evaluate allowed boundaries dynamically against the runtime block size.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/inode.c | 4 ++--
fs/f2fs/node.c | 2 +-
fs/f2fs/super.c | 17 +++++++++++++++--
fs/f2fs/xattr.c | 8 +++++---
fs/f2fs/xattr.h | 15 ++++++++++-----
include/linux/f2fs_fs.h | 2 ++
6 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index fda9ee3bfc61..20b0561fe35d 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -337,12 +337,12 @@ static bool sanity_check_inode(struct inode *inode, struct folio *node_folio)
}
if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
- (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE ||
+ (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE(inode) ||
(f2fs_has_inline_xattr(inode) &&
fi->i_inline_xattr_size < MIN_INLINE_XATTR_SIZE))) {
f2fs_warn(sbi, "%s: inode (ino=%llx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %lu",
__func__, inode->i_ino, fi->i_inline_xattr_size,
- MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE);
+ MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE(inode));
return false;
}
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index e3f594f7bcce..7dabfada1b54 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -2919,7 +2919,7 @@ int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
/* 3: update and set xattr node page dirty */
if (folio) {
memcpy(F2FS_NODE(xfolio), F2FS_NODE(folio),
- VALID_XATTR_BLOCK_SIZE);
+ VALID_XATTR_BLOCK_SIZE(inode));
folio_mark_dirty(xfolio);
}
f2fs_folio_put(xfolio, true);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index fcaeaacaab33..3ba4df757213 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -855,9 +855,11 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
break;
case Opt_inline_xattr_size:
if (result.int_32 < MIN_INLINE_XATTR_SIZE ||
- result.int_32 > MAX_INLINE_XATTR_SIZE) {
+ result.int_32 >
+ MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_MAX_BLKSIZE)) {
f2fs_err(NULL, "inline xattr size is out of range: %u ~ %u",
- (u32)MIN_INLINE_XATTR_SIZE, (u32)MAX_INLINE_XATTR_SIZE);
+ (u32)MIN_INLINE_XATTR_SIZE,
+ (u32)MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_MAX_BLKSIZE));
return -EINVAL;
}
ctx_set_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE);
@@ -1596,6 +1598,8 @@ static int f2fs_check_opt_consistency(struct fs_context *fc,
}
if (ctx_test_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE)) {
+ int min_size, max_size;
+
if (!f2fs_sb_has_extra_attr(sbi) ||
!f2fs_sb_has_flexible_inline_xattr(sbi)) {
f2fs_err(sbi, "extra_attr or flexible_inline_xattr feature is off");
@@ -1605,6 +1609,15 @@ static int f2fs_check_opt_consistency(struct fs_context *fc,
f2fs_err(sbi, "inline_xattr_size option should be set with inline_xattr option");
return -EINVAL;
}
+ min_size = MIN_INLINE_XATTR_SIZE;
+ max_size = MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_BLKSIZE);
+
+ if (F2FS_OPTION(sbi).inline_xattr_size < min_size ||
+ F2FS_OPTION(sbi).inline_xattr_size > max_size) {
+ f2fs_err(sbi, "inline xattr size is out of range: %d ~ %d",
+ min_size, max_size);
+ return -EINVAL;
+ }
}
if (ctx_test_opt(ctx, F2FS_MOUNT_ATGC) &&
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 6728d1488cad..99c863513725 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -310,7 +310,8 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr)
return PTR_ERR(xfolio);
xattr_addr = folio_address(xfolio);
- memcpy(txattr_addr + inline_size, xattr_addr, VALID_XATTR_BLOCK_SIZE);
+ memcpy(txattr_addr + inline_size, xattr_addr,
+ VALID_XATTR_BLOCK_SIZE(inode));
f2fs_folio_put(xfolio, true);
return 0;
@@ -393,7 +394,7 @@ static int read_all_xattrs(struct inode *inode, struct folio *ifolio,
{
struct f2fs_xattr_header *header;
nid_t xnid = F2FS_I(inode)->i_xattr_nid;
- unsigned int size = VALID_XATTR_BLOCK_SIZE;
+ unsigned int size = VALID_XATTR_BLOCK_SIZE(inode);
unsigned int inline_size = inline_xattr_size(inode);
void *txattr_addr;
int err;
@@ -502,7 +503,8 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
if (inline_size)
memcpy(inline_addr, txattr_addr, inline_size);
- memcpy(xattr_addr, txattr_addr + inline_size, VALID_XATTR_BLOCK_SIZE);
+ memcpy(xattr_addr, txattr_addr + inline_size,
+ VALID_XATTR_BLOCK_SIZE(inode));
if (inline_size)
folio_mark_dirty(ifolio ? ifolio : in_folio);
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
index bce3d93e4755..d9e2c65a1fc7 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -71,24 +71,29 @@ struct f2fs_xattr_entry {
for (entry = XATTR_FIRST_ENTRY(addr);\
!IS_XATTR_LAST_ENTRY(entry);\
entry = XATTR_NEXT_ENTRY(entry))
-#define VALID_XATTR_BLOCK_SIZE (PAGE_SIZE - sizeof(struct node_footer))
+#define VALID_XATTR_BLOCK_SIZE(i) (i_blocksize(i) - \
+ sizeof(struct node_footer))
#define XATTR_PADDING_SIZE (sizeof(__u32))
#define XATTR_SIZE(i) ((F2FS_I(i)->i_xattr_nid ? \
- VALID_XATTR_BLOCK_SIZE : 0) + \
+ VALID_XATTR_BLOCK_SIZE(i) : 0) + \
(inline_xattr_size(i)))
#define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + \
- VALID_XATTR_BLOCK_SIZE)
+ VALID_XATTR_BLOCK_SIZE(i))
#define MAX_VALUE_LEN(i) (MIN_OFFSET(i) - \
sizeof(struct f2fs_xattr_header) - \
sizeof(struct f2fs_xattr_entry))
#define MIN_INLINE_XATTR_SIZE (sizeof(struct f2fs_xattr_header) / sizeof(__le32))
-#define MAX_INLINE_XATTR_SIZE \
- (DEF_ADDRS_PER_INODE - \
+#define MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(blocksize) \
+ (((blocksize) - OFFSET_OF_END_OF_I_EXT - \
+ SIZE_OF_I_NID - sizeof(struct node_footer)) / \
+ sizeof(__le32) - \
F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \
DEF_INLINE_RESERVED_SIZE - \
MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
+#define MAX_INLINE_XATTR_SIZE(inode) \
+ MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(i_blocksize(inode))
#define DEFAULT_XATTR_SLAB_SIZE (DEFAULT_INLINE_XATTR_ADDRS * \
sizeof(__le32) + XATTR_PADDING_SIZE)
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 3d0fe2c78e12..d4151970ae86 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -15,6 +15,8 @@
#define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */
#define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
#define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
+#define F2FS_MIN_LOG_BLOCKSIZE 12
+#define F2FS_MIN_BLKSIZE 4096UL
#define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */
#define F2FS_MAX_BLKSIZE PAGE_SIZE
#define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 07/11] f2fs: describe xattr block layout dynamically
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 07/11] f2fs: describe xattr " Kelvin Zhang
@ 2026-09-01 1:10 ` Daeho Jeong
2026-09-01 16:38 ` Xinping Zhang
0 siblings, 1 reply; 30+ messages in thread
From: Daeho Jeong @ 2026-09-01 1:10 UTC (permalink / raw)
To: Kelvin Zhang; +Cc: jaegeuk, linux-kernel, linux-f2fs-devel
On Mon, Aug 31, 2026 at 3:09 PM Kelvin Zhang <zhangxp1998@gmail.com> wrote:
>
> The usable capacity of dedicated on-disk extended attribute blocks and
> inline xattr regions scales with the filesystem block size.
>
> Parameterize VALID_XATTR_BLOCK_SIZE and MAX_INLINE_XATTR_SIZE to
> calculate usable xattr limits dynamically from sbi->blocksize rather than
> hardcoding PAGE_SIZE or DEF_ADDRS_PER_INODE.
>
> Update mount option consistency validation for inline_xattr_size to
> evaluate allowed boundaries dynamically against the runtime block size.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/inode.c | 4 ++--
> fs/f2fs/node.c | 2 +-
> fs/f2fs/super.c | 17 +++++++++++++++--
> fs/f2fs/xattr.c | 8 +++++---
> fs/f2fs/xattr.h | 15 ++++++++++-----
> include/linux/f2fs_fs.h | 2 ++
> 6 files changed, 35 insertions(+), 13 deletions(-)
>
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index fda9ee3bfc61..20b0561fe35d 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -337,12 +337,12 @@ static bool sanity_check_inode(struct inode *inode, struct folio *node_folio)
> }
>
> if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
> - (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE ||
> + (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE(inode) ||
> (f2fs_has_inline_xattr(inode) &&
> fi->i_inline_xattr_size < MIN_INLINE_XATTR_SIZE))) {
> f2fs_warn(sbi, "%s: inode (ino=%llx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %lu",
> __func__, inode->i_ino, fi->i_inline_xattr_size,
> - MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE);
> + MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE(inode));
> return false;
> }
>
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index e3f594f7bcce..7dabfada1b54 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -2919,7 +2919,7 @@ int f2fs_recover_xattr_data(struct inode *inode, struct folio *folio)
> /* 3: update and set xattr node page dirty */
> if (folio) {
> memcpy(F2FS_NODE(xfolio), F2FS_NODE(folio),
> - VALID_XATTR_BLOCK_SIZE);
> + VALID_XATTR_BLOCK_SIZE(inode));
> folio_mark_dirty(xfolio);
> }
> f2fs_folio_put(xfolio, true);
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index fcaeaacaab33..3ba4df757213 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -855,9 +855,11 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
> break;
> case Opt_inline_xattr_size:
> if (result.int_32 < MIN_INLINE_XATTR_SIZE ||
> - result.int_32 > MAX_INLINE_XATTR_SIZE) {
> + result.int_32 >
> + MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_MAX_BLKSIZE)) {
> f2fs_err(NULL, "inline xattr size is out of range: %u ~ %u",
> - (u32)MIN_INLINE_XATTR_SIZE, (u32)MAX_INLINE_XATTR_SIZE);
> + (u32)MIN_INLINE_XATTR_SIZE,
> + (u32)MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_MAX_BLKSIZE));
> return -EINVAL;
> }
> ctx_set_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE);
> @@ -1596,6 +1598,8 @@ static int f2fs_check_opt_consistency(struct fs_context *fc,
> }
>
> if (ctx_test_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE)) {
> + int min_size, max_size;
> +
> if (!f2fs_sb_has_extra_attr(sbi) ||
> !f2fs_sb_has_flexible_inline_xattr(sbi)) {
> f2fs_err(sbi, "extra_attr or flexible_inline_xattr feature is off");
> @@ -1605,6 +1609,15 @@ static int f2fs_check_opt_consistency(struct fs_context *fc,
> f2fs_err(sbi, "inline_xattr_size option should be set with inline_xattr option");
> return -EINVAL;
> }
> + min_size = MIN_INLINE_XATTR_SIZE;
> + max_size = MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_BLKSIZE);
> +
> + if (F2FS_OPTION(sbi).inline_xattr_size < min_size ||
> + F2FS_OPTION(sbi).inline_xattr_size > max_size) {
> + f2fs_err(sbi, "inline xattr size is out of range: %d ~ %d",
> + min_size, max_size);
> + return -EINVAL;
> + }
> }
>
> if (ctx_test_opt(ctx, F2FS_MOUNT_ATGC) &&
> diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
> index 6728d1488cad..99c863513725 100644
> --- a/fs/f2fs/xattr.c
> +++ b/fs/f2fs/xattr.c
> @@ -310,7 +310,8 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr)
> return PTR_ERR(xfolio);
>
> xattr_addr = folio_address(xfolio);
> - memcpy(txattr_addr + inline_size, xattr_addr, VALID_XATTR_BLOCK_SIZE);
> + memcpy(txattr_addr + inline_size, xattr_addr,
> + VALID_XATTR_BLOCK_SIZE(inode));
> f2fs_folio_put(xfolio, true);
>
> return 0;
> @@ -393,7 +394,7 @@ static int read_all_xattrs(struct inode *inode, struct folio *ifolio,
> {
> struct f2fs_xattr_header *header;
> nid_t xnid = F2FS_I(inode)->i_xattr_nid;
> - unsigned int size = VALID_XATTR_BLOCK_SIZE;
> + unsigned int size = VALID_XATTR_BLOCK_SIZE(inode);
> unsigned int inline_size = inline_xattr_size(inode);
> void *txattr_addr;
> int err;
> @@ -502,7 +503,8 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
>
> if (inline_size)
> memcpy(inline_addr, txattr_addr, inline_size);
> - memcpy(xattr_addr, txattr_addr + inline_size, VALID_XATTR_BLOCK_SIZE);
> + memcpy(xattr_addr, txattr_addr + inline_size,
> + VALID_XATTR_BLOCK_SIZE(inode));
>
> if (inline_size)
> folio_mark_dirty(ifolio ? ifolio : in_folio);
> diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
> index bce3d93e4755..d9e2c65a1fc7 100644
> --- a/fs/f2fs/xattr.h
> +++ b/fs/f2fs/xattr.h
> @@ -71,24 +71,29 @@ struct f2fs_xattr_entry {
> for (entry = XATTR_FIRST_ENTRY(addr);\
> !IS_XATTR_LAST_ENTRY(entry);\
> entry = XATTR_NEXT_ENTRY(entry))
> -#define VALID_XATTR_BLOCK_SIZE (PAGE_SIZE - sizeof(struct node_footer))
> +#define VALID_XATTR_BLOCK_SIZE(i) (i_blocksize(i) - \
> + sizeof(struct node_footer))
> #define XATTR_PADDING_SIZE (sizeof(__u32))
> #define XATTR_SIZE(i) ((F2FS_I(i)->i_xattr_nid ? \
> - VALID_XATTR_BLOCK_SIZE : 0) + \
> + VALID_XATTR_BLOCK_SIZE(i) : 0) + \
> (inline_xattr_size(i)))
> #define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + \
> - VALID_XATTR_BLOCK_SIZE)
> + VALID_XATTR_BLOCK_SIZE(i))
>
> #define MAX_VALUE_LEN(i) (MIN_OFFSET(i) - \
> sizeof(struct f2fs_xattr_header) - \
> sizeof(struct f2fs_xattr_entry))
>
> #define MIN_INLINE_XATTR_SIZE (sizeof(struct f2fs_xattr_header) / sizeof(__le32))
> -#define MAX_INLINE_XATTR_SIZE \
> - (DEF_ADDRS_PER_INODE - \
> +#define MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(blocksize) \
> + (((blocksize) - OFFSET_OF_END_OF_I_EXT - \
> + SIZE_OF_I_NID - sizeof(struct node_footer)) / \
> + sizeof(__le32) - \
> F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \
> DEF_INLINE_RESERVED_SIZE - \
> MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
> +#define MAX_INLINE_XATTR_SIZE(inode) \
> + MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(i_blocksize(inode))
Regarding MAX_INLINE_XATTR_SIZE and MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE:
Currently, two separate macros are defined in fs/f2fs/xattr.h:
1. MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(blocksize) - taking a blocksize value
2. MAX_INLINE_XATTR_SIZE(inode) - a wrapper calling the above with
i_blocksize(inode)
This duplication was added because in super.c (during mount option parsing in
f2fs_parse_param), there is no struct inode instance yet, so F2FS_MIN_BLKSIZE
had to be passed explicitly.
Instead of maintaining the verbose `_FOR_BLOCKSIZE` duplicate macro, we can
simply define a single unified macro that takes the blocksize:
#define MAX_INLINE_XATTR_SIZE(bs) \
(F2FS_DEF_ADDRS_PER_INODE(bs) - \
F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \
DEF_INLINE_RESERVED_SIZE - \
MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
Call sites can then pass the blocksize directly:
- In super.c:
MAX_INLINE_XATTR_SIZE(F2FS_MIN_BLKSIZE)
- In inode.c:
MAX_INLINE_XATTR_SIZE(i_blocksize(inode))
(or MAX_INLINE_XATTR_SIZE(F2FS_I_SB(inode)->blocksize))
Thanks,
> #define DEFAULT_XATTR_SLAB_SIZE (DEFAULT_INLINE_XATTR_ADDRS * \
> sizeof(__le32) + XATTR_PADDING_SIZE)
>
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index 3d0fe2c78e12..d4151970ae86 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -15,6 +15,8 @@
> #define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */
> #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
> #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
> +#define F2FS_MIN_LOG_BLOCKSIZE 12
> +#define F2FS_MIN_BLKSIZE 4096UL
> #define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */
> #define F2FS_MAX_BLKSIZE PAGE_SIZE
> #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
> --
> 2.53.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 08/11] f2fs: parameterize sector conversion macros
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (6 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 07/11] f2fs: describe xattr " Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 09/11] f2fs: parameterize byte and block " Kelvin Zhang
` (2 subsequent siblings)
10 siblings, 0 replies; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
Sector-to-block and block-to-sector conversion helpers previously
assumed a fixed sector count per block derived from 4KB pages.
Parameterize F2FS_LOG_SECTORS_PER_BLOCK, SECTOR_FROM_BLOCK, and
SECTOR_TO_BLOCK with struct f2fs_sb_info *sbi, using
sbi->log_sectors_per_block.
Update all call sites across metadata I/O, data mapping, discard
operations, and zoned block device reporting.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/data.c | 2 +-
fs/f2fs/f2fs.h | 5 +++--
fs/f2fs/file.c | 4 ++--
fs/f2fs/inode.c | 11 +++++++----
fs/f2fs/segment.c | 14 +++++++-------
fs/f2fs/segment.h | 8 ++++----
fs/f2fs/super.c | 10 +++++-----
include/linux/f2fs_fs.h | 2 +-
8 files changed, 30 insertions(+), 26 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 751b7a457d9a..44e1ae43565e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -466,7 +466,7 @@ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
}
if (sector)
- *sector = SECTOR_FROM_BLOCK(blk_addr);
+ *sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
return bdev;
}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 247e56522441..b90c5a42703f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2609,7 +2609,8 @@ static inline int F2FS_HAS_BLOCKS(struct inode *inode)
{
block_t xattr_block = F2FS_I(inode)->i_xattr_nid ? 1 : 0;
- return (inode->i_blocks >> F2FS_LOG_SECTORS_PER_BLOCK) > xattr_block;
+ return (inode->i_blocks >>
+ F2FS_LOG_SECTORS_PER_BLOCK(F2FS_I_SB(inode))) > xattr_block;
}
static inline bool f2fs_has_xattr_block(unsigned int ofs)
@@ -2815,7 +2816,7 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
struct inode *inode,
block_t count)
{
- blkcnt_t sectors = count << F2FS_LOG_SECTORS_PER_BLOCK;
+ blkcnt_t sectors = count << F2FS_LOG_SECTORS_PER_BLOCK(sbi);
spin_lock(&sbi->stat_lock);
if (unlikely(sbi->total_valid_block_count < count)) {
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d440231b8cb9..2c72e028cec2 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4510,8 +4510,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode,
pgoff_t off, block_t block, block_t len, u32 flags)
{
- sector_t sector = SECTOR_FROM_BLOCK(block);
- sector_t nr_sects = SECTOR_FROM_BLOCK(len);
+ sector_t sector = SECTOR_FROM_BLOCK(F2FS_I_SB(inode), block);
+ sector_t nr_sects = SECTOR_FROM_BLOCK(F2FS_I_SB(inode), len);
int ret = 0;
if (flags & F2FS_TRIM_FILE_DISCARD) {
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 20b0561fe35d..b628fdc4198f 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -221,11 +221,11 @@ static bool sanity_check_compress_inode(struct inode *inode,
return false;
}
if (le64_to_cpu(ri->i_compr_blocks) >
- SECTOR_TO_BLOCK(inode->i_blocks)) {
+ SECTOR_TO_BLOCK(sbi, inode->i_blocks)) {
f2fs_warn(sbi,
"%s: inode (ino=%llx) has inconsistent i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix",
__func__, inode->i_ino, le64_to_cpu(ri->i_compr_blocks),
- SECTOR_TO_BLOCK(inode->i_blocks));
+ SECTOR_TO_BLOCK(sbi, inode->i_blocks));
return false;
}
if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE ||
@@ -446,7 +446,8 @@ static int do_read_inode(struct inode *inode)
i_gid_write(inode, le32_to_cpu(ri->i_gid));
set_nlink(inode, le32_to_cpu(ri->i_links));
inode->i_size = le64_to_cpu(ri->i_size);
- inode->i_blocks = SECTOR_FROM_BLOCK(le64_to_cpu(ri->i_blocks) - 1);
+ inode->i_blocks = SECTOR_FROM_BLOCK(sbi,
+ le64_to_cpu(ri->i_blocks) - 1);
inode_set_atime(inode, le64_to_cpu(ri->i_atime),
le32_to_cpu(ri->i_atime_nsec));
@@ -695,6 +696,7 @@ struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino)
void f2fs_update_inode(struct inode *inode, struct folio *node_folio)
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_inode *ri;
struct extent_tree *et = fi->extent_tree[EX_READ];
@@ -711,7 +713,8 @@ void f2fs_update_inode(struct inode *inode, struct folio *node_folio)
ri->i_uid = cpu_to_le32(i_uid_read(inode));
ri->i_gid = cpu_to_le32(i_gid_read(inode));
ri->i_links = cpu_to_le32(inode->i_nlink);
- ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(READ_ONCE(inode->i_blocks)) + 1);
+ ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(sbi,
+ READ_ONCE(inode->i_blocks)) + 1);
if (!f2fs_is_atomic_file(inode) ||
is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index b29df65ab5b7..f565b6873832 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1310,7 +1310,7 @@ static void __submit_zone_reset_cmd(struct f2fs_sb_info *sbi,
/* sanity check on discard range */
__check_sit_bitmap(sbi, dc->di.lstart, dc->di.lstart + dc->di.len);
- bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(dc->di.start);
+ bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, dc->di.start);
bio->bi_private = dc;
bio->bi_end_io = f2fs_submit_discard_endio;
submit_bio(bio);
@@ -1327,7 +1327,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
{
struct block_device *bdev = dc->bdev;
unsigned int max_discard_blocks =
- SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev));
+ SECTOR_TO_BLOCK(sbi, bdev_max_discard_sectors(bdev));
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct list_head *wait_list = (dpolicy->type == DPOLICY_FSTRIM) ?
&(dcc->fstrim_list) : &(dcc->wait_list);
@@ -1389,8 +1389,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
dc->di.len += len;
- __blkdev_issue_discard(bdev, SECTOR_FROM_BLOCK(start),
- SECTOR_FROM_BLOCK(len), GFP_NOFS, &bio);
+ __blkdev_issue_discard(bdev, SECTOR_FROM_BLOCK(sbi, start),
+ SECTOR_FROM_BLOCK(sbi, len), GFP_NOFS, &bio);
f2fs_bug_on(sbi, !bio);
/*
@@ -1518,7 +1518,7 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
struct discard_info di = {0};
struct rb_node **insert_p = NULL, *insert_parent = NULL;
unsigned int max_discard_blocks =
- SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev));
+ SECTOR_TO_BLOCK(sbi, bdev_max_discard_sectors(bdev));
block_t end = lstart + len;
dc = __lookup_discard_cmd_ret(&dcc->root, lstart,
@@ -2041,8 +2041,8 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
/* For sequential zones, reset the zone write pointer */
if (f2fs_blkz_is_seq(sbi, devi, blkstart)) {
- sector = SECTOR_FROM_BLOCK(blkstart);
- nr_sects = SECTOR_FROM_BLOCK(blklen);
+ sector = SECTOR_FROM_BLOCK(sbi, blkstart);
+ nr_sects = SECTOR_FROM_BLOCK(sbi, blklen);
div64_u64_rem(sector, bdev_zone_sectors(bdev), &remainder);
if (remainder || nr_sects != bdev_zone_sectors(bdev)) {
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 534e376cbc92..2275404e769c 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -114,10 +114,10 @@ f2fs_start_segno(struct f2fs_sb_info *sbi, unsigned int segno)
#define f2fs_bitmap_size(nr) \
(BITS_TO_LONGS(nr) * sizeof(unsigned long))
-#define SECTOR_FROM_BLOCK(blk_addr) \
- (((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK)
-#define SECTOR_TO_BLOCK(sectors) \
- ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
+#define SECTOR_FROM_BLOCK(sbi, blk_addr) \
+ (((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK(sbi))
+#define SECTOR_TO_BLOCK(sbi, sectors) \
+ ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK(sbi))
/*
* In the victim_sel_policy->alloc_mode, there are three block allocation modes.
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 3ba4df757213..46973207cd7b 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3944,7 +3944,7 @@ static int __f2fs_commit_super(struct f2fs_sb_info *sbi, struct folio *folio,
bio = bio_alloc(sbi->sb->s_bdev, 1, opf, GFP_NOFS);
/* it doesn't need to set crypto context for superblock update */
- bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(folio->index);
+ bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, folio->index);
if (!bio_add_folio(bio, folio, folio_size(folio), 0))
f2fs_bug_on(sbi, 1);
@@ -4520,7 +4520,7 @@ static int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx,
{
struct f2fs_report_zones_args *rz_args = data;
block_t unusable_blocks = (zone->len - zone->capacity) >>
- F2FS_LOG_SECTORS_PER_BLOCK;
+ F2FS_LOG_SECTORS_PER_BLOCK(rz_args->sbi);
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
return 0;
@@ -4563,10 +4563,10 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
zone_sectors = bdev_zone_sectors(bdev);
if (sbi->blocks_per_blkz && sbi->blocks_per_blkz !=
- SECTOR_TO_BLOCK(zone_sectors))
+ SECTOR_TO_BLOCK(sbi, zone_sectors))
return -EINVAL;
- sbi->blocks_per_blkz = SECTOR_TO_BLOCK(zone_sectors);
- FDEV(devi).nr_blkz = div_u64(SECTOR_TO_BLOCK(nr_sectors),
+ sbi->blocks_per_blkz = SECTOR_TO_BLOCK(sbi, zone_sectors);
+ FDEV(devi).nr_blkz = div_u64(SECTOR_TO_BLOCK(sbi, nr_sectors),
sbi->blocks_per_blkz);
if (nr_sectors & (zone_sectors - 1))
FDEV(devi).nr_blkz++;
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index d4151970ae86..f89609356be8 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -14,7 +14,7 @@
#define F2FS_SUPER_OFFSET 1024 /* byte-size offset */
#define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */
#define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
-#define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */
+#define F2FS_LOG_SECTORS_PER_BLOCK(sbi) ((sbi)->log_blocksize - 9) /* log number for sector/blk */
#define F2FS_MIN_LOG_BLOCKSIZE 12
#define F2FS_MIN_BLKSIZE 4096UL
#define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* [f2fs-dev] [PATCH v7 09/11] f2fs: parameterize byte and block conversion macros
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (7 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 08/11] f2fs: parameterize sector conversion macros Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-09-01 1:14 ` Daeho Jeong
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 10/11] f2fs: parameterize block size and mask macros Kelvin Zhang
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 11/11] f2fs: describe node tree geometry dynamically Kelvin Zhang
10 siblings, 1 reply; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
Byte-to-block and block-to-byte conversion helpers previously relied on
global PAGE_SIZE, PAGE_SHIFT, or F2FS_BLKSIZE_BITS.
Parameterize F2FS_BYTES_TO_BLK, F2FS_BLK_TO_BYTES, F2FS_BLK_END_BYTES,
F2FS_BLK_ALIGN, and max_file_blocks with struct f2fs_sb_info *sbi using
sbi->log_blocksize.
Update all call sites across data mapping, file operations, fiemap queries,
fsverity checks, NAT bitmap allocations, and truncate paths.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/checkpoint.c | 2 +-
fs/f2fs/data.c | 58 +++++++++++++++++++++++------------------
fs/f2fs/debug.c | 2 +-
fs/f2fs/f2fs.h | 7 ++---
fs/f2fs/file.c | 54 +++++++++++++++++++++-----------------
fs/f2fs/node.c | 7 ++---
fs/f2fs/recovery.c | 4 +--
fs/f2fs/segment.c | 9 ++++---
fs/f2fs/super.c | 9 ++++---
fs/f2fs/verity.c | 6 +++--
include/linux/f2fs_fs.h | 12 ++++++---
11 files changed, 96 insertions(+), 74 deletions(-)
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 37a72b693545..d0dcc918422e 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -1866,7 +1866,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
blk = start_blk + BLKS_PER_SEG(sbi) - nm_i->nat_bits_blocks;
for (i = 0; i < nm_i->nat_bits_blocks; i++)
f2fs_update_meta_page(sbi, nm_i->nat_bits +
- F2FS_BLK_TO_BYTES(i), blk + i);
+ F2FS_BLK_TO_BYTES(sbi, i), blk + i);
}
/* write out checkpoint buffer at block 0 */
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 44e1ae43565e..6ee4440c17dd 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1977,12 +1977,12 @@ static bool __f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len,
if (pos + len > i_size_read(inode))
return false;
- map.m_lblk = F2FS_BYTES_TO_BLK(pos);
+ map.m_lblk = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), pos);
map.m_next_pgofs = NULL;
map.m_next_extent = NULL;
map.m_seg_type = NO_CHECK_TYPE;
map.m_may_create = false;
- last_lblk = F2FS_BLK_ALIGN(pos + len);
+ last_lblk = F2FS_BLK_ALIGN(F2FS_I_SB(inode), pos + len);
while (map.m_lblk < last_lblk) {
map.m_len = last_lblk - map.m_lblk;
@@ -2025,7 +2025,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
return err;
}
- phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
+ phys = F2FS_BLK_TO_BYTES(sbi, ni.blk_addr);
offset = offsetof(struct f2fs_inode, i_addr) +
sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) -
get_inline_xattr_addrs(inode));
@@ -2059,7 +2059,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
return err;
}
- phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
+ phys = F2FS_BLK_TO_BYTES(sbi, ni.blk_addr);
len = inode->i_sb->s_blocksize;
f2fs_folio_put(folio, true);
@@ -2078,6 +2078,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_map_blocks map;
sector_t start_blk, last_blk, blk_len, max_len;
pgoff_t next_pgofs;
@@ -2101,7 +2102,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
inode_lock_shared(inode);
- maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
+ maxbytes = F2FS_BLK_TO_BYTES(sbi, max_file_blocks(sbi, inode));
if (start > maxbytes) {
ret = -EFBIG;
goto out;
@@ -2121,10 +2122,10 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
goto out;
}
- start_blk = F2FS_BYTES_TO_BLK(start);
- last_blk = F2FS_BYTES_TO_BLK(start + len - 1);
+ start_blk = F2FS_BYTES_TO_BLK(sbi, start);
+ last_blk = F2FS_BYTES_TO_BLK(sbi, start + len - 1);
blk_len = last_blk - start_blk + 1;
- max_len = F2FS_BYTES_TO_BLK(maxbytes) - start_blk;
+ max_len = F2FS_BYTES_TO_BLK(sbi, maxbytes) - start_blk;
next:
memset(&map, 0, sizeof(map));
@@ -2146,7 +2147,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) {
start_blk = next_pgofs;
- if (F2FS_BLK_TO_BYTES(start_blk) < maxbytes)
+ if (F2FS_BLK_TO_BYTES(sbi, start_blk) < maxbytes)
goto prep_next;
flags |= FIEMAP_EXTENT_LAST;
@@ -2194,14 +2195,14 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
} else if (compr_appended) {
unsigned int appended_blks = cluster_size -
count_in_cluster + 1;
- size += F2FS_BLK_TO_BYTES(appended_blks);
+ size += F2FS_BLK_TO_BYTES(sbi, appended_blks);
start_blk += appended_blks;
compr_cluster = false;
} else {
- logical = F2FS_BLK_TO_BYTES(start_blk);
+ logical = F2FS_BLK_TO_BYTES(sbi, start_blk);
phys = __is_valid_data_blkaddr(map.m_pblk) ?
- F2FS_BLK_TO_BYTES(map.m_pblk) : 0;
- size = F2FS_BLK_TO_BYTES(map.m_len);
+ F2FS_BLK_TO_BYTES(sbi, map.m_pblk) : 0;
+ size = F2FS_BLK_TO_BYTES(sbi, map.m_len);
flags = 0;
if (compr_cluster) {
@@ -2215,7 +2216,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
flags = FIEMAP_EXTENT_UNWRITTEN;
}
- start_blk += F2FS_BYTES_TO_BLK(size);
+ start_blk += F2FS_BYTES_TO_BLK(sbi, size);
}
prep_next:
@@ -2235,7 +2236,8 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
static inline loff_t f2fs_readpage_limit(struct inode *inode)
{
if (IS_ENABLED(CONFIG_FS_VERITY) && IS_VERITY(inode))
- return F2FS_BLK_TO_BYTES(max_file_blocks(inode));
+ return F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
+ max_file_blocks(F2FS_I_SB(inode), inode));
return i_size_read(inode);
}
@@ -2263,7 +2265,8 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
block_in_file = (sector_t)index;
last_block = block_in_file + nr_pages;
- last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) +
+ last_block_in_file = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode),
+ f2fs_readpage_limit(inode) +
blocksize - 1);
if (last_block > last_block_in_file)
last_block = last_block_in_file;
@@ -2374,7 +2377,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc));
- last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) +
+ last_block_in_file = F2FS_BYTES_TO_BLK(sbi,
+ f2fs_readpage_limit(inode) +
blocksize - 1);
/* get rid of pages beyond EOF */
@@ -4236,7 +4240,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
filemap_write_and_wait(mapping);
/* Block number less than F2FS MAX BLOCKS */
- if (unlikely(block >= max_file_blocks(inode)))
+ if (unlikely(block >= max_file_blocks(F2FS_I_SB(inode), inode)))
goto out;
if (f2fs_compressed_file(inode)) {
@@ -4352,7 +4356,7 @@ static int check_swap_activate(struct swap_info_struct *sis,
* to be very smart.
*/
cur_lblock = 0;
- last_lblock = F2FS_BYTES_TO_BLK(i_size_read(inode));
+ last_lblock = F2FS_BYTES_TO_BLK(sbi, i_size_read(inode));
while (cur_lblock < last_lblock && cur_lblock < sis->max) {
struct f2fs_map_blocks map;
@@ -4607,12 +4611,14 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
unsigned int flags, struct iomap *iomap,
struct iomap *srcmap)
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_map_blocks map = { NULL, };
pgoff_t next_pgofs = 0;
int err;
- map.m_lblk = F2FS_BYTES_TO_BLK(offset);
- map.m_len = F2FS_BYTES_TO_BLK(offset + length - 1) - map.m_lblk + 1;
+ map.m_lblk = F2FS_BYTES_TO_BLK(sbi, offset);
+ map.m_len = F2FS_BYTES_TO_BLK(sbi, offset + length - 1) -
+ map.m_lblk + 1;
map.m_next_pgofs = &next_pgofs;
map.m_seg_type = f2fs_rw_hint_to_seg_type(F2FS_I_SB(inode),
inode->i_write_hint);
@@ -4633,7 +4639,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
if (err)
return err;
- iomap->offset = F2FS_BLK_TO_BYTES(map.m_lblk);
+ iomap->offset = F2FS_BLK_TO_BYTES(sbi, map.m_lblk);
/*
* When inline encryption is enabled, sometimes I/O to an encrypted file
@@ -4653,11 +4659,11 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR))
return -EINVAL;
- iomap->length = F2FS_BLK_TO_BYTES(map.m_len);
+ iomap->length = F2FS_BLK_TO_BYTES(sbi, map.m_len);
iomap->type = IOMAP_MAPPED;
iomap->flags |= IOMAP_F_MERGED;
iomap->bdev = map.m_bdev;
- iomap->addr = F2FS_BLK_TO_BYTES(map.m_pblk);
+ iomap->addr = F2FS_BLK_TO_BYTES(sbi, map.m_pblk);
if (flags & IOMAP_WRITE && map.m_last_pblk)
iomap->private = (void *)map.m_last_pblk;
@@ -4666,11 +4672,11 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
return -ENOTBLK;
if (map.m_pblk == NULL_ADDR) {
- iomap->length = F2FS_BLK_TO_BYTES(next_pgofs) -
+ iomap->length = F2FS_BLK_TO_BYTES(sbi, next_pgofs) -
iomap->offset;
iomap->type = IOMAP_HOLE;
} else if (map.m_pblk == NEW_ADDR) {
- iomap->length = F2FS_BLK_TO_BYTES(map.m_len);
+ iomap->length = F2FS_BLK_TO_BYTES(sbi, map.m_len);
iomap->type = IOMAP_UNWRITTEN;
} else {
f2fs_bug_on(F2FS_I_SB(inode), 1);
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 5980b9d79afb..a6cfceafe2fe 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -343,7 +343,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
/* build nm */
si->base_mem += sizeof(struct f2fs_nm_info);
si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
- si->base_mem += F2FS_BLK_TO_BYTES(NM_I(sbi)->nat_bits_blocks);
+ si->base_mem += F2FS_BLK_TO_BYTES(sbi, NM_I(sbi)->nat_bits_blocks);
si->base_mem += NM_I(sbi)->nat_blocks *
f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi));
si->base_mem += NM_I(sbi)->nat_blocks / 8;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index b90c5a42703f..c625a2572841 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -4016,7 +4016,7 @@ void f2fs_inode_synced(struct inode *inode);
int f2fs_dquot_initialize(struct inode *inode);
int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly);
int f2fs_do_quota_sync(struct super_block *sb, int type);
-loff_t max_file_blocks(struct inode *inode);
+loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode);
void f2fs_quota_off_umount(struct super_block *sb);
void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag);
void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
@@ -5263,8 +5263,9 @@ static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi,
NULL, 0, DATA);
truncate_inode_pages_range(META_MAPPING(sbi),
- F2FS_BLK_TO_BYTES((loff_t)blkaddr),
- F2FS_BLK_END_BYTES((loff_t)(blkaddr + cnt - 1)));
+ F2FS_BLK_TO_BYTES(sbi, (loff_t)blkaddr),
+ F2FS_BLK_END_BYTES(sbi,
+ (loff_t)(blkaddr + cnt - 1)));
}
static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi,
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 2c72e028cec2..6fafb32bc5f2 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -513,7 +513,8 @@ static bool __found_offset(struct address_space *mapping,
static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
{
struct inode *inode = file->f_mapping->host;
- loff_t maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
+ loff_t maxbytes = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
+ max_file_blocks(F2FS_I_SB(inode), inode));
struct dnode_of_data dn;
pgoff_t pgofs, end_offset;
loff_t data_ofs = offset;
@@ -537,9 +538,10 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
}
}
- pgofs = (pgoff_t)(offset >> PAGE_SHIFT);
+ pgofs = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), offset);
- for (; data_ofs < isize; data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
+ for (; data_ofs < isize;
+ data_ofs = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), pgofs)) {
set_new_dnode(&dn, inode, NULL, NULL, 0);
err = f2fs_get_dnode_of_data(&dn, pgofs, LOOKUP_NODE);
if (err && err != -ENOENT) {
@@ -559,7 +561,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
/* find data/hole in dnode block */
for (; dn.ofs_in_node < end_offset;
dn.ofs_in_node++, pgofs++,
- data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
+ data_ofs = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), pgofs)) {
block_t blkaddr;
blkaddr = f2fs_data_blkaddr(&dn);
@@ -595,7 +597,8 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence)
{
struct inode *inode = file->f_mapping->host;
- loff_t maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
+ loff_t maxbytes = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
+ max_file_blocks(F2FS_I_SB(inode), inode));
switch (whence) {
case SEEK_SET:
@@ -846,9 +849,9 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock)
goto out_err;
}
- free_from = (pgoff_t)F2FS_BLK_ALIGN(from);
+ free_from = (pgoff_t)F2FS_BLK_ALIGN(sbi, from);
- if (free_from >= max_file_blocks(inode))
+ if (free_from >= max_file_blocks(sbi, inode))
goto free_partial;
if (lock)
@@ -959,9 +962,10 @@ int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock)
int f2fs_truncate(struct inode *inode)
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int err;
- if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
+ if (unlikely(f2fs_cp_error(sbi)))
return -EIO;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
@@ -970,7 +974,7 @@ int f2fs_truncate(struct inode *inode)
trace_f2fs_truncate(inode);
- if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE))
+ if (time_to_inject(sbi, FAULT_TRUNCATE))
return -EIO;
err = f2fs_dquot_initialize(inode);
@@ -986,8 +990,8 @@ int f2fs_truncate(struct inode *inode)
* leak in evict() path.
*/
truncate_inode_pages_range(inode->i_mapping,
- F2FS_BLK_TO_BYTES(0),
- F2FS_BLK_END_BYTES(0));
+ F2FS_BLK_TO_BYTES(sbi, 0),
+ F2FS_BLK_END_BYTES(sbi, 0));
return err;
}
}
@@ -1161,7 +1165,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
return -EOPNOTSUPP;
if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) &&
!IS_ALIGNED(attr->ia_size,
- F2FS_BLK_TO_BYTES(fi->i_cluster_size)))
+ F2FS_BLK_TO_BYTES(sbi, fi->i_cluster_size)))
return -EINVAL;
if (f2fs_is_pinned_file(inode)) {
@@ -1177,7 +1181,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
* pinned file.
*/
else if (!IS_ALIGNED(attr->ia_size,
- F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi))))
+ F2FS_BLK_TO_BYTES(sbi, CAP_BLKS_PER_SEC(sbi))))
return -EINVAL;
}
}
@@ -2648,7 +2652,8 @@ static int f2fs_keep_noreuse_range(struct inode *inode,
loff_t offset, loff_t len)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
- u64 max_bytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
+ u64 max_bytes = F2FS_BLK_TO_BYTES(sbi,
+ max_file_blocks(sbi, inode));
u64 start, end;
int ret = 0;
@@ -3191,8 +3196,8 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
if (range.start & (F2FS_BLKSIZE - 1) || range.len & (F2FS_BLKSIZE - 1))
return -EINVAL;
- if (unlikely((range.start + range.len) >> PAGE_SHIFT >
- max_file_blocks(inode)))
+ if (unlikely(F2FS_BYTES_TO_BLK(sbi, range.start + range.len) >
+ max_file_blocks(sbi, inode)))
return -EINVAL;
err = mnt_want_write_file(filp);
@@ -3326,9 +3331,9 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
}
f2fs_lock_op(sbi, &lc);
- ret = __exchange_data_block(src, dst, F2FS_BYTES_TO_BLK(pos_in),
- F2FS_BYTES_TO_BLK(pos_out),
- F2FS_BYTES_TO_BLK(len), false);
+ ret = __exchange_data_block(src, dst, F2FS_BYTES_TO_BLK(sbi, pos_in),
+ F2FS_BYTES_TO_BLK(sbi, pos_out),
+ F2FS_BYTES_TO_BLK(sbi, len), false);
if (!ret) {
if (dst_max_i_size)
@@ -3994,7 +3999,7 @@ int f2fs_precache_extents(struct inode *inode)
map.m_next_extent = &m_next_extent;
map.m_seg_type = NO_CHECK_TYPE;
map.m_may_create = false;
- end = F2FS_BLK_ALIGN(i_size_read(inode));
+ end = F2FS_BLK_ALIGN(F2FS_I_SB(inode), i_size_read(inode));
while (map.m_lblk < end) {
map.m_len = end - map.m_lblk;
@@ -4594,7 +4599,7 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
goto err;
}
- index = F2FS_BYTES_TO_BLK(range.start);
+ index = F2FS_BYTES_TO_BLK(sbi, range.start);
pg_end = DIV_ROUND_UP(end_addr, F2FS_BLKSIZE);
ret = f2fs_convert_inline_inode(inode);
@@ -5385,7 +5390,8 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter,
* buffered IO, if DIO meets any holes.
*/
if (dio && i_size_read(inode) &&
- (F2FS_BYTES_TO_BLK(pos) < F2FS_BLK_ALIGN(i_size_read(inode))))
+ (F2FS_BYTES_TO_BLK(sbi, pos) <
+ F2FS_BLK_ALIGN(sbi, i_size_read(inode))))
return 0;
/* No-wait I/O can't allocate blocks. */
@@ -5406,8 +5412,8 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter,
}
/* Do not preallocate blocks that will be written partially in 4KB. */
- map.m_lblk = F2FS_BLK_ALIGN(pos);
- map.m_len = F2FS_BYTES_TO_BLK(pos + count);
+ map.m_lblk = F2FS_BLK_ALIGN(sbi, pos);
+ map.m_len = F2FS_BYTES_TO_BLK(sbi, pos + count);
if (map.m_len > map.m_lblk)
map.m_len -= map.m_lblk;
else
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 7dabfada1b54..e7aa3b790214 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -3294,9 +3294,10 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
if (!enabled_nat_bits(sbi, NULL))
return 0;
- nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
+ nm_i->nat_bits_blocks = F2FS_BLK_ALIGN(sbi,
+ (nat_bits_bytes << 1) + 8);
nm_i->nat_bits = f2fs_kvzalloc(sbi,
- F2FS_BLK_TO_BYTES(nm_i->nat_bits_blocks), GFP_KERNEL);
+ F2FS_BLK_TO_BYTES(sbi, nm_i->nat_bits_blocks), GFP_KERNEL);
if (!nm_i->nat_bits)
return -ENOMEM;
@@ -3309,7 +3310,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
if (IS_ERR(folio))
return PTR_ERR(folio);
- memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(i),
+ memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(sbi, i),
folio_address(folio), F2FS_BLKSIZE);
f2fs_folio_put(folio, true);
}
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index aaa5227739c8..b52718741ddc 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -734,9 +734,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
}
if (!file_keep_isize(inode) &&
- (i_size_read(inode) <= ((loff_t)index << PAGE_SHIFT)))
+ (i_size_read(inode) <= F2FS_BLK_TO_BYTES(sbi, index)))
f2fs_i_size_write(inode,
- (loff_t)(index + 1) << PAGE_SHIFT);
+ F2FS_BLK_TO_BYTES(sbi, index + 1));
/*
* dest is reserved block, invalidate src block
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index f565b6873832..f58b26c84b3a 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -3592,8 +3592,8 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
{
- __u64 start = F2FS_BYTES_TO_BLK(range->start);
- __u64 end = start + F2FS_BYTES_TO_BLK(range->len) - 1;
+ __u64 start = F2FS_BYTES_TO_BLK(sbi, range->start);
+ __u64 end = start + F2FS_BYTES_TO_BLK(sbi, range->len) - 1;
unsigned int start_segno, end_segno;
block_t start_block, end_block;
struct cp_control cpc;
@@ -3624,7 +3624,8 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
}
cpc.reason = CP_DISCARD;
- cpc.trim_minlen = max_t(__u64, 1, F2FS_BYTES_TO_BLK(range->minlen));
+ cpc.trim_minlen = max_t(__u64, 1,
+ F2FS_BYTES_TO_BLK(sbi, range->minlen));
cpc.trim_start = start_segno;
cpc.trim_end = end_segno;
@@ -3658,7 +3659,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
start_block, end_block);
out:
if (!err)
- range->len = F2FS_BLK_TO_BYTES(trimmed);
+ range->len = F2FS_BLK_TO_BYTES(sbi, trimmed);
return err;
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 46973207cd7b..b962c14cbcc1 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3884,7 +3884,7 @@ static const struct export_operations f2fs_export_ops = {
.get_parent = f2fs_get_parent,
};
-loff_t max_file_blocks(struct inode *inode)
+loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode)
{
loff_t result = 0;
loff_t leaf_count;
@@ -3918,7 +3918,8 @@ loff_t max_file_blocks(struct inode *inode)
* fit within U32_MAX + 1 data units.
*/
- result = umin(result, F2FS_BYTES_TO_BLK(((loff_t)U32_MAX + 1) * 4096));
+ result = umin(result, F2FS_BYTES_TO_BLK(sbi,
+ ((loff_t)U32_MAX + 1) * 4096));
return result;
}
@@ -4370,7 +4371,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
nat_blocks = nat_segs << log_blocks_per_seg;
nat_bits_bytes = nat_blocks / BITS_PER_BYTE;
- nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
+ nat_bits_blocks = F2FS_BLK_ALIGN(sbi, (nat_bits_bytes << 1) + 8);
if (__is_set_ckpt_flags(ckpt, CP_NAT_BITS_FLAG) &&
(cp_payload + F2FS_CP_PACKS +
NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) {
@@ -5193,7 +5194,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
if (err)
goto free_options;
- sb->s_maxbytes = max_file_blocks(NULL) <<
+ sb->s_maxbytes = max_file_blocks(sbi, NULL) <<
le32_to_cpu(raw_super->log_blocksize);
sb->s_max_links = F2FS_LINK_MAX;
diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c
index 39f482515445..ee838f880c4a 100644
--- a/fs/f2fs/verity.c
+++ b/fs/f2fs/verity.c
@@ -75,7 +75,8 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
struct address_space *mapping = inode->i_mapping;
const struct address_space_operations *aops = mapping->a_ops;
- if (pos + count > F2FS_BLK_TO_BYTES(max_file_blocks(inode)))
+ if (pos + count > F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
+ max_file_blocks(F2FS_I_SB(inode), inode)))
return -EFBIG;
while (count) {
@@ -239,7 +240,8 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
/* Get the descriptor */
if (pos + size < pos ||
- pos + size > F2FS_BLK_TO_BYTES(max_file_blocks(inode)) ||
+ pos + size > F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
+ max_file_blocks(F2FS_I_SB(inode), inode)) ||
pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) {
f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr");
f2fs_handle_error(F2FS_I_SB(inode),
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index f89609356be8..f622d26f37a7 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -28,10 +28,14 @@
#define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */
#define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1)
-#define F2FS_BYTES_TO_BLK(bytes) ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS)
-#define F2FS_BLK_TO_BYTES(blk) ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS)
-#define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1)
-#define F2FS_BLK_ALIGN(x) (F2FS_BYTES_TO_BLK((x) + F2FS_BLKSIZE - 1))
+#define F2FS_BYTES_TO_BLK(sbi, bytes) \
+ ((unsigned long long)(bytes) >> (sbi)->log_blocksize)
+#define F2FS_BLK_TO_BYTES(sbi, blk) \
+ ((unsigned long long)(blk) << (sbi)->log_blocksize)
+#define F2FS_BLK_END_BYTES(sbi, blk) \
+ (F2FS_BLK_TO_BYTES(sbi, (blk) + 1) - 1)
+#define F2FS_BLK_ALIGN(sbi, x) \
+ DIV_ROUND_UP_ULL((x), (sbi)->blocksize)
/* 0, 1(node nid), 2(meta nid) are reserved node id */
#define F2FS_RESERVED_NODE_NUM 3
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 09/11] f2fs: parameterize byte and block conversion macros
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 09/11] f2fs: parameterize byte and block " Kelvin Zhang
@ 2026-09-01 1:14 ` Daeho Jeong
2026-09-01 16:38 ` Xinping Zhang
0 siblings, 1 reply; 30+ messages in thread
From: Daeho Jeong @ 2026-09-01 1:14 UTC (permalink / raw)
To: Kelvin Zhang; +Cc: jaegeuk, linux-kernel, linux-f2fs-devel
On Mon, Aug 31, 2026 at 3:09 PM Kelvin Zhang <zhangxp1998@gmail.com> wrote:
>
> Byte-to-block and block-to-byte conversion helpers previously relied on
> global PAGE_SIZE, PAGE_SHIFT, or F2FS_BLKSIZE_BITS.
>
> Parameterize F2FS_BYTES_TO_BLK, F2FS_BLK_TO_BYTES, F2FS_BLK_END_BYTES,
> F2FS_BLK_ALIGN, and max_file_blocks with struct f2fs_sb_info *sbi using
> sbi->log_blocksize.
>
> Update all call sites across data mapping, file operations, fiemap queries,
> fsverity checks, NAT bitmap allocations, and truncate paths.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/checkpoint.c | 2 +-
> fs/f2fs/data.c | 58 +++++++++++++++++++++++------------------
> fs/f2fs/debug.c | 2 +-
> fs/f2fs/f2fs.h | 7 ++---
> fs/f2fs/file.c | 54 +++++++++++++++++++++-----------------
> fs/f2fs/node.c | 7 ++---
> fs/f2fs/recovery.c | 4 +--
> fs/f2fs/segment.c | 9 ++++---
> fs/f2fs/super.c | 9 ++++---
> fs/f2fs/verity.c | 6 +++--
> include/linux/f2fs_fs.h | 12 ++++++---
> 11 files changed, 96 insertions(+), 74 deletions(-)
>
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 37a72b693545..d0dcc918422e 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -1866,7 +1866,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> blk = start_blk + BLKS_PER_SEG(sbi) - nm_i->nat_bits_blocks;
> for (i = 0; i < nm_i->nat_bits_blocks; i++)
> f2fs_update_meta_page(sbi, nm_i->nat_bits +
> - F2FS_BLK_TO_BYTES(i), blk + i);
> + F2FS_BLK_TO_BYTES(sbi, i), blk + i);
> }
>
> /* write out checkpoint buffer at block 0 */
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 44e1ae43565e..6ee4440c17dd 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1977,12 +1977,12 @@ static bool __f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len,
> if (pos + len > i_size_read(inode))
> return false;
>
> - map.m_lblk = F2FS_BYTES_TO_BLK(pos);
> + map.m_lblk = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), pos);
> map.m_next_pgofs = NULL;
> map.m_next_extent = NULL;
> map.m_seg_type = NO_CHECK_TYPE;
> map.m_may_create = false;
> - last_lblk = F2FS_BLK_ALIGN(pos + len);
> + last_lblk = F2FS_BLK_ALIGN(F2FS_I_SB(inode), pos + len);
>
> while (map.m_lblk < last_lblk) {
> map.m_len = last_lblk - map.m_lblk;
> @@ -2025,7 +2025,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
> return err;
> }
>
> - phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
> + phys = F2FS_BLK_TO_BYTES(sbi, ni.blk_addr);
> offset = offsetof(struct f2fs_inode, i_addr) +
> sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) -
> get_inline_xattr_addrs(inode));
> @@ -2059,7 +2059,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
> return err;
> }
>
> - phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
> + phys = F2FS_BLK_TO_BYTES(sbi, ni.blk_addr);
> len = inode->i_sb->s_blocksize;
>
> f2fs_folio_put(folio, true);
> @@ -2078,6 +2078,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
> int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> u64 start, u64 len)
> {
> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> struct f2fs_map_blocks map;
> sector_t start_blk, last_blk, blk_len, max_len;
> pgoff_t next_pgofs;
> @@ -2101,7 +2102,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
>
> inode_lock_shared(inode);
>
> - maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
> + maxbytes = F2FS_BLK_TO_BYTES(sbi, max_file_blocks(sbi, inode));
> if (start > maxbytes) {
> ret = -EFBIG;
> goto out;
> @@ -2121,10 +2122,10 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> goto out;
> }
>
> - start_blk = F2FS_BYTES_TO_BLK(start);
> - last_blk = F2FS_BYTES_TO_BLK(start + len - 1);
> + start_blk = F2FS_BYTES_TO_BLK(sbi, start);
> + last_blk = F2FS_BYTES_TO_BLK(sbi, start + len - 1);
> blk_len = last_blk - start_blk + 1;
> - max_len = F2FS_BYTES_TO_BLK(maxbytes) - start_blk;
> + max_len = F2FS_BYTES_TO_BLK(sbi, maxbytes) - start_blk;
>
> next:
> memset(&map, 0, sizeof(map));
> @@ -2146,7 +2147,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) {
> start_blk = next_pgofs;
>
> - if (F2FS_BLK_TO_BYTES(start_blk) < maxbytes)
> + if (F2FS_BLK_TO_BYTES(sbi, start_blk) < maxbytes)
> goto prep_next;
>
> flags |= FIEMAP_EXTENT_LAST;
> @@ -2194,14 +2195,14 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> } else if (compr_appended) {
> unsigned int appended_blks = cluster_size -
> count_in_cluster + 1;
> - size += F2FS_BLK_TO_BYTES(appended_blks);
> + size += F2FS_BLK_TO_BYTES(sbi, appended_blks);
> start_blk += appended_blks;
> compr_cluster = false;
> } else {
> - logical = F2FS_BLK_TO_BYTES(start_blk);
> + logical = F2FS_BLK_TO_BYTES(sbi, start_blk);
> phys = __is_valid_data_blkaddr(map.m_pblk) ?
> - F2FS_BLK_TO_BYTES(map.m_pblk) : 0;
> - size = F2FS_BLK_TO_BYTES(map.m_len);
> + F2FS_BLK_TO_BYTES(sbi, map.m_pblk) : 0;
> + size = F2FS_BLK_TO_BYTES(sbi, map.m_len);
> flags = 0;
>
> if (compr_cluster) {
> @@ -2215,7 +2216,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> flags = FIEMAP_EXTENT_UNWRITTEN;
> }
>
> - start_blk += F2FS_BYTES_TO_BLK(size);
> + start_blk += F2FS_BYTES_TO_BLK(sbi, size);
> }
>
> prep_next:
> @@ -2235,7 +2236,8 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> static inline loff_t f2fs_readpage_limit(struct inode *inode)
> {
> if (IS_ENABLED(CONFIG_FS_VERITY) && IS_VERITY(inode))
> - return F2FS_BLK_TO_BYTES(max_file_blocks(inode));
> + return F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
> + max_file_blocks(F2FS_I_SB(inode), inode));
>
> return i_size_read(inode);
> }
> @@ -2263,7 +2265,8 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
>
> block_in_file = (sector_t)index;
> last_block = block_in_file + nr_pages;
> - last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) +
> + last_block_in_file = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode),
> + f2fs_readpage_limit(inode) +
> blocksize - 1);
> if (last_block > last_block_in_file)
> last_block = last_block_in_file;
> @@ -2374,7 +2377,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
>
> f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc));
>
> - last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) +
> + last_block_in_file = F2FS_BYTES_TO_BLK(sbi,
> + f2fs_readpage_limit(inode) +
> blocksize - 1);
>
> /* get rid of pages beyond EOF */
> @@ -4236,7 +4240,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
> filemap_write_and_wait(mapping);
>
> /* Block number less than F2FS MAX BLOCKS */
> - if (unlikely(block >= max_file_blocks(inode)))
> + if (unlikely(block >= max_file_blocks(F2FS_I_SB(inode), inode)))
> goto out;
>
> if (f2fs_compressed_file(inode)) {
> @@ -4352,7 +4356,7 @@ static int check_swap_activate(struct swap_info_struct *sis,
> * to be very smart.
> */
> cur_lblock = 0;
> - last_lblock = F2FS_BYTES_TO_BLK(i_size_read(inode));
> + last_lblock = F2FS_BYTES_TO_BLK(sbi, i_size_read(inode));
>
> while (cur_lblock < last_lblock && cur_lblock < sis->max) {
> struct f2fs_map_blocks map;
> @@ -4607,12 +4611,14 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
> unsigned int flags, struct iomap *iomap,
> struct iomap *srcmap)
> {
> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> struct f2fs_map_blocks map = { NULL, };
> pgoff_t next_pgofs = 0;
> int err;
>
> - map.m_lblk = F2FS_BYTES_TO_BLK(offset);
> - map.m_len = F2FS_BYTES_TO_BLK(offset + length - 1) - map.m_lblk + 1;
> + map.m_lblk = F2FS_BYTES_TO_BLK(sbi, offset);
> + map.m_len = F2FS_BYTES_TO_BLK(sbi, offset + length - 1) -
> + map.m_lblk + 1;
> map.m_next_pgofs = &next_pgofs;
> map.m_seg_type = f2fs_rw_hint_to_seg_type(F2FS_I_SB(inode),
> inode->i_write_hint);
> @@ -4633,7 +4639,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
> if (err)
> return err;
>
> - iomap->offset = F2FS_BLK_TO_BYTES(map.m_lblk);
> + iomap->offset = F2FS_BLK_TO_BYTES(sbi, map.m_lblk);
>
> /*
> * When inline encryption is enabled, sometimes I/O to an encrypted file
> @@ -4653,11 +4659,11 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
> if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR))
> return -EINVAL;
>
> - iomap->length = F2FS_BLK_TO_BYTES(map.m_len);
> + iomap->length = F2FS_BLK_TO_BYTES(sbi, map.m_len);
> iomap->type = IOMAP_MAPPED;
> iomap->flags |= IOMAP_F_MERGED;
> iomap->bdev = map.m_bdev;
> - iomap->addr = F2FS_BLK_TO_BYTES(map.m_pblk);
> + iomap->addr = F2FS_BLK_TO_BYTES(sbi, map.m_pblk);
>
> if (flags & IOMAP_WRITE && map.m_last_pblk)
> iomap->private = (void *)map.m_last_pblk;
> @@ -4666,11 +4672,11 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
> return -ENOTBLK;
>
> if (map.m_pblk == NULL_ADDR) {
> - iomap->length = F2FS_BLK_TO_BYTES(next_pgofs) -
> + iomap->length = F2FS_BLK_TO_BYTES(sbi, next_pgofs) -
> iomap->offset;
> iomap->type = IOMAP_HOLE;
> } else if (map.m_pblk == NEW_ADDR) {
> - iomap->length = F2FS_BLK_TO_BYTES(map.m_len);
> + iomap->length = F2FS_BLK_TO_BYTES(sbi, map.m_len);
> iomap->type = IOMAP_UNWRITTEN;
> } else {
> f2fs_bug_on(F2FS_I_SB(inode), 1);
> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> index 5980b9d79afb..a6cfceafe2fe 100644
> --- a/fs/f2fs/debug.c
> +++ b/fs/f2fs/debug.c
> @@ -343,7 +343,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
> /* build nm */
> si->base_mem += sizeof(struct f2fs_nm_info);
> si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
> - si->base_mem += F2FS_BLK_TO_BYTES(NM_I(sbi)->nat_bits_blocks);
> + si->base_mem += F2FS_BLK_TO_BYTES(sbi, NM_I(sbi)->nat_bits_blocks);
> si->base_mem += NM_I(sbi)->nat_blocks *
> f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi));
> si->base_mem += NM_I(sbi)->nat_blocks / 8;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index b90c5a42703f..c625a2572841 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -4016,7 +4016,7 @@ void f2fs_inode_synced(struct inode *inode);
> int f2fs_dquot_initialize(struct inode *inode);
> int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly);
> int f2fs_do_quota_sync(struct super_block *sb, int type);
> -loff_t max_file_blocks(struct inode *inode);
> +loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode);
> void f2fs_quota_off_umount(struct super_block *sb);
> void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag);
> void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
> @@ -5263,8 +5263,9 @@ static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi,
> NULL, 0, DATA);
>
> truncate_inode_pages_range(META_MAPPING(sbi),
> - F2FS_BLK_TO_BYTES((loff_t)blkaddr),
> - F2FS_BLK_END_BYTES((loff_t)(blkaddr + cnt - 1)));
> + F2FS_BLK_TO_BYTES(sbi, (loff_t)blkaddr),
> + F2FS_BLK_END_BYTES(sbi,
> + (loff_t)(blkaddr + cnt - 1)));
> }
>
> static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi,
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 2c72e028cec2..6fafb32bc5f2 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -513,7 +513,8 @@ static bool __found_offset(struct address_space *mapping,
> static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
> {
> struct inode *inode = file->f_mapping->host;
> - loff_t maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
> + loff_t maxbytes = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
> + max_file_blocks(F2FS_I_SB(inode), inode));
> struct dnode_of_data dn;
> pgoff_t pgofs, end_offset;
> loff_t data_ofs = offset;
> @@ -537,9 +538,10 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
> }
> }
>
> - pgofs = (pgoff_t)(offset >> PAGE_SHIFT);
> + pgofs = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), offset);
>
> - for (; data_ofs < isize; data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
> + for (; data_ofs < isize;
> + data_ofs = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), pgofs)) {
> set_new_dnode(&dn, inode, NULL, NULL, 0);
> err = f2fs_get_dnode_of_data(&dn, pgofs, LOOKUP_NODE);
> if (err && err != -ENOENT) {
> @@ -559,7 +561,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
> /* find data/hole in dnode block */
> for (; dn.ofs_in_node < end_offset;
> dn.ofs_in_node++, pgofs++,
> - data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
> + data_ofs = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), pgofs)) {
> block_t blkaddr;
>
> blkaddr = f2fs_data_blkaddr(&dn);
> @@ -595,7 +597,8 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
> static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence)
> {
> struct inode *inode = file->f_mapping->host;
> - loff_t maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
> + loff_t maxbytes = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
> + max_file_blocks(F2FS_I_SB(inode), inode));
>
> switch (whence) {
> case SEEK_SET:
> @@ -846,9 +849,9 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock)
> goto out_err;
> }
>
> - free_from = (pgoff_t)F2FS_BLK_ALIGN(from);
> + free_from = (pgoff_t)F2FS_BLK_ALIGN(sbi, from);
>
> - if (free_from >= max_file_blocks(inode))
> + if (free_from >= max_file_blocks(sbi, inode))
> goto free_partial;
>
> if (lock)
> @@ -959,9 +962,10 @@ int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock)
>
> int f2fs_truncate(struct inode *inode)
> {
> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> int err;
>
> - if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
> + if (unlikely(f2fs_cp_error(sbi)))
> return -EIO;
>
> if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
> @@ -970,7 +974,7 @@ int f2fs_truncate(struct inode *inode)
>
> trace_f2fs_truncate(inode);
>
> - if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE))
> + if (time_to_inject(sbi, FAULT_TRUNCATE))
> return -EIO;
>
> err = f2fs_dquot_initialize(inode);
> @@ -986,8 +990,8 @@ int f2fs_truncate(struct inode *inode)
> * leak in evict() path.
> */
> truncate_inode_pages_range(inode->i_mapping,
> - F2FS_BLK_TO_BYTES(0),
> - F2FS_BLK_END_BYTES(0));
> + F2FS_BLK_TO_BYTES(sbi, 0),
> + F2FS_BLK_END_BYTES(sbi, 0));
> return err;
> }
> }
> @@ -1161,7 +1165,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> return -EOPNOTSUPP;
> if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) &&
> !IS_ALIGNED(attr->ia_size,
> - F2FS_BLK_TO_BYTES(fi->i_cluster_size)))
> + F2FS_BLK_TO_BYTES(sbi, fi->i_cluster_size)))
> return -EINVAL;
>
> if (f2fs_is_pinned_file(inode)) {
> @@ -1177,7 +1181,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> * pinned file.
> */
> else if (!IS_ALIGNED(attr->ia_size,
> - F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi))))
> + F2FS_BLK_TO_BYTES(sbi, CAP_BLKS_PER_SEC(sbi))))
> return -EINVAL;
> }
> }
> @@ -2648,7 +2652,8 @@ static int f2fs_keep_noreuse_range(struct inode *inode,
> loff_t offset, loff_t len)
> {
> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> - u64 max_bytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
> + u64 max_bytes = F2FS_BLK_TO_BYTES(sbi,
> + max_file_blocks(sbi, inode));
> u64 start, end;
> int ret = 0;
>
> @@ -3191,8 +3196,8 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
> if (range.start & (F2FS_BLKSIZE - 1) || range.len & (F2FS_BLKSIZE - 1))
> return -EINVAL;
>
> - if (unlikely((range.start + range.len) >> PAGE_SHIFT >
> - max_file_blocks(inode)))
> + if (unlikely(F2FS_BYTES_TO_BLK(sbi, range.start + range.len) >
> + max_file_blocks(sbi, inode)))
> return -EINVAL;
>
> err = mnt_want_write_file(filp);
> @@ -3326,9 +3331,9 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
> }
>
> f2fs_lock_op(sbi, &lc);
> - ret = __exchange_data_block(src, dst, F2FS_BYTES_TO_BLK(pos_in),
> - F2FS_BYTES_TO_BLK(pos_out),
> - F2FS_BYTES_TO_BLK(len), false);
> + ret = __exchange_data_block(src, dst, F2FS_BYTES_TO_BLK(sbi, pos_in),
> + F2FS_BYTES_TO_BLK(sbi, pos_out),
> + F2FS_BYTES_TO_BLK(sbi, len), false);
>
> if (!ret) {
> if (dst_max_i_size)
> @@ -3994,7 +3999,7 @@ int f2fs_precache_extents(struct inode *inode)
> map.m_next_extent = &m_next_extent;
> map.m_seg_type = NO_CHECK_TYPE;
> map.m_may_create = false;
> - end = F2FS_BLK_ALIGN(i_size_read(inode));
> + end = F2FS_BLK_ALIGN(F2FS_I_SB(inode), i_size_read(inode));
>
> while (map.m_lblk < end) {
> map.m_len = end - map.m_lblk;
> @@ -4594,7 +4599,7 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
> goto err;
> }
>
> - index = F2FS_BYTES_TO_BLK(range.start);
> + index = F2FS_BYTES_TO_BLK(sbi, range.start);
> pg_end = DIV_ROUND_UP(end_addr, F2FS_BLKSIZE);
>
> ret = f2fs_convert_inline_inode(inode);
> @@ -5385,7 +5390,8 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter,
> * buffered IO, if DIO meets any holes.
> */
> if (dio && i_size_read(inode) &&
> - (F2FS_BYTES_TO_BLK(pos) < F2FS_BLK_ALIGN(i_size_read(inode))))
> + (F2FS_BYTES_TO_BLK(sbi, pos) <
> + F2FS_BLK_ALIGN(sbi, i_size_read(inode))))
> return 0;
>
> /* No-wait I/O can't allocate blocks. */
> @@ -5406,8 +5412,8 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter,
> }
>
> /* Do not preallocate blocks that will be written partially in 4KB. */
> - map.m_lblk = F2FS_BLK_ALIGN(pos);
> - map.m_len = F2FS_BYTES_TO_BLK(pos + count);
> + map.m_lblk = F2FS_BLK_ALIGN(sbi, pos);
> + map.m_len = F2FS_BYTES_TO_BLK(sbi, pos + count);
> if (map.m_len > map.m_lblk)
> map.m_len -= map.m_lblk;
> else
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 7dabfada1b54..e7aa3b790214 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -3294,9 +3294,10 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
> if (!enabled_nat_bits(sbi, NULL))
> return 0;
>
> - nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
> + nm_i->nat_bits_blocks = F2FS_BLK_ALIGN(sbi,
> + (nat_bits_bytes << 1) + 8);
> nm_i->nat_bits = f2fs_kvzalloc(sbi,
> - F2FS_BLK_TO_BYTES(nm_i->nat_bits_blocks), GFP_KERNEL);
> + F2FS_BLK_TO_BYTES(sbi, nm_i->nat_bits_blocks), GFP_KERNEL);
> if (!nm_i->nat_bits)
> return -ENOMEM;
>
> @@ -3309,7 +3310,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
> if (IS_ERR(folio))
> return PTR_ERR(folio);
>
> - memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(i),
> + memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(sbi, i),
> folio_address(folio), F2FS_BLKSIZE);
> f2fs_folio_put(folio, true);
> }
> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> index aaa5227739c8..b52718741ddc 100644
> --- a/fs/f2fs/recovery.c
> +++ b/fs/f2fs/recovery.c
> @@ -734,9 +734,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
> }
>
> if (!file_keep_isize(inode) &&
> - (i_size_read(inode) <= ((loff_t)index << PAGE_SHIFT)))
> + (i_size_read(inode) <= F2FS_BLK_TO_BYTES(sbi, index)))
> f2fs_i_size_write(inode,
> - (loff_t)(index + 1) << PAGE_SHIFT);
> + F2FS_BLK_TO_BYTES(sbi, index + 1));
>
> /*
> * dest is reserved block, invalidate src block
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index f565b6873832..f58b26c84b3a 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -3592,8 +3592,8 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
>
> int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
> {
> - __u64 start = F2FS_BYTES_TO_BLK(range->start);
> - __u64 end = start + F2FS_BYTES_TO_BLK(range->len) - 1;
> + __u64 start = F2FS_BYTES_TO_BLK(sbi, range->start);
> + __u64 end = start + F2FS_BYTES_TO_BLK(sbi, range->len) - 1;
> unsigned int start_segno, end_segno;
> block_t start_block, end_block;
> struct cp_control cpc;
> @@ -3624,7 +3624,8 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
> }
>
> cpc.reason = CP_DISCARD;
> - cpc.trim_minlen = max_t(__u64, 1, F2FS_BYTES_TO_BLK(range->minlen));
> + cpc.trim_minlen = max_t(__u64, 1,
> + F2FS_BYTES_TO_BLK(sbi, range->minlen));
> cpc.trim_start = start_segno;
> cpc.trim_end = end_segno;
>
> @@ -3658,7 +3659,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
> start_block, end_block);
> out:
> if (!err)
> - range->len = F2FS_BLK_TO_BYTES(trimmed);
> + range->len = F2FS_BLK_TO_BYTES(sbi, trimmed);
> return err;
> }
>
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 46973207cd7b..b962c14cbcc1 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -3884,7 +3884,7 @@ static const struct export_operations f2fs_export_ops = {
> .get_parent = f2fs_get_parent,
> };
>
> -loff_t max_file_blocks(struct inode *inode)
> +loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode)
> {
> loff_t result = 0;
> loff_t leaf_count;
> @@ -3918,7 +3918,8 @@ loff_t max_file_blocks(struct inode *inode)
> * fit within U32_MAX + 1 data units.
> */
>
> - result = umin(result, F2FS_BYTES_TO_BLK(((loff_t)U32_MAX + 1) * 4096));
> + result = umin(result, F2FS_BYTES_TO_BLK(sbi,
> + ((loff_t)U32_MAX + 1) * 4096));
>
> return result;
> }
> @@ -4370,7 +4371,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>
> nat_blocks = nat_segs << log_blocks_per_seg;
> nat_bits_bytes = nat_blocks / BITS_PER_BYTE;
> - nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
> + nat_bits_blocks = F2FS_BLK_ALIGN(sbi, (nat_bits_bytes << 1) + 8);
> if (__is_set_ckpt_flags(ckpt, CP_NAT_BITS_FLAG) &&
> (cp_payload + F2FS_CP_PACKS +
> NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) {
> @@ -5193,7 +5194,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
> if (err)
> goto free_options;
>
> - sb->s_maxbytes = max_file_blocks(NULL) <<
> + sb->s_maxbytes = max_file_blocks(sbi, NULL) <<
> le32_to_cpu(raw_super->log_blocksize);
> sb->s_max_links = F2FS_LINK_MAX;
>
> diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c
> index 39f482515445..ee838f880c4a 100644
> --- a/fs/f2fs/verity.c
> +++ b/fs/f2fs/verity.c
> @@ -75,7 +75,8 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
> struct address_space *mapping = inode->i_mapping;
> const struct address_space_operations *aops = mapping->a_ops;
>
> - if (pos + count > F2FS_BLK_TO_BYTES(max_file_blocks(inode)))
> + if (pos + count > F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
> + max_file_blocks(F2FS_I_SB(inode), inode)))
> return -EFBIG;
>
> while (count) {
> @@ -239,7 +240,8 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
>
> /* Get the descriptor */
> if (pos + size < pos ||
> - pos + size > F2FS_BLK_TO_BYTES(max_file_blocks(inode)) ||
> + pos + size > F2FS_BLK_TO_BYTES(F2FS_I_SB(inode),
> + max_file_blocks(F2FS_I_SB(inode), inode)) ||
> pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) {
> f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr");
> f2fs_handle_error(F2FS_I_SB(inode),
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index f89609356be8..f622d26f37a7 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -28,10 +28,14 @@
> #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */
>
> #define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1)
> -#define F2FS_BYTES_TO_BLK(bytes) ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS)
> -#define F2FS_BLK_TO_BYTES(blk) ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS)
> -#define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1)
> -#define F2FS_BLK_ALIGN(x) (F2FS_BYTES_TO_BLK((x) + F2FS_BLKSIZE - 1))
> +#define F2FS_BYTES_TO_BLK(sbi, bytes) \
> + ((unsigned long long)(bytes) >> (sbi)->log_blocksize)
> +#define F2FS_BLK_TO_BYTES(sbi, blk) \
> + ((unsigned long long)(blk) << (sbi)->log_blocksize)
> +#define F2FS_BLK_END_BYTES(sbi, blk) \
> + (F2FS_BLK_TO_BYTES(sbi, (blk) + 1) - 1)
> +#define F2FS_BLK_ALIGN(sbi, x) \
> + DIV_ROUND_UP_ULL((x), (sbi)->blocksize)
DIV_ROUND_UP_ULL() expands internally to do_div().
Please restore the original bit-shifting style using F2FS_BYTES_TO_BLK:
#define F2FS_BLK_ALIGN(sbi, bytes) \
F2FS_BYTES_TO_BLK(sbi, (unsigned long long)(bytes) +
F2FS_BLKSIZE(sbi) - 1)
This avoids unnecessary 64-bit division overhead on hot I/O and block
calculation paths.
Thanks,
>
> /* 0, 1(node nid), 2(meta nid) are reserved node id */
> #define F2FS_RESERVED_NODE_NUM 3
> --
> 2.53.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 10/11] f2fs: parameterize block size and mask macros
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (8 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 09/11] f2fs: parameterize byte and block " Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
2026-09-01 12:03 ` Chao Yu via Linux-f2fs-devel
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 11/11] f2fs: describe node tree geometry dynamically Kelvin Zhang
10 siblings, 1 reply; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
Block size constants, shift counts, masks, and page-to-block ratios were
globally defined assuming a fixed 4KB block size.
Parameterize F2FS_BLKSIZE, F2FS_BLKSIZE_BITS, F2FS_BLKSIZE_MASK,
F2FS_BLKS_PER_PAGE, and CP_CHKSUM_OFFSET with struct f2fs_sb_info *sbi
to reference sbi->blocksize, sbi->log_blocksize, and runtime masks.
Update call sites across metadata operations, data I/O, file operations,
garbage collection, inline data, and sysfs information.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/checkpoint.c | 23 ++++++++++++-----------
fs/f2fs/data.c | 25 ++++++++++++++-----------
fs/f2fs/extent_cache.c | 6 ++++--
fs/f2fs/f2fs.h | 15 +++++++++++----
fs/f2fs/file.c | 30 +++++++++++++++++-------------
fs/f2fs/gc.c | 11 ++++++-----
fs/f2fs/inline.c | 6 +++---
fs/f2fs/inode.c | 4 ++--
fs/f2fs/node.c | 7 ++++---
fs/f2fs/node.h | 2 +-
fs/f2fs/segment.c | 18 +++++++++++-------
fs/f2fs/segment.h | 4 ++--
fs/f2fs/super.c | 6 +++---
fs/f2fs/sysfs.c | 10 +++++-----
fs/f2fs/xattr.c | 2 +-
include/linux/f2fs_fs.h | 22 +++++++++++-----------
16 files changed, 107 insertions(+), 84 deletions(-)
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index d0dcc918422e..015c7449e45a 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -288,7 +288,7 @@ static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index,
return ERR_PTR(err);
}
- f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE(sbi));
folio_lock(folio);
if (unlikely(!is_meta_folio(folio))) {
@@ -513,7 +513,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
if (!err)
f2fs_update_iostat(sbi, NULL, FS_META_READ_IO,
- F2FS_BLKSIZE);
+ F2FS_BLKSIZE(sbi));
}
out:
blk_finish_plug(&plug);
@@ -1141,16 +1141,17 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
}
}
-static __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *ckpt)
+static __u32 f2fs_checkpoint_chksum(struct f2fs_sb_info *sbi,
+ struct f2fs_checkpoint *ckpt)
{
unsigned int chksum_ofs = le32_to_cpu(ckpt->checksum_offset);
__u32 chksum;
chksum = f2fs_crc32(ckpt, chksum_ofs);
- if (chksum_ofs < CP_CHKSUM_OFFSET) {
+ if (chksum_ofs < CP_CHKSUM_OFFSET(sbi)) {
chksum_ofs += sizeof(chksum);
chksum = f2fs_chksum(chksum, (__u8 *)ckpt + chksum_ofs,
- F2FS_BLKSIZE - chksum_ofs);
+ F2FS_BLKSIZE(sbi) - chksum_ofs);
}
return chksum;
}
@@ -1170,13 +1171,13 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
if (crc_offset < CP_MIN_CHKSUM_OFFSET ||
- crc_offset > CP_CHKSUM_OFFSET) {
+ crc_offset > CP_CHKSUM_OFFSET(sbi)) {
f2fs_folio_put(*cp_folio, true);
f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset);
return -EINVAL;
}
- crc = f2fs_checkpoint_chksum(*cp_block);
+ crc = f2fs_checkpoint_chksum(sbi, *cp_block);
if (crc != cur_cp_crc(*cp_block)) {
f2fs_folio_put(*cp_folio, true);
f2fs_warn(sbi, "invalid crc value");
@@ -1713,7 +1714,7 @@ static void commit_checkpoint(struct f2fs_sb_info *sbi,
*/
struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
- memcpy(folio_address(folio), src, PAGE_SIZE);
+ memcpy(folio_address(folio), src, F2FS_BLKSIZE(sbi));
folio_mark_dirty(folio);
if (unlikely(!folio_clear_dirty_for_io(folio)))
@@ -1848,7 +1849,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
- crc32 = f2fs_checkpoint_chksum(ckpt);
+ crc32 = f2fs_checkpoint_chksum(sbi, ckpt);
*((__le32 *)((unsigned char *)ckpt +
le32_to_cpu(ckpt->checksum_offset)))
= cpu_to_le32(crc32);
@@ -1873,8 +1874,8 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
f2fs_update_meta_page(sbi, ckpt, start_blk++);
for (i = 1; i < 1 + cp_payload_blks; i++)
- f2fs_update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE,
- start_blk++);
+ f2fs_update_meta_page(sbi, (char *)ckpt +
+ i * F2FS_BLKSIZE(sbi), start_blk++);
if (orphan_num) {
write_orphan_inodes(sbi, start_blk);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 6ee4440c17dd..d7b22eaa746e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1227,7 +1227,7 @@ static void f2fs_submit_page_read(struct inode *inode, struct fsverity_info *vi,
f2fs_bug_on(sbi, 1);
inc_page_count(sbi, F2FS_RD_DATA);
- f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE(sbi));
f2fs_submit_read_bio(sbi, bio, DATA);
}
@@ -2210,7 +2210,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
count_in_cluster += map.m_len;
if (count_in_cluster == cluster_size) {
compr_cluster = false;
- size += F2FS_BLKSIZE;
+ size += F2FS_BLKSIZE(sbi);
}
} else if (map.m_flags & F2FS_MAP_DELALLOC) {
flags = FIEMAP_EXTENT_UNWRITTEN;
@@ -2255,7 +2255,7 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
struct readahead_control *rac)
{
struct bio *bio = *bio_ret;
- const unsigned int blocksize = F2FS_BLKSIZE;
+ const unsigned int blocksize = F2FS_BLKSIZE(F2FS_I_SB(inode));
sector_t block_in_file;
sector_t last_block;
sector_t last_block_in_file;
@@ -2344,7 +2344,7 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO,
- F2FS_BLKSIZE);
+ F2FS_BLKSIZE(F2FS_I_SB(inode)));
*last_block_in_bio = block_nr;
out:
*bio_ret = bio;
@@ -2362,7 +2362,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
struct bio *bio = *bio_ret;
unsigned int start_idx = cc->cluster_idx << cc->log_cluster_size;
sector_t last_block_in_file;
- const unsigned int blocksize = F2FS_BLKSIZE;
+ const unsigned int blocksize = F2FS_BLKSIZE(sbi);
struct decompress_io_ctx *dic = NULL;
struct extent_info ei = {};
bool from_dnode = true;
@@ -2495,7 +2495,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
refcount_inc(&dic->refcnt);
inc_page_count(sbi, F2FS_RD_DATA);
- f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO,
+ F2FS_BLKSIZE(sbi));
*last_block_in_bio = blkaddr;
}
@@ -2669,14 +2670,14 @@ static int f2fs_read_data_large_folio(struct inode *inode,
*/
f2fs_wait_on_block_writeback(inode, block_nr);
- if (!bio_add_folio(bio, folio, F2FS_BLKSIZE,
- offset << PAGE_SHIFT))
+ if (!bio_add_folio(bio, folio, F2FS_BLKSIZE(F2FS_I_SB(inode)),
+ offset << PAGE_SHIFT))
goto submit_and_realloc;
folio_in_bio = true;
inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO,
- F2FS_BLKSIZE);
+ F2FS_BLKSIZE(F2FS_I_SB(inode)));
last_block_in_bio = block_nr;
}
trace_f2fs_read_folio(folio, DATA);
@@ -4230,6 +4231,7 @@ static sector_t f2fs_bmap_compress(struct inode *inode, sector_t block)
static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
{
struct inode *inode = mapping->host;
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
sector_t blknr = 0;
if (f2fs_has_inline_data(inode))
@@ -4240,7 +4242,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
filemap_write_and_wait(mapping);
/* Block number less than F2FS MAX BLOCKS */
- if (unlikely(block >= max_file_blocks(F2FS_I_SB(inode), inode)))
+ if (unlikely(block >= max_file_blocks(sbi, inode)))
goto out;
if (f2fs_compressed_file(inode)) {
@@ -4442,7 +4444,8 @@ static int check_swap_activate(struct swap_info_struct *sis,
out:
if (not_aligned)
f2fs_warn(sbi, "Swapfile (%u) is not align to section: 1) creat(), 2) ioctl(F2FS_IOC_SET_PIN_FILE), 3) fallocate(%lu * N)",
- not_aligned, blks_per_sec * F2FS_BLKSIZE);
+ not_aligned,
+ (unsigned long)blks_per_sec * F2FS_BLKSIZE(sbi));
return ret;
}
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
index 37cf9fa8d537..2d3fdd82b13d 100644
--- a/fs/f2fs/extent_cache.c
+++ b/fs/f2fs/extent_cache.c
@@ -904,11 +904,13 @@ static int __get_new_block_age(struct inode *inode, struct extent_info *ei,
struct extent_info tei = *ei; /* only fofs and len are valid */
/*
- * When I/O is not aligned to a PAGE_SIZE, update will happen to the last
+ * When I/O is not aligned to the filesystem block size, update will
+ * happen to the last
* file block even in seq write. So don't record age for newly last file
* block here.
*/
- if ((f_size >> PAGE_SHIFT) == ei->fofs && f_size & (PAGE_SIZE - 1) &&
+ if ((f_size >> sbi->log_blocksize) == ei->fofs &&
+ f_size & F2FS_BLKSIZE_MASK(sbi) &&
blkaddr == NEW_ADDR)
return -EINVAL;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c625a2572841..f83cdab66f54 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2234,7 +2234,7 @@ static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
return sb->s_fs_info;
}
-static inline struct f2fs_sb_info *F2FS_I_SB(struct inode *inode)
+static inline struct f2fs_sb_info *F2FS_I_SB(const struct inode *inode)
{
return F2FS_SB(inode->i_sb);
}
@@ -2249,12 +2249,18 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
return F2FS_M_SB(folio->mapping);
}
+static inline struct f2fs_sb_info *F2FS_P_SB(struct page *page)
+{
+ return F2FS_F_SB(page_folio(page));
+}
+
#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode)
#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
F2FS_ORPHANS_PER_BLOCK(sbi))
+#define CP_CHKSUM_OFFSET(sbi) (F2FS_BLKSIZE(sbi) - sizeof(__le32))
static inline struct f2fs_orphan_footer *
f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi)
@@ -2303,7 +2309,7 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio)
{
- return folio_address(folio) + F2FS_BLKSIZE -
+ return folio_address(folio) + F2FS_BLKSIZE(F2FS_F_SB(folio)) -
sizeof(struct node_footer);
}
@@ -2319,7 +2325,8 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio)
static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio)
{
- return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) -
+ return folio_address(folio) + F2FS_BLKSIZE(F2FS_F_SB(folio)) -
+ sizeof(struct node_footer) -
SIZE_OF_I_NID;
}
@@ -2968,7 +2975,7 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
if (flag == NAT_BITMAP)
return tmp_ptr;
else
- return (unsigned char *)ckpt + F2FS_BLKSIZE;
+ return (unsigned char *)ckpt + F2FS_BLKSIZE(sbi);
} else {
offset = (flag == NAT_BITMAP) ?
le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6fafb32bc5f2..7001c18da506 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -110,7 +110,8 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
ret = filemap_fault(vmf);
if (ret & VM_FAULT_LOCKED)
f2fs_update_iostat(F2FS_I_SB(inode), inode,
- APP_MAPPED_READ_IO, F2FS_BLKSIZE);
+ APP_MAPPED_READ_IO,
+ F2FS_BLKSIZE(F2FS_I_SB(inode)));
trace_f2fs_filemap_fault(inode, vmf->pgoff, flags, ret);
@@ -233,7 +234,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
}
folio_mark_dirty(folio);
- f2fs_update_iostat(sbi, inode, APP_MAPPED_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, inode, APP_MAPPED_IO, F2FS_BLKSIZE(sbi));
f2fs_update_time(sbi, REQ_TIME);
out_sem:
@@ -974,7 +975,7 @@ int f2fs_truncate(struct inode *inode)
trace_f2fs_truncate(inode);
- if (time_to_inject(sbi, FAULT_TRUNCATE))
+ if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE))
return -EIO;
err = f2fs_dquot_initialize(inode);
@@ -1675,7 +1676,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
return -EINVAL;
/* collapse range should be aligned to block size of f2fs. */
- if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1))
+ if (offset & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)) ||
+ len & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)))
return -EINVAL;
ret = f2fs_convert_inline_inode(inode);
@@ -1890,7 +1892,8 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
return -EINVAL;
/* insert range should be aligned to block size of f2fs. */
- if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1))
+ if (offset & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)) ||
+ len & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)))
return -EINVAL;
ret = f2fs_convert_inline_inode(inode);
@@ -3193,7 +3196,8 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
return -EFAULT;
/* verify alignment of offset & size */
- if (range.start & (F2FS_BLKSIZE - 1) || range.len & (F2FS_BLKSIZE - 1))
+ if (range.start & F2FS_BLKSIZE_MASK(sbi) ||
+ range.len & F2FS_BLKSIZE_MASK(sbi))
return -EINVAL;
if (unlikely(F2FS_BYTES_TO_BLK(sbi, range.start + range.len) >
@@ -3279,7 +3283,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
if (src == dst && pos_out > pos_in && pos_out < pos_in + len)
goto out_unlock;
if (pos_in + len == src->i_size)
- len = ALIGN(src->i_size, F2FS_BLKSIZE) - pos_in;
+ len = ALIGN(src->i_size, F2FS_BLKSIZE(sbi)) - pos_in;
if (len == 0) {
ret = 0;
goto out_unlock;
@@ -3297,9 +3301,9 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
}
/* verify the end result is block aligned */
- if (!IS_ALIGNED(pos_in, F2FS_BLKSIZE) ||
- !IS_ALIGNED(pos_in + len, F2FS_BLKSIZE) ||
- !IS_ALIGNED(pos_out, F2FS_BLKSIZE))
+ if (!IS_ALIGNED(pos_in, F2FS_BLKSIZE(sbi)) ||
+ !IS_ALIGNED(pos_in + len, F2FS_BLKSIZE(sbi)) ||
+ !IS_ALIGNED(pos_out, F2FS_BLKSIZE(sbi)))
goto out_unlock;
ret = f2fs_convert_inline_inode(src);
@@ -4593,14 +4597,14 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
to_end = true;
}
- if (!IS_ALIGNED(range.start, F2FS_BLKSIZE) ||
- (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE))) {
+ if (!IS_ALIGNED(range.start, F2FS_BLKSIZE(sbi)) ||
+ (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE(sbi)))) {
ret = -EINVAL;
goto err;
}
index = F2FS_BYTES_TO_BLK(sbi, range.start);
- pg_end = DIV_ROUND_UP(end_addr, F2FS_BLKSIZE);
+ pg_end = F2FS_BLK_ALIGN(sbi, end_addr);
ret = f2fs_convert_inline_inode(inode);
if (ret)
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index f15ab07a7347..299d5310e597 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1303,8 +1303,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
f2fs_put_page(fio.encrypted_page, false);
f2fs_folio_put(folio, true);
- f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
- f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE(sbi));
+ f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE(sbi));
if (atomic_inode)
iput(atomic_inode);
@@ -1424,9 +1424,9 @@ static int move_data_block(struct inode *inode, block_t bidx,
}
f2fs_update_iostat(fio.sbi, inode, FS_DATA_READ_IO,
- F2FS_BLKSIZE);
+ F2FS_BLKSIZE(fio.sbi));
f2fs_update_iostat(fio.sbi, NULL, FS_GDATA_READ_IO,
- F2FS_BLKSIZE);
+ F2FS_BLKSIZE(fio.sbi));
folio_lock(mfolio);
if (unlikely(!is_meta_folio(mfolio) ||
@@ -1477,7 +1477,8 @@ static int move_data_block(struct inode *inode, block_t bidx,
fio.new_blkaddr = newaddr;
f2fs_submit_page_write(&fio);
- f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO,
+ F2FS_BLKSIZE(fio.sbi));
f2fs_update_data_blkaddr(&dn, newaddr);
set_inode_flag(inode, FI_APPEND_WRITE);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 73cd9b6ddcc5..3e0b9449ffba 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -448,7 +448,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio,
* Start by zeroing the full block, to ensure that all unused space is
* zeroed and no uninitialized memory is leaked to disk.
*/
- memset(dentry_blk, 0, F2FS_BLKSIZE);
+ memset(dentry_blk, 0, F2FS_BLKSIZE(F2FS_I_SB(dir)));
make_dentry_ptr_inline(dir, &src, inline_dentry);
make_dentry_ptr_block(dir, &dst, dentry_blk);
@@ -477,8 +477,8 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio,
F2FS_I(dir)->i_inline_xattr_size = 0;
f2fs_i_depth_write(dir, 1);
- if (i_size_read(dir) < PAGE_SIZE)
- f2fs_i_size_write(dir, PAGE_SIZE);
+ if (i_size_read(dir) < F2FS_BLKSIZE(F2FS_I_SB(dir)))
+ f2fs_i_size_write(dir, F2FS_BLKSIZE(F2FS_I_SB(dir)));
out:
f2fs_folio_put(folio, true);
return err;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index b628fdc4198f..b947b724b3bc 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -165,7 +165,7 @@ static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
chksum = f2fs_chksum(chksum, (__u8 *)&dummy_cs, cs_size);
offset += cs_size;
chksum = f2fs_chksum(chksum, (__u8 *)ri + offset,
- F2FS_BLKSIZE - offset);
+ F2FS_BLKSIZE(sbi) - offset);
return chksum;
}
@@ -447,7 +447,7 @@ static int do_read_inode(struct inode *inode)
set_nlink(inode, le32_to_cpu(ri->i_links));
inode->i_size = le64_to_cpu(ri->i_size);
inode->i_blocks = SECTOR_FROM_BLOCK(sbi,
- le64_to_cpu(ri->i_blocks) - 1);
+ le64_to_cpu(ri->i_blocks) - 1);
inode_set_atime(inode, le64_to_cpu(ri->i_atime),
le32_to_cpu(ri->i_atime_nsec));
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index e7aa3b790214..8d16715a3aae 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -165,7 +165,7 @@ static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
src_addr = folio_address(src_folio);
dst_addr = folio_address(dst_folio);
- memcpy(dst_addr, src_addr, PAGE_SIZE);
+ memcpy(dst_addr, src_addr, F2FS_BLKSIZE(sbi));
folio_mark_dirty(dst_folio);
f2fs_folio_put(src_folio, true);
@@ -1498,7 +1498,8 @@ static int read_node_folio(struct folio *folio, blk_opf_t op_flags)
err = f2fs_submit_page_bio(&fio);
if (!err)
- f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO,
+ F2FS_BLKSIZE(sbi));
return err;
}
@@ -3311,7 +3312,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
return PTR_ERR(folio);
memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(sbi, i),
- folio_address(folio), F2FS_BLKSIZE);
+ folio_address(folio), F2FS_BLKSIZE(sbi));
f2fs_folio_put(folio, true);
}
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 6a2b7c63f4a3..32125f8fc753 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -284,7 +284,7 @@ static inline void fill_node_footer(const struct folio *folio, nid_t nid,
unsigned int old_flag = 0;
if (reset)
- memset(rn, 0, F2FS_BLKSIZE);
+ memset(rn, 0, F2FS_BLKSIZE(F2FS_F_SB(folio)));
else
old_flag = le32_to_cpu(footer->flag);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index f58b26c84b3a..f2641a6080ae 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1316,7 +1316,8 @@ static void __submit_zone_reset_cmd(struct f2fs_sb_info *sbi,
submit_bio(bio);
atomic_inc(&dcc->issued_discard);
- f2fs_update_iostat(sbi, NULL, FS_ZONE_RESET_IO, dc->di.len * F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, NULL, FS_ZONE_RESET_IO,
+ dc->di.len * F2FS_BLKSIZE(sbi));
}
#endif
@@ -1419,7 +1420,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
atomic_inc(&dcc->issued_discard);
- f2fs_update_iostat(sbi, NULL, FS_DISCARD_IO, len * F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, NULL, FS_DISCARD_IO,
+ len * F2FS_BLKSIZE(sbi));
lstart += len;
start += len;
@@ -2797,7 +2799,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
if (IS_ERR(folio))
return;
- memcpy(folio_address(folio), src, PAGE_SIZE);
+ memcpy(folio_address(folio), src, F2FS_BLKSIZE(sbi));
folio_mark_dirty(folio);
f2fs_folio_put(folio, true);
}
@@ -4152,7 +4154,7 @@ void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
f2fs_submit_page_write(&fio);
stat_inc_meta_count(sbi, folio->index);
- f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE(sbi));
}
void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio)
@@ -4162,7 +4164,8 @@ void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio)
set_summary(&sum, nid, 0, 0);
do_write_page(&sum, fio);
- f2fs_update_iostat(fio->sbi, NULL, fio->io_type, F2FS_BLKSIZE);
+ f2fs_update_iostat(fio->sbi, NULL, fio->io_type,
+ F2FS_BLKSIZE(fio->sbi));
}
void f2fs_outplace_write_data(struct dnode_of_data *dn,
@@ -4178,7 +4181,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn,
do_write_page(&sum, fio);
f2fs_update_data_blkaddr(dn, fio->new_blkaddr);
- f2fs_update_iostat(sbi, dn->inode, fio->io_type, F2FS_BLKSIZE);
+ f2fs_update_iostat(sbi, dn->inode, fio->io_type,
+ F2FS_BLKSIZE(sbi));
}
int f2fs_inplace_write_data(struct f2fs_io_info *fio)
@@ -4220,7 +4224,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
f2fs_update_device_state(fio->sbi, fio->ino,
fio->new_blkaddr, 1);
f2fs_update_iostat(fio->sbi, fio_inode(fio),
- fio->io_type, F2FS_BLKSIZE);
+ fio->io_type, F2FS_BLKSIZE(fio->sbi));
}
return err;
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 2275404e769c..2c85c085961b 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -116,7 +116,7 @@ f2fs_start_segno(struct f2fs_sb_info *sbi, unsigned int segno)
#define SECTOR_FROM_BLOCK(sbi, blk_addr) \
(((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK(sbi))
-#define SECTOR_TO_BLOCK(sbi, sectors) \
+#define SECTOR_TO_BLOCK(sbi, sectors) \
((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK(sbi))
/*
@@ -432,7 +432,7 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
int i;
raw_sit = folio_address(folio);
- memset(raw_sit, 0, PAGE_SIZE);
+ memset(raw_sit, 0, F2FS_BLKSIZE(sbi));
for (i = 0; i < end - start; i++) {
rs = &raw_sit->entries[i];
se = get_seg_entry(sbi, start + i);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index b962c14cbcc1..ca6403a0ed88 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1610,7 +1610,7 @@ static int f2fs_check_opt_consistency(struct fs_context *fc,
return -EINVAL;
}
min_size = MIN_INLINE_XATTR_SIZE;
- max_size = MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_BLKSIZE);
+ max_size = MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_BLKSIZE(sbi));
if (F2FS_OPTION(sbi).inline_xattr_size < min_size ||
F2FS_OPTION(sbi).inline_xattr_size > max_size) {
@@ -4079,10 +4079,10 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
}
/* only support block_size equals to PAGE_SIZE */
- if (le32_to_cpu(raw_super->log_blocksize) != F2FS_BLKSIZE_BITS) {
+ if (le32_to_cpu(raw_super->log_blocksize) != PAGE_SHIFT) {
f2fs_info(sbi, "Invalid log_blocksize (%u), supports only %u",
le32_to_cpu(raw_super->log_blocksize),
- F2FS_BLKSIZE_BITS);
+ PAGE_SHIFT);
return -EFSCORRUPTED;
}
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 811e350a1430..aaca9ed9b169 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1871,8 +1871,8 @@ static int __maybe_unused disk_map_seq_show(struct seq_file *seq,
struct f2fs_sb_info *sbi = F2FS_SB(sb);
int i;
- seq_printf(seq, "Address Layout : %5luB Block address (# of Segments)\n",
- F2FS_BLKSIZE);
+ seq_printf(seq, "Address Layout : %5uB Block address (# of Segments)\n",
+ F2FS_BLKSIZE(sbi));
seq_printf(seq, " SB : %12s\n", "0/1024B");
seq_printf(seq, " seg0_blkaddr : 0x%010x\n", SEG0_BLKADDR(sbi));
seq_printf(seq, " Checkpoint : 0x%010x (%10d)\n",
@@ -1889,13 +1889,13 @@ static int __maybe_unused disk_map_seq_show(struct seq_file *seq,
seq_printf(seq, " Main : 0x%010x (%10d)\n",
SM_I(sbi)->main_blkaddr,
le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_main));
- seq_printf(seq, " Block size : %12lu KB\n", F2FS_BLKSIZE >> 10);
+ seq_printf(seq, " Block size : %12u KB\n", F2FS_BLKSIZE(sbi) >> 10);
seq_printf(seq, " Segment size : %12d MB\n",
- (BLKS_PER_SEG(sbi) << (F2FS_BLKSIZE_BITS - 10)) >> 10);
+ (BLKS_PER_SEG(sbi) << (F2FS_BLKSIZE_BITS(sbi) - 10)) >> 10);
seq_printf(seq, " Segs/Sections : %12d\n",
SEGS_PER_SEC(sbi));
seq_printf(seq, " Section size : %12d MB\n",
- (BLKS_PER_SEC(sbi) << (F2FS_BLKSIZE_BITS - 10)) >> 10);
+ (BLKS_PER_SEC(sbi) << (F2FS_BLKSIZE_BITS(sbi) - 10)) >> 10);
seq_printf(seq, " # of Sections : %12d\n",
le32_to_cpu(F2FS_RAW_SUPER(sbi)->section_count));
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 99c863513725..98059e583b09 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -850,4 +850,4 @@ int __init f2fs_init_xattr_cache(void)
void f2fs_destroy_xattr_cache(void)
{
kmem_cache_destroy(inline_xattr_slab);
-}
\ No newline at end of file
+}
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index f622d26f37a7..957bb713ff24 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -14,12 +14,9 @@
#define F2FS_SUPER_OFFSET 1024 /* byte-size offset */
#define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */
#define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
-#define F2FS_LOG_SECTORS_PER_BLOCK(sbi) ((sbi)->log_blocksize - 9) /* log number for sector/blk */
#define F2FS_MIN_LOG_BLOCKSIZE 12
#define F2FS_MIN_BLKSIZE 4096UL
-#define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */
#define F2FS_MAX_BLKSIZE PAGE_SIZE
-#define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
#define F2FS_MAX_EXTENSION 64 /* # of extension entries */
#define F2FS_EXTENSION_LEN 8 /* max size of extension */
@@ -27,15 +24,19 @@
#define NEW_ADDR ((block_t)-1) /* used as block_t addresses */
#define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */
-#define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1)
+#define F2FS_BLKSIZE(sbi) ((sbi)->blocksize)
+#define F2FS_BLKSIZE_BITS(sbi) ((sbi)->log_blocksize)
+#define F2FS_BLKSIZE_MASK(sbi) (F2FS_BLKSIZE(sbi) - 1)
+#define F2FS_LOG_SECTORS_PER_BLOCK(sbi) (F2FS_BLKSIZE_BITS(sbi) - 9)
+#define F2FS_BLKS_PER_PAGE(sbi) (PAGE_SIZE / F2FS_BLKSIZE(sbi))
#define F2FS_BYTES_TO_BLK(sbi, bytes) \
- ((unsigned long long)(bytes) >> (sbi)->log_blocksize)
+ ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS(sbi))
#define F2FS_BLK_TO_BYTES(sbi, blk) \
- ((unsigned long long)(blk) << (sbi)->log_blocksize)
+ ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS(sbi))
#define F2FS_BLK_END_BYTES(sbi, blk) \
(F2FS_BLK_TO_BYTES(sbi, (blk) + 1) - 1)
#define F2FS_BLK_ALIGN(sbi, x) \
- DIV_ROUND_UP_ULL((x), (sbi)->blocksize)
+ DIV_ROUND_UP_ULL((x), F2FS_BLKSIZE(sbi))
/* 0, 1(node nid), 2(meta nid) are reserved node id */
#define F2FS_RESERVED_NODE_NUM 3
@@ -221,7 +222,6 @@ struct f2fs_checkpoint {
unsigned char sit_nat_version_bitmap[];
} __packed;
-#define CP_CHKSUM_OFFSET (F2FS_BLKSIZE - sizeof(__le32)) /* default chksum offset in checkpoint */
#define CP_MIN_CHKSUM_OFFSET \
(offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap))
@@ -271,7 +271,7 @@ struct node_footer {
} __packed;
/* Address Pointers in an Inode */
-#define DEF_ADDRS_PER_INODE ((F2FS_BLKSIZE - OFFSET_OF_END_OF_I_EXT \
+#define DEF_ADDRS_PER_INODE ((PAGE_SIZE - OFFSET_OF_END_OF_I_EXT \
- SIZE_OF_I_NID \
- sizeof(struct node_footer)) / sizeof(__le32))
#define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \
@@ -279,10 +279,10 @@ struct node_footer {
#define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */
#define ADDRS_PER_INODE(inode) addrs_per_page(inode, true)
/* Address Pointers in a Direct Block */
-#define DEF_ADDRS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32))
+#define DEF_ADDRS_PER_BLOCK ((PAGE_SIZE - sizeof(struct node_footer)) / sizeof(__le32))
#define ADDRS_PER_BLOCK(inode) addrs_per_page(inode, false)
/* Node IDs in an Indirect Block */
-#define NIDS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32))
+#define NIDS_PER_BLOCK ((PAGE_SIZE - sizeof(struct node_footer)) / sizeof(__le32))
#define ADDRS_PER_PAGE(folio, inode) (addrs_per_page(inode, IS_INODE(folio)))
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [f2fs-dev] [PATCH v7 10/11] f2fs: parameterize block size and mask macros
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 10/11] f2fs: parameterize block size and mask macros Kelvin Zhang
@ 2026-09-01 12:03 ` Chao Yu via Linux-f2fs-devel
2026-09-01 16:38 ` Xinping Zhang
0 siblings, 1 reply; 30+ messages in thread
From: Chao Yu via Linux-f2fs-devel @ 2026-09-01 12:03 UTC (permalink / raw)
To: Kelvin Zhang, linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
On 9/1/26 06:08, Kelvin Zhang wrote:
> Block size constants, shift counts, masks, and page-to-block ratios were
> globally defined assuming a fixed 4KB block size.
>
> Parameterize F2FS_BLKSIZE, F2FS_BLKSIZE_BITS, F2FS_BLKSIZE_MASK,
> F2FS_BLKS_PER_PAGE, and CP_CHKSUM_OFFSET with struct f2fs_sb_info *sbi
> to reference sbi->blocksize, sbi->log_blocksize, and runtime masks.
>
> Update call sites across metadata operations, data I/O, file operations,
> garbage collection, inline data, and sysfs information.
>
> Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
> ---
> fs/f2fs/checkpoint.c | 23 ++++++++++++-----------
> fs/f2fs/data.c | 25 ++++++++++++++-----------
> fs/f2fs/extent_cache.c | 6 ++++--
> fs/f2fs/f2fs.h | 15 +++++++++++----
> fs/f2fs/file.c | 30 +++++++++++++++++-------------
> fs/f2fs/gc.c | 11 ++++++-----
> fs/f2fs/inline.c | 6 +++---
> fs/f2fs/inode.c | 4 ++--
> fs/f2fs/node.c | 7 ++++---
> fs/f2fs/node.h | 2 +-
> fs/f2fs/segment.c | 18 +++++++++++-------
> fs/f2fs/segment.h | 4 ++--
> fs/f2fs/super.c | 6 +++---
> fs/f2fs/sysfs.c | 10 +++++-----
> fs/f2fs/xattr.c | 2 +-
> include/linux/f2fs_fs.h | 22 +++++++++++-----------
> 16 files changed, 107 insertions(+), 84 deletions(-)
>
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index d0dcc918422e..015c7449e45a 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -288,7 +288,7 @@ static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index,
> return ERR_PTR(err);
> }
>
> - f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE(sbi));
>
> folio_lock(folio);
> if (unlikely(!is_meta_folio(folio))) {
> @@ -513,7 +513,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
>
> if (!err)
> f2fs_update_iostat(sbi, NULL, FS_META_READ_IO,
> - F2FS_BLKSIZE);
> + F2FS_BLKSIZE(sbi));
> }
> out:
> blk_finish_plug(&plug);
> @@ -1141,16 +1141,17 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
> }
> }
>
> -static __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *ckpt)
> +static __u32 f2fs_checkpoint_chksum(struct f2fs_sb_info *sbi,
> + struct f2fs_checkpoint *ckpt)
> {
> unsigned int chksum_ofs = le32_to_cpu(ckpt->checksum_offset);
> __u32 chksum;
>
> chksum = f2fs_crc32(ckpt, chksum_ofs);
> - if (chksum_ofs < CP_CHKSUM_OFFSET) {
> + if (chksum_ofs < CP_CHKSUM_OFFSET(sbi)) {
> chksum_ofs += sizeof(chksum);
> chksum = f2fs_chksum(chksum, (__u8 *)ckpt + chksum_ofs,
> - F2FS_BLKSIZE - chksum_ofs);
> + F2FS_BLKSIZE(sbi) - chksum_ofs);
> }
> return chksum;
> }
> @@ -1170,13 +1171,13 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
>
> crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
> if (crc_offset < CP_MIN_CHKSUM_OFFSET ||
> - crc_offset > CP_CHKSUM_OFFSET) {
> + crc_offset > CP_CHKSUM_OFFSET(sbi)) {
> f2fs_folio_put(*cp_folio, true);
> f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset);
> return -EINVAL;
> }
>
> - crc = f2fs_checkpoint_chksum(*cp_block);
> + crc = f2fs_checkpoint_chksum(sbi, *cp_block);
> if (crc != cur_cp_crc(*cp_block)) {
> f2fs_folio_put(*cp_folio, true);
> f2fs_warn(sbi, "invalid crc value");
> @@ -1713,7 +1714,7 @@ static void commit_checkpoint(struct f2fs_sb_info *sbi,
> */
> struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
>
> - memcpy(folio_address(folio), src, PAGE_SIZE);
> + memcpy(folio_address(folio), src, F2FS_BLKSIZE(sbi));
>
> folio_mark_dirty(folio);
> if (unlikely(!folio_clear_dirty_for_io(folio)))
> @@ -1848,7 +1849,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
> get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
>
> - crc32 = f2fs_checkpoint_chksum(ckpt);
> + crc32 = f2fs_checkpoint_chksum(sbi, ckpt);
> *((__le32 *)((unsigned char *)ckpt +
> le32_to_cpu(ckpt->checksum_offset)))
> = cpu_to_le32(crc32);
> @@ -1873,8 +1874,8 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
> f2fs_update_meta_page(sbi, ckpt, start_blk++);
>
> for (i = 1; i < 1 + cp_payload_blks; i++)
> - f2fs_update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE,
> - start_blk++);
> + f2fs_update_meta_page(sbi, (char *)ckpt +
> + i * F2FS_BLKSIZE(sbi), start_blk++);
>
> if (orphan_num) {
> write_orphan_inodes(sbi, start_blk);
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 6ee4440c17dd..d7b22eaa746e 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1227,7 +1227,7 @@ static void f2fs_submit_page_read(struct inode *inode, struct fsverity_info *vi,
> f2fs_bug_on(sbi, 1);
>
> inc_page_count(sbi, F2FS_RD_DATA);
> - f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE(sbi));
> f2fs_submit_read_bio(sbi, bio, DATA);
> }
>
> @@ -2210,7 +2210,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> count_in_cluster += map.m_len;
> if (count_in_cluster == cluster_size) {
> compr_cluster = false;
> - size += F2FS_BLKSIZE;
> + size += F2FS_BLKSIZE(sbi);
> }
> } else if (map.m_flags & F2FS_MAP_DELALLOC) {
> flags = FIEMAP_EXTENT_UNWRITTEN;
> @@ -2255,7 +2255,7 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
> struct readahead_control *rac)
> {
> struct bio *bio = *bio_ret;
> - const unsigned int blocksize = F2FS_BLKSIZE;
> + const unsigned int blocksize = F2FS_BLKSIZE(F2FS_I_SB(inode));
> sector_t block_in_file;
> sector_t last_block;
> sector_t last_block_in_file;
> @@ -2344,7 +2344,7 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
>
> inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
> f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO,
> - F2FS_BLKSIZE);
> + F2FS_BLKSIZE(F2FS_I_SB(inode)));
> *last_block_in_bio = block_nr;
> out:
> *bio_ret = bio;
> @@ -2362,7 +2362,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
> struct bio *bio = *bio_ret;
> unsigned int start_idx = cc->cluster_idx << cc->log_cluster_size;
> sector_t last_block_in_file;
> - const unsigned int blocksize = F2FS_BLKSIZE;
> + const unsigned int blocksize = F2FS_BLKSIZE(sbi);
> struct decompress_io_ctx *dic = NULL;
> struct extent_info ei = {};
> bool from_dnode = true;
> @@ -2495,7 +2495,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
> refcount_inc(&dic->refcnt);
>
> inc_page_count(sbi, F2FS_RD_DATA);
> - f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO,
> + F2FS_BLKSIZE(sbi));
> *last_block_in_bio = blkaddr;
> }
>
> @@ -2669,14 +2670,14 @@ static int f2fs_read_data_large_folio(struct inode *inode,
> */
> f2fs_wait_on_block_writeback(inode, block_nr);
>
> - if (!bio_add_folio(bio, folio, F2FS_BLKSIZE,
> - offset << PAGE_SHIFT))
> + if (!bio_add_folio(bio, folio, F2FS_BLKSIZE(F2FS_I_SB(inode)),
> + offset << PAGE_SHIFT))
> goto submit_and_realloc;
>
> folio_in_bio = true;
> inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
> f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO,
> - F2FS_BLKSIZE);
> + F2FS_BLKSIZE(F2FS_I_SB(inode)));
> last_block_in_bio = block_nr;
> }
> trace_f2fs_read_folio(folio, DATA);
> @@ -4230,6 +4231,7 @@ static sector_t f2fs_bmap_compress(struct inode *inode, sector_t block)
> static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
> {
> struct inode *inode = mapping->host;
> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> sector_t blknr = 0;
>
> if (f2fs_has_inline_data(inode))
> @@ -4240,7 +4242,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
> filemap_write_and_wait(mapping);
>
> /* Block number less than F2FS MAX BLOCKS */
> - if (unlikely(block >= max_file_blocks(F2FS_I_SB(inode), inode)))
> + if (unlikely(block >= max_file_blocks(sbi, inode)))
> goto out;
>
> if (f2fs_compressed_file(inode)) {
> @@ -4442,7 +4444,8 @@ static int check_swap_activate(struct swap_info_struct *sis,
> out:
> if (not_aligned)
> f2fs_warn(sbi, "Swapfile (%u) is not align to section: 1) creat(), 2) ioctl(F2FS_IOC_SET_PIN_FILE), 3) fallocate(%lu * N)",
> - not_aligned, blks_per_sec * F2FS_BLKSIZE);
> + not_aligned,
> + (unsigned long)blks_per_sec * F2FS_BLKSIZE(sbi));
> return ret;
> }
>
> diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
> index 37cf9fa8d537..2d3fdd82b13d 100644
> --- a/fs/f2fs/extent_cache.c
> +++ b/fs/f2fs/extent_cache.c
> @@ -904,11 +904,13 @@ static int __get_new_block_age(struct inode *inode, struct extent_info *ei,
> struct extent_info tei = *ei; /* only fofs and len are valid */
>
> /*
> - * When I/O is not aligned to a PAGE_SIZE, update will happen to the last
> + * When I/O is not aligned to the filesystem block size, update will
> + * happen to the last
Looks like the comment was truncated here.
> * file block even in seq write. So don't record age for newly last file
> * block here.
When I/O is not aligned to the filesystem block size, update will
happen to the last file block even in seq write. So don't record
age for newly last file block here.
> */
> - if ((f_size >> PAGE_SHIFT) == ei->fofs && f_size & (PAGE_SIZE - 1) &&
> + if ((f_size >> sbi->log_blocksize) == ei->fofs &&
> + f_size & F2FS_BLKSIZE_MASK(sbi) &&
> blkaddr == NEW_ADDR)
> return -EINVAL;
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index c625a2572841..f83cdab66f54 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -2234,7 +2234,7 @@ static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
> return sb->s_fs_info;
> }
>
> -static inline struct f2fs_sb_info *F2FS_I_SB(struct inode *inode)
> +static inline struct f2fs_sb_info *F2FS_I_SB(const struct inode *inode)
Unneeded change?
> {
> return F2FS_SB(inode->i_sb);
> }
> @@ -2249,12 +2249,18 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio)
> return F2FS_M_SB(folio->mapping);
> }
>
> +static inline struct f2fs_sb_info *F2FS_P_SB(struct page *page)
> +{
> + return F2FS_F_SB(page_folio(page));
> +}
Unneeded? as no one will use in this patch?
> +
> #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
> #define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
> #define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode)
> #define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
> #define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
> F2FS_ORPHANS_PER_BLOCK(sbi))
> +#define CP_CHKSUM_OFFSET(sbi) (F2FS_BLKSIZE(sbi) - sizeof(__le32))
>
> static inline struct f2fs_orphan_footer *
> f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi)
> @@ -2303,7 +2309,7 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
>
> static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio)
> {
> - return folio_address(folio) + F2FS_BLKSIZE -
> + return folio_address(folio) + F2FS_BLKSIZE(F2FS_F_SB(folio)) -
> sizeof(struct node_footer);
> }
>
> @@ -2319,7 +2325,8 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio)
>
> static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio)
> {
> - return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) -
> + return folio_address(folio) + F2FS_BLKSIZE(F2FS_F_SB(folio)) -
> + sizeof(struct node_footer) -
> SIZE_OF_I_NID;
> }
>
> @@ -2968,7 +2975,7 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
> if (flag == NAT_BITMAP)
> return tmp_ptr;
> else
> - return (unsigned char *)ckpt + F2FS_BLKSIZE;
> + return (unsigned char *)ckpt + F2FS_BLKSIZE(sbi);
> } else {
> offset = (flag == NAT_BITMAP) ?
> le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 6fafb32bc5f2..7001c18da506 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -110,7 +110,8 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
> ret = filemap_fault(vmf);
> if (ret & VM_FAULT_LOCKED)
> f2fs_update_iostat(F2FS_I_SB(inode), inode,
> - APP_MAPPED_READ_IO, F2FS_BLKSIZE);
> + APP_MAPPED_READ_IO,
> + F2FS_BLKSIZE(F2FS_I_SB(inode)));
>
> trace_f2fs_filemap_fault(inode, vmf->pgoff, flags, ret);
>
> @@ -233,7 +234,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
> }
> folio_mark_dirty(folio);
>
> - f2fs_update_iostat(sbi, inode, APP_MAPPED_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, inode, APP_MAPPED_IO, F2FS_BLKSIZE(sbi));
> f2fs_update_time(sbi, REQ_TIME);
>
> out_sem:
> @@ -974,7 +975,7 @@ int f2fs_truncate(struct inode *inode)
>
> trace_f2fs_truncate(inode);
>
> - if (time_to_inject(sbi, FAULT_TRUNCATE))
> + if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE))
> return -EIO;
>
> err = f2fs_dquot_initialize(inode);
> @@ -1675,7 +1676,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
> return -EINVAL;
>
> /* collapse range should be aligned to block size of f2fs. */
> - if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1))
> + if (offset & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)) ||
> + len & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)))
> return -EINVAL;
>
> ret = f2fs_convert_inline_inode(inode);
> @@ -1890,7 +1892,8 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
> return -EINVAL;
>
> /* insert range should be aligned to block size of f2fs. */
> - if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1))
> + if (offset & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)) ||
> + len & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)))
> return -EINVAL;
>
> ret = f2fs_convert_inline_inode(inode);
> @@ -3193,7 +3196,8 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
> return -EFAULT;
>
> /* verify alignment of offset & size */
> - if (range.start & (F2FS_BLKSIZE - 1) || range.len & (F2FS_BLKSIZE - 1))
> + if (range.start & F2FS_BLKSIZE_MASK(sbi) ||
> + range.len & F2FS_BLKSIZE_MASK(sbi))
> return -EINVAL;
>
> if (unlikely(F2FS_BYTES_TO_BLK(sbi, range.start + range.len) >
> @@ -3279,7 +3283,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
> if (src == dst && pos_out > pos_in && pos_out < pos_in + len)
> goto out_unlock;
> if (pos_in + len == src->i_size)
> - len = ALIGN(src->i_size, F2FS_BLKSIZE) - pos_in;
> + len = ALIGN(src->i_size, F2FS_BLKSIZE(sbi)) - pos_in;
> if (len == 0) {
> ret = 0;
> goto out_unlock;
> @@ -3297,9 +3301,9 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
> }
>
> /* verify the end result is block aligned */
> - if (!IS_ALIGNED(pos_in, F2FS_BLKSIZE) ||
> - !IS_ALIGNED(pos_in + len, F2FS_BLKSIZE) ||
> - !IS_ALIGNED(pos_out, F2FS_BLKSIZE))
> + if (!IS_ALIGNED(pos_in, F2FS_BLKSIZE(sbi)) ||
> + !IS_ALIGNED(pos_in + len, F2FS_BLKSIZE(sbi)) ||
> + !IS_ALIGNED(pos_out, F2FS_BLKSIZE(sbi)))
> goto out_unlock;
>
> ret = f2fs_convert_inline_inode(src);
> @@ -4593,14 +4597,14 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
> to_end = true;
> }
>
> - if (!IS_ALIGNED(range.start, F2FS_BLKSIZE) ||
> - (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE))) {
> + if (!IS_ALIGNED(range.start, F2FS_BLKSIZE(sbi)) ||
> + (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE(sbi)))) {
> ret = -EINVAL;
> goto err;
> }
>
> index = F2FS_BYTES_TO_BLK(sbi, range.start);
> - pg_end = DIV_ROUND_UP(end_addr, F2FS_BLKSIZE);
> + pg_end = F2FS_BLK_ALIGN(sbi, end_addr);
>
> ret = f2fs_convert_inline_inode(inode);
> if (ret)
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index f15ab07a7347..299d5310e597 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1303,8 +1303,8 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
> f2fs_put_page(fio.encrypted_page, false);
> f2fs_folio_put(folio, true);
>
> - f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
> - f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE(sbi));
> + f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE(sbi));
>
> if (atomic_inode)
> iput(atomic_inode);
> @@ -1424,9 +1424,9 @@ static int move_data_block(struct inode *inode, block_t bidx,
> }
>
> f2fs_update_iostat(fio.sbi, inode, FS_DATA_READ_IO,
> - F2FS_BLKSIZE);
> + F2FS_BLKSIZE(fio.sbi));
> f2fs_update_iostat(fio.sbi, NULL, FS_GDATA_READ_IO,
> - F2FS_BLKSIZE);
> + F2FS_BLKSIZE(fio.sbi));
>
> folio_lock(mfolio);
> if (unlikely(!is_meta_folio(mfolio) ||
> @@ -1477,7 +1477,8 @@ static int move_data_block(struct inode *inode, block_t bidx,
> fio.new_blkaddr = newaddr;
> f2fs_submit_page_write(&fio);
>
> - f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO,
> + F2FS_BLKSIZE(fio.sbi));
>
> f2fs_update_data_blkaddr(&dn, newaddr);
> set_inode_flag(inode, FI_APPEND_WRITE);
> diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
> index 73cd9b6ddcc5..3e0b9449ffba 100644
> --- a/fs/f2fs/inline.c
> +++ b/fs/f2fs/inline.c
> @@ -448,7 +448,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio,
> * Start by zeroing the full block, to ensure that all unused space is
> * zeroed and no uninitialized memory is leaked to disk.
> */
> - memset(dentry_blk, 0, F2FS_BLKSIZE);
> + memset(dentry_blk, 0, F2FS_BLKSIZE(F2FS_I_SB(dir)));
>
> make_dentry_ptr_inline(dir, &src, inline_dentry);
> make_dentry_ptr_block(dir, &dst, dentry_blk);
> @@ -477,8 +477,8 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio,
> F2FS_I(dir)->i_inline_xattr_size = 0;
>
> f2fs_i_depth_write(dir, 1);
> - if (i_size_read(dir) < PAGE_SIZE)
> - f2fs_i_size_write(dir, PAGE_SIZE);
> + if (i_size_read(dir) < F2FS_BLKSIZE(F2FS_I_SB(dir)))
> + f2fs_i_size_write(dir, F2FS_BLKSIZE(F2FS_I_SB(dir)));
> out:
> f2fs_folio_put(folio, true);
> return err;
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index b628fdc4198f..b947b724b3bc 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -165,7 +165,7 @@ static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio)
> chksum = f2fs_chksum(chksum, (__u8 *)&dummy_cs, cs_size);
> offset += cs_size;
> chksum = f2fs_chksum(chksum, (__u8 *)ri + offset,
> - F2FS_BLKSIZE - offset);
> + F2FS_BLKSIZE(sbi) - offset);
> return chksum;
> }
>
> @@ -447,7 +447,7 @@ static int do_read_inode(struct inode *inode)
> set_nlink(inode, le32_to_cpu(ri->i_links));
> inode->i_size = le64_to_cpu(ri->i_size);
> inode->i_blocks = SECTOR_FROM_BLOCK(sbi,
> - le64_to_cpu(ri->i_blocks) - 1);
> + le64_to_cpu(ri->i_blocks) - 1);
Unneeded change.
>
> inode_set_atime(inode, le64_to_cpu(ri->i_atime),
> le32_to_cpu(ri->i_atime_nsec));
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index e7aa3b790214..8d16715a3aae 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -165,7 +165,7 @@ static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid)
>
> src_addr = folio_address(src_folio);
> dst_addr = folio_address(dst_folio);
> - memcpy(dst_addr, src_addr, PAGE_SIZE);
> + memcpy(dst_addr, src_addr, F2FS_BLKSIZE(sbi));
> folio_mark_dirty(dst_folio);
> f2fs_folio_put(src_folio, true);
>
> @@ -1498,7 +1498,8 @@ static int read_node_folio(struct folio *folio, blk_opf_t op_flags)
> err = f2fs_submit_page_bio(&fio);
>
> if (!err)
> - f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO,
> + F2FS_BLKSIZE(sbi));
>
> return err;
> }
> @@ -3311,7 +3312,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
> return PTR_ERR(folio);
>
> memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(sbi, i),
> - folio_address(folio), F2FS_BLKSIZE);
> + folio_address(folio), F2FS_BLKSIZE(sbi));
> f2fs_folio_put(folio, true);
> }
>
> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
> index 6a2b7c63f4a3..32125f8fc753 100644
> --- a/fs/f2fs/node.h
> +++ b/fs/f2fs/node.h
> @@ -284,7 +284,7 @@ static inline void fill_node_footer(const struct folio *folio, nid_t nid,
> unsigned int old_flag = 0;
>
> if (reset)
> - memset(rn, 0, F2FS_BLKSIZE);
> + memset(rn, 0, F2FS_BLKSIZE(F2FS_F_SB(folio)));
> else
> old_flag = le32_to_cpu(footer->flag);
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index f58b26c84b3a..f2641a6080ae 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -1316,7 +1316,8 @@ static void __submit_zone_reset_cmd(struct f2fs_sb_info *sbi,
> submit_bio(bio);
>
> atomic_inc(&dcc->issued_discard);
> - f2fs_update_iostat(sbi, NULL, FS_ZONE_RESET_IO, dc->di.len * F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, NULL, FS_ZONE_RESET_IO,
> + dc->di.len * F2FS_BLKSIZE(sbi));
> }
> #endif
>
> @@ -1419,7 +1420,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
>
> atomic_inc(&dcc->issued_discard);
>
> - f2fs_update_iostat(sbi, NULL, FS_DISCARD_IO, len * F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, NULL, FS_DISCARD_IO,
> + len * F2FS_BLKSIZE(sbi));
>
> lstart += len;
> start += len;
> @@ -2797,7 +2799,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
> if (IS_ERR(folio))
> return;
>
> - memcpy(folio_address(folio), src, PAGE_SIZE);
> + memcpy(folio_address(folio), src, F2FS_BLKSIZE(sbi));
> folio_mark_dirty(folio);
> f2fs_folio_put(folio, true);
> }
> @@ -4152,7 +4154,7 @@ void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio,
> f2fs_submit_page_write(&fio);
>
> stat_inc_meta_count(sbi, folio->index);
> - f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE(sbi));
> }
>
> void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio)
> @@ -4162,7 +4164,8 @@ void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio)
> set_summary(&sum, nid, 0, 0);
> do_write_page(&sum, fio);
>
> - f2fs_update_iostat(fio->sbi, NULL, fio->io_type, F2FS_BLKSIZE);
> + f2fs_update_iostat(fio->sbi, NULL, fio->io_type,
> + F2FS_BLKSIZE(fio->sbi));
> }
>
> void f2fs_outplace_write_data(struct dnode_of_data *dn,
> @@ -4178,7 +4181,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn,
> do_write_page(&sum, fio);
> f2fs_update_data_blkaddr(dn, fio->new_blkaddr);
>
> - f2fs_update_iostat(sbi, dn->inode, fio->io_type, F2FS_BLKSIZE);
> + f2fs_update_iostat(sbi, dn->inode, fio->io_type,
> + F2FS_BLKSIZE(sbi));
> }
>
> int f2fs_inplace_write_data(struct f2fs_io_info *fio)
> @@ -4220,7 +4224,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
> f2fs_update_device_state(fio->sbi, fio->ino,
> fio->new_blkaddr, 1);
> f2fs_update_iostat(fio->sbi, fio_inode(fio),
> - fio->io_type, F2FS_BLKSIZE);
> + fio->io_type, F2FS_BLKSIZE(fio->sbi));
> }
>
> return err;
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index 2275404e769c..2c85c085961b 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -116,7 +116,7 @@ f2fs_start_segno(struct f2fs_sb_info *sbi, unsigned int segno)
>
> #define SECTOR_FROM_BLOCK(sbi, blk_addr) \
> (((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK(sbi))
> -#define SECTOR_TO_BLOCK(sbi, sectors) \
> +#define SECTOR_TO_BLOCK(sbi, sectors) \
Unneeded change.
> ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK(sbi))
>
> /*
> @@ -432,7 +432,7 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi,
> int i;
>
> raw_sit = folio_address(folio);
> - memset(raw_sit, 0, PAGE_SIZE);
> + memset(raw_sit, 0, F2FS_BLKSIZE(sbi));
> for (i = 0; i < end - start; i++) {
> rs = &raw_sit->entries[i];
> se = get_seg_entry(sbi, start + i);
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index b962c14cbcc1..ca6403a0ed88 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1610,7 +1610,7 @@ static int f2fs_check_opt_consistency(struct fs_context *fc,
> return -EINVAL;
> }
> min_size = MIN_INLINE_XATTR_SIZE;
> - max_size = MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_BLKSIZE);
> + max_size = MAX_INLINE_XATTR_SIZE_FOR_BLOCKSIZE(F2FS_BLKSIZE(sbi));
>
> if (F2FS_OPTION(sbi).inline_xattr_size < min_size ||
> F2FS_OPTION(sbi).inline_xattr_size > max_size) {
> @@ -4079,10 +4079,10 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
> }
>
> /* only support block_size equals to PAGE_SIZE */
> - if (le32_to_cpu(raw_super->log_blocksize) != F2FS_BLKSIZE_BITS) {
> + if (le32_to_cpu(raw_super->log_blocksize) != PAGE_SHIFT) {
> f2fs_info(sbi, "Invalid log_blocksize (%u), supports only %u",
> le32_to_cpu(raw_super->log_blocksize),
> - F2FS_BLKSIZE_BITS);
> + PAGE_SHIFT);
> return -EFSCORRUPTED;
> }
>
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 811e350a1430..aaca9ed9b169 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -1871,8 +1871,8 @@ static int __maybe_unused disk_map_seq_show(struct seq_file *seq,
> struct f2fs_sb_info *sbi = F2FS_SB(sb);
> int i;
>
> - seq_printf(seq, "Address Layout : %5luB Block address (# of Segments)\n",
> - F2FS_BLKSIZE);
> + seq_printf(seq, "Address Layout : %5uB Block address (# of Segments)\n",
> + F2FS_BLKSIZE(sbi));
> seq_printf(seq, " SB : %12s\n", "0/1024B");
> seq_printf(seq, " seg0_blkaddr : 0x%010x\n", SEG0_BLKADDR(sbi));
> seq_printf(seq, " Checkpoint : 0x%010x (%10d)\n",
> @@ -1889,13 +1889,13 @@ static int __maybe_unused disk_map_seq_show(struct seq_file *seq,
> seq_printf(seq, " Main : 0x%010x (%10d)\n",
> SM_I(sbi)->main_blkaddr,
> le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_main));
> - seq_printf(seq, " Block size : %12lu KB\n", F2FS_BLKSIZE >> 10);
> + seq_printf(seq, " Block size : %12u KB\n", F2FS_BLKSIZE(sbi) >> 10);
> seq_printf(seq, " Segment size : %12d MB\n",
> - (BLKS_PER_SEG(sbi) << (F2FS_BLKSIZE_BITS - 10)) >> 10);
> + (BLKS_PER_SEG(sbi) << (F2FS_BLKSIZE_BITS(sbi) - 10)) >> 10);
> seq_printf(seq, " Segs/Sections : %12d\n",
> SEGS_PER_SEC(sbi));
> seq_printf(seq, " Section size : %12d MB\n",
> - (BLKS_PER_SEC(sbi) << (F2FS_BLKSIZE_BITS - 10)) >> 10);
> + (BLKS_PER_SEC(sbi) << (F2FS_BLKSIZE_BITS(sbi) - 10)) >> 10);
> seq_printf(seq, " # of Sections : %12d\n",
> le32_to_cpu(F2FS_RAW_SUPER(sbi)->section_count));
>
> diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
> index 99c863513725..98059e583b09 100644
> --- a/fs/f2fs/xattr.c
> +++ b/fs/f2fs/xattr.c
> @@ -850,4 +850,4 @@ int __init f2fs_init_xattr_cache(void)
> void f2fs_destroy_xattr_cache(void)
> {
> kmem_cache_destroy(inline_xattr_slab);
> -}
> \ No newline at end of file
> +}
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index f622d26f37a7..957bb713ff24 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -14,12 +14,9 @@
> #define F2FS_SUPER_OFFSET 1024 /* byte-size offset */
> #define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */
> #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */
> -#define F2FS_LOG_SECTORS_PER_BLOCK(sbi) ((sbi)->log_blocksize - 9) /* log number for sector/blk */
> #define F2FS_MIN_LOG_BLOCKSIZE 12
> #define F2FS_MIN_BLKSIZE 4096UL
> -#define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */
> #define F2FS_MAX_BLKSIZE PAGE_SIZE
> -#define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */
> #define F2FS_MAX_EXTENSION 64 /* # of extension entries */
> #define F2FS_EXTENSION_LEN 8 /* max size of extension */
>
> @@ -27,15 +24,19 @@
> #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */
> #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */
>
> -#define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1)
> +#define F2FS_BLKSIZE(sbi) ((sbi)->blocksize)
> +#define F2FS_BLKSIZE_BITS(sbi) ((sbi)->log_blocksize)
> +#define F2FS_BLKSIZE_MASK(sbi) (F2FS_BLKSIZE(sbi) - 1)
> +#define F2FS_LOG_SECTORS_PER_BLOCK(sbi) (F2FS_BLKSIZE_BITS(sbi) - 9)
> +#define F2FS_BLKS_PER_PAGE(sbi) (PAGE_SIZE / F2FS_BLKSIZE(sbi))
> #define F2FS_BYTES_TO_BLK(sbi, bytes) \
> - ((unsigned long long)(bytes) >> (sbi)->log_blocksize)
> + ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS(sbi))
> #define F2FS_BLK_TO_BYTES(sbi, blk) \
> - ((unsigned long long)(blk) << (sbi)->log_blocksize)
> + ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS(sbi))
> #define F2FS_BLK_END_BYTES(sbi, blk) \
> (F2FS_BLK_TO_BYTES(sbi, (blk) + 1) - 1)
> #define F2FS_BLK_ALIGN(sbi, x) \
> - DIV_ROUND_UP_ULL((x), (sbi)->blocksize)
> + DIV_ROUND_UP_ULL((x), F2FS_BLKSIZE(sbi))
>
> /* 0, 1(node nid), 2(meta nid) are reserved node id */
> #define F2FS_RESERVED_NODE_NUM 3
> @@ -221,7 +222,6 @@ struct f2fs_checkpoint {
> unsigned char sit_nat_version_bitmap[];
> } __packed;
>
> -#define CP_CHKSUM_OFFSET (F2FS_BLKSIZE - sizeof(__le32)) /* default chksum offset in checkpoint */
> #define CP_MIN_CHKSUM_OFFSET \
> (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap))
>
> @@ -271,7 +271,7 @@ struct node_footer {
> } __packed;
>
> /* Address Pointers in an Inode */
> -#define DEF_ADDRS_PER_INODE ((F2FS_BLKSIZE - OFFSET_OF_END_OF_I_EXT \
> +#define DEF_ADDRS_PER_INODE ((PAGE_SIZE - OFFSET_OF_END_OF_I_EXT \
Why we change to use PAGE_SIZE?
> - SIZE_OF_I_NID \
> - sizeof(struct node_footer)) / sizeof(__le32))
> #define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \
> @@ -279,10 +279,10 @@ struct node_footer {
> #define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */
> #define ADDRS_PER_INODE(inode) addrs_per_page(inode, true)
> /* Address Pointers in a Direct Block */
> -#define DEF_ADDRS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32))
> +#define DEF_ADDRS_PER_BLOCK ((PAGE_SIZE - sizeof(struct node_footer)) / sizeof(__le32))
Ditto,
> #define ADDRS_PER_BLOCK(inode) addrs_per_page(inode, false)
> /* Node IDs in an Indirect Block */
> -#define NIDS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32))
> +#define NIDS_PER_BLOCK ((PAGE_SIZE - sizeof(struct node_footer)) / sizeof(__le32))
Ditto,
Thanks,
>
> #define ADDRS_PER_PAGE(folio, inode) (addrs_per_page(inode, IS_INODE(folio)))
>
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 30+ messages in thread
* [f2fs-dev] [PATCH v7 11/11] f2fs: describe node tree geometry dynamically
2026-08-31 22:05 [f2fs-dev] [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
` (9 preceding siblings ...)
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 10/11] f2fs: parameterize block size and mask macros Kelvin Zhang
@ 2026-08-31 22:08 ` Kelvin Zhang
10 siblings, 0 replies; 30+ messages in thread
From: Kelvin Zhang @ 2026-08-31 22:08 UTC (permalink / raw)
To: linux-f2fs-devel; +Cc: jaegeuk, linux-kernel
The file indexing tree boundaries separating direct, indirect, and
double-indirect node blocks depend on the number of data block addresses
and node IDs contained in each node block.
Parameterize index boundary macros (NODE_DIR1_BLOCK,
NODE_DIR2_BLOCK, NODE_IND1_BLOCK, NODE_IND2_BLOCK, and NODE_DIND_BLOCK) and
address capacity helpers (DEF_ADDRS_PER_BLOCK, NIDS_PER_BLOCK,
cur_addrs_per_inode, addrs_per_page, and addrs_per_folio) with
struct f2fs_sb_info *sbi.
Update file mapping, block allocation, truncate, garbage collection,
and recovery paths to compute indexing tree offsets from the runtime
geometry.
Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com>
---
fs/f2fs/f2fs.h | 19 +++++++++--
fs/f2fs/gc.c | 10 +++---
fs/f2fs/node.c | 74 +++++++++++++++++++++--------------------
fs/f2fs/node.h | 18 ++++++----
fs/f2fs/super.c | 6 ++--
include/linux/f2fs_fs.h | 18 ++--------
6 files changed, 77 insertions(+), 68 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index f83cdab66f54..e1f33ac24c6e 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -602,8 +602,12 @@ static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i)
#define DEF_INLINE_RESERVED_SIZE 1
static inline int get_extra_isize(struct inode *inode);
static inline int get_inline_xattr_addrs(struct inode *inode);
+static inline unsigned int cur_addrs_per_inode(struct inode *inode)
+{
+ return DEF_ADDRS_PER_INODE(inode) - get_extra_isize(inode);
+}
#define MAX_INLINE_DATA(inode) (sizeof(__le32) * \
- (CUR_ADDRS_PER_INODE(inode) - \
+ (cur_addrs_per_inode(inode) - \
get_inline_xattr_addrs(inode) - \
DEF_INLINE_RESERVED_SIZE))
@@ -2257,11 +2261,19 @@ static inline struct f2fs_sb_info *F2FS_P_SB(struct page *page)
#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block)
#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block)
#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode)
+#define DEF_ADDRS_PER_BLOCK(sbi) ((sbi)->addrs_per_block)
+#define NIDS_PER_BLOCK(sbi) ((sbi)->nids_per_block)
#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block)
#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \
F2FS_ORPHANS_PER_BLOCK(sbi))
#define CP_CHKSUM_OFFSET(sbi) (F2FS_BLKSIZE(sbi) - sizeof(__le32))
+#define NODE_DIR1_BLOCK(sbi) (DEF_ADDRS_PER_INODE_SBI(sbi) + 1)
+#define NODE_DIR2_BLOCK(sbi) (DEF_ADDRS_PER_INODE_SBI(sbi) + 2)
+#define NODE_IND1_BLOCK(sbi) (DEF_ADDRS_PER_INODE_SBI(sbi) + 3)
+#define NODE_IND2_BLOCK(sbi) (DEF_ADDRS_PER_INODE_SBI(sbi) + 4)
+#define NODE_DIND_BLOCK(sbi) (DEF_ADDRS_PER_INODE_SBI(sbi) + 5)
+
static inline struct f2fs_orphan_footer *
f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi)
{
@@ -3650,8 +3662,9 @@ static inline bool f2fs_need_compress_data(struct inode *inode)
static inline unsigned int addrs_per_page(struct inode *inode,
bool is_inode)
{
- unsigned int addrs = is_inode ? (CUR_ADDRS_PER_INODE(inode) -
- get_inline_xattr_addrs(inode)) : DEF_ADDRS_PER_BLOCK;
+ unsigned int addrs = is_inode ? (cur_addrs_per_inode(inode) -
+ get_inline_xattr_addrs(inode)) :
+ DEF_ADDRS_PER_BLOCK(F2FS_I_SB(inode));
if (f2fs_compressed_file(inode))
return ALIGN_DOWN(addrs, F2FS_I(inode)->i_cluster_size);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 299d5310e597..b17e7ce58f2c 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1123,7 +1123,8 @@ static int gc_node_segment(struct f2fs_sb_info *sbi,
*/
block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
{
- unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ unsigned int indirect_blks = 2 * NIDS_PER_BLOCK(sbi) + 4;
unsigned int bidx;
if (node_ofs == 0)
@@ -1132,11 +1133,12 @@ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
if (node_ofs <= 2) {
bidx = node_ofs - 1;
} else if (node_ofs <= indirect_blks) {
- int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
+ int dec = (node_ofs - 4) / (NIDS_PER_BLOCK(sbi) + 1);
bidx = node_ofs - 2 - dec;
} else {
- int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
+ int dec = (node_ofs - indirect_blks - 3) /
+ (NIDS_PER_BLOCK(sbi) + 1);
bidx = node_ofs - 5 - dec;
}
@@ -1179,7 +1181,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
max_addrs = DEF_ADDRS_PER_INODE_SBI(sbi);
} else {
base = 0;
- max_addrs = DEF_ADDRS_PER_BLOCK;
+ max_addrs = DEF_ADDRS_PER_BLOCK(sbi);
}
if (base + ofs_in_node >= max_addrs) {
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 8d16715a3aae..68a95d703c4a 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -691,7 +691,7 @@ static void f2fs_ra_node_pages(struct folio *parent, int start, int n)
/* Then, try readahead for siblings of the desired node */
end = start + n;
- end = min(end, (int)NIDS_PER_BLOCK);
+ end = min_t(int, end, NIDS_PER_BLOCK(sbi));
for (i = start; i < end; i++) {
nid = get_nid(parent, i, false);
f2fs_ra_node_page(sbi, nid);
@@ -702,9 +702,11 @@ static void f2fs_ra_node_pages(struct folio *parent, int start, int n)
pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
const long direct_index = ADDRS_PER_INODE(dn->inode);
const long direct_blks = ADDRS_PER_BLOCK(dn->inode);
- const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK;
+ const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) *
+ NIDS_PER_BLOCK(sbi);
unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode);
int cur_level = dn->cur_level;
int max_level = dn->max_level;
@@ -714,7 +716,7 @@ pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
return pgofs + 1;
while (max_level-- > cur_level)
- skipped_unit *= NIDS_PER_BLOCK;
+ skipped_unit *= NIDS_PER_BLOCK(sbi);
switch (dn->max_level) {
case 3:
@@ -740,11 +742,13 @@ pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
static int get_node_path(struct inode *inode, long block,
int offset[4], unsigned int noffset[4])
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
const long direct_index = ADDRS_PER_INODE(inode);
const long direct_blks = ADDRS_PER_BLOCK(inode);
- const long dptrs_per_blk = NIDS_PER_BLOCK;
- const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK;
- const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
+ const long dptrs_per_blk = NIDS_PER_BLOCK(sbi);
+ const long indirect_blks = ADDRS_PER_BLOCK(inode) *
+ NIDS_PER_BLOCK(sbi);
+ const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK(sbi);
int n = 0;
int level = 0;
@@ -756,7 +760,7 @@ static int get_node_path(struct inode *inode, long block,
}
block -= direct_index;
if (block < direct_blks) {
- offset[n++] = NODE_DIR1_BLOCK;
+ offset[n++] = NODE_DIR1_BLOCK(sbi);
noffset[n] = 1;
offset[n] = block;
level = 1;
@@ -764,7 +768,7 @@ static int get_node_path(struct inode *inode, long block,
}
block -= direct_blks;
if (block < direct_blks) {
- offset[n++] = NODE_DIR2_BLOCK;
+ offset[n++] = NODE_DIR2_BLOCK(sbi);
noffset[n] = 2;
offset[n] = block;
level = 1;
@@ -772,7 +776,7 @@ static int get_node_path(struct inode *inode, long block,
}
block -= direct_blks;
if (block < indirect_blks) {
- offset[n++] = NODE_IND1_BLOCK;
+ offset[n++] = NODE_IND1_BLOCK(sbi);
noffset[n] = 3;
offset[n++] = block / direct_blks;
noffset[n] = 4 + offset[n - 1];
@@ -782,7 +786,7 @@ static int get_node_path(struct inode *inode, long block,
}
block -= indirect_blks;
if (block < indirect_blks) {
- offset[n++] = NODE_IND2_BLOCK;
+ offset[n++] = NODE_IND2_BLOCK(sbi);
noffset[n] = 4 + dptrs_per_blk;
offset[n++] = block / direct_blks;
noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
@@ -792,7 +796,7 @@ static int get_node_path(struct inode *inode, long block,
}
block -= indirect_blks;
if (block < dindirect_blks) {
- offset[n++] = NODE_DIND_BLOCK;
+ offset[n++] = NODE_DIND_BLOCK(sbi);
noffset[n] = 5 + (dptrs_per_blk * 2);
offset[n++] = block / indirect_blks;
noffset[n] = 6 + (dptrs_per_blk * 2) +
@@ -1054,6 +1058,7 @@ static int truncate_dnode(struct dnode_of_data *dn)
static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
int ofs, int depth)
{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
struct dnode_of_data rdn = *dn;
struct folio *folio;
struct f2fs_node *rn;
@@ -1063,7 +1068,7 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
int i, ret;
if (dn->nid == 0)
- return NIDS_PER_BLOCK + 1;
+ return NIDS_PER_BLOCK(sbi) + 1;
trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr);
@@ -1074,11 +1079,11 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
return PTR_ERR(folio);
}
- f2fs_ra_node_pages(folio, ofs, NIDS_PER_BLOCK);
+ f2fs_ra_node_pages(folio, ofs, NIDS_PER_BLOCK(sbi));
rn = F2FS_NODE(folio);
if (depth < 3) {
- for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
+ for (i = ofs; i < NIDS_PER_BLOCK(sbi); i++, freed++) {
child_nid = le32_to_cpu(rn->in.nid[i]);
if (child_nid == 0)
continue;
@@ -1090,16 +1095,16 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
dn->node_changed = true;
}
} else {
- child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
- for (i = ofs; i < NIDS_PER_BLOCK; i++) {
+ child_nofs = nofs + ofs * (NIDS_PER_BLOCK(sbi) + 1) + 1;
+ for (i = ofs; i < NIDS_PER_BLOCK(sbi); i++) {
child_nid = le32_to_cpu(rn->in.nid[i]);
if (child_nid == 0) {
- child_nofs += NIDS_PER_BLOCK + 1;
+ child_nofs += NIDS_PER_BLOCK(sbi) + 1;
continue;
}
rdn.nid = child_nid;
ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
- if (ret == (NIDS_PER_BLOCK + 1)) {
+ if (ret == (NIDS_PER_BLOCK(sbi) + 1)) {
if (set_nid(folio, i, 0, false))
dn->node_changed = true;
child_nofs += ret;
@@ -1156,10 +1161,12 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
nid[i + 1] = get_nid(folios[i], offset[i + 1], false);
}
- f2fs_ra_node_pages(folios[idx], offset[idx + 1], NIDS_PER_BLOCK);
+ f2fs_ra_node_pages(folios[idx], offset[idx + 1],
+ NIDS_PER_BLOCK(F2FS_I_SB(dn->inode)));
/* free direct nodes linked to a partial indirect node */
- for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) {
+ for (i = offset[idx + 1];
+ i < NIDS_PER_BLOCK(F2FS_I_SB(dn->inode)); i++) {
child_nid = get_nid(folios[idx], i, false);
if (!child_nid)
continue;
@@ -1193,7 +1200,9 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
}
/*
- * All the block addresses of data and nodes should be nullified.
+ * All the node blocks actually belong to the inode will be released.
+ * If the level is 0, we will simply truncate the dnode,
+ * or else we should do dynamic truncate for the node pointers with the depth.
*/
int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from)
{
@@ -1240,10 +1249,10 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from)
err = truncate_partial_nodes(&dn, offset, level);
if (err < 0 && err != -ENOENT)
goto fail;
- nofs += 1 + NIDS_PER_BLOCK;
+ nofs += 1 + NIDS_PER_BLOCK(sbi);
break;
case 3:
- nofs = 5 + 2 * NIDS_PER_BLOCK;
+ nofs = 5 + 2 * NIDS_PER_BLOCK(sbi);
if (!offset[level - 1])
goto skip_partial;
err = truncate_partial_nodes(&dn, offset, level);
@@ -1257,23 +1266,16 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from)
skip_partial:
while (cont) {
dn.nid = get_nid(folio, offset[0], true);
- switch (offset[0]) {
- case NODE_DIR1_BLOCK:
- case NODE_DIR2_BLOCK:
+ if (offset[0] == NODE_DIR1_BLOCK(sbi) ||
+ offset[0] == NODE_DIR2_BLOCK(sbi)) {
err = truncate_dnode(&dn);
- break;
-
- case NODE_IND1_BLOCK:
- case NODE_IND2_BLOCK:
+ } else if (offset[0] == NODE_IND1_BLOCK(sbi) ||
+ offset[0] == NODE_IND2_BLOCK(sbi)) {
err = truncate_nodes(&dn, nofs, offset[1], 2);
- break;
-
- case NODE_DIND_BLOCK:
+ } else if (offset[0] == NODE_DIND_BLOCK(sbi)) {
err = truncate_nodes(&dn, nofs, offset[1], 3);
cont = 0;
- break;
-
- default:
+ } else {
BUG();
}
if (err == -ENOENT) {
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 32125f8fc753..66898288b961 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -354,17 +354,18 @@ static inline bool is_recoverable_dnode(const struct folio *folio)
*/
static inline bool IS_DNODE(const struct folio *node_folio)
{
+ struct f2fs_sb_info *sbi = F2FS_F_SB(node_folio);
unsigned int ofs = ofs_of_node(node_folio);
if (f2fs_has_xattr_block(ofs))
return true;
- if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
- ofs == 5 + 2 * NIDS_PER_BLOCK)
+ if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK(sbi) ||
+ ofs == 5 + 2 * NIDS_PER_BLOCK(sbi))
return false;
- if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
- ofs -= 6 + 2 * NIDS_PER_BLOCK;
- if (!((long int)ofs % (NIDS_PER_BLOCK + 1)))
+ if (ofs >= 6 + 2 * NIDS_PER_BLOCK(sbi)) {
+ ofs -= 6 + 2 * NIDS_PER_BLOCK(sbi);
+ if (!((long)ofs % (NIDS_PER_BLOCK(sbi) + 1)))
return false;
}
return true;
@@ -372,13 +373,15 @@ static inline bool IS_DNODE(const struct folio *node_folio)
static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
{
+ struct f2fs_sb_info *sbi = F2FS_F_SB(folio);
struct f2fs_node *rn = F2FS_NODE(folio);
__le32 *inode_nids = F2FS_INODE_NIDS(folio);
f2fs_folio_wait_writeback(folio, NODE, true, true);
if (i)
- inode_nids[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
+ inode_nids[off - NODE_DIR1_BLOCK(sbi)] =
+ cpu_to_le32(nid);
else
rn->in.nid[off] = cpu_to_le32(nid);
return folio_mark_dirty(folio);
@@ -388,9 +391,10 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i)
{
struct f2fs_node *rn = F2FS_NODE(folio);
const __le32 *inode_nids = F2FS_INODE_NIDS(folio);
+ int nid_index = off - NODE_DIR1_BLOCK(F2FS_F_SB(folio));
if (i)
- return le32_to_cpu(inode_nids[off - NODE_DIR1_BLOCK]);
+ return le32_to_cpu(inode_nids[nid_index]);
return le32_to_cpu(rn->in.nid[off]);
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index ca6403a0ed88..f6c492f76f0c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3899,17 +3899,17 @@ loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode)
if (inode && f2fs_compressed_file(inode))
leaf_count = ADDRS_PER_BLOCK(inode);
else
- leaf_count = DEF_ADDRS_PER_BLOCK;
+ leaf_count = DEF_ADDRS_PER_BLOCK(sbi);
/* two direct node blocks */
result += (leaf_count * 2);
/* two indirect node blocks */
- leaf_count *= NIDS_PER_BLOCK;
+ leaf_count *= NIDS_PER_BLOCK(sbi);
result += (leaf_count * 2);
/* one double indirect node block */
- leaf_count *= NIDS_PER_BLOCK;
+ leaf_count *= NIDS_PER_BLOCK(sbi);
result += leaf_count;
/*
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 957bb713ff24..e43ac6509550 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -271,27 +271,15 @@ struct node_footer {
} __packed;
/* Address Pointers in an Inode */
-#define DEF_ADDRS_PER_INODE ((PAGE_SIZE - OFFSET_OF_END_OF_I_EXT \
- - SIZE_OF_I_NID \
- - sizeof(struct node_footer)) / sizeof(__le32))
-#define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \
- get_extra_isize(inode))
+#define DEF_ADDRS_PER_INODE(inode) \
+ ((i_blocksize(inode) - OFFSET_OF_END_OF_I_EXT - SIZE_OF_I_NID - \
+ sizeof(struct node_footer)) / sizeof(__le32))
#define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */
#define ADDRS_PER_INODE(inode) addrs_per_page(inode, true)
/* Address Pointers in a Direct Block */
-#define DEF_ADDRS_PER_BLOCK ((PAGE_SIZE - sizeof(struct node_footer)) / sizeof(__le32))
#define ADDRS_PER_BLOCK(inode) addrs_per_page(inode, false)
-/* Node IDs in an Indirect Block */
-#define NIDS_PER_BLOCK ((PAGE_SIZE - sizeof(struct node_footer)) / sizeof(__le32))
-
#define ADDRS_PER_PAGE(folio, inode) (addrs_per_page(inode, IS_INODE(folio)))
-#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1)
-#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2)
-#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3)
-#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4)
-#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5)
-
#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */
#define F2FS_INLINE_DATA 0x02 /* file inline data flag */
#define F2FS_INLINE_DENTRY 0x04 /* file inline dentry flag */
--
2.53.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 30+ messages in thread