Linux-f2fs-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: Kelvin Zhang <zhangxp1998@gmail.com>,
	linux-f2fs-devel@lists.sourceforge.net
Cc: jaegeuk@kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [f2fs-dev] [PATCH v7 04/11] f2fs: describe orphan block layout dynamically
Date: Tue, 1 Sep 2026 19:34:55 +0800	[thread overview]
Message-ID: <47f696a1-1efc-4e8e-90fe-22e1ea2feaea@kernel.org> (raw)
In-Reply-To: <f05b57691fdc4c186b08010314f8085aeb868e04.1788213716.git.zhangxp1998@gmail.com>

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

  reply	other threads:[~2026-09-01 11:35 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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-09-01  0:48   ` Chao Yu via Linux-f2fs-devel
2026-09-01 16:38     ` Xinping 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 ` [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
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 [this message]
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 05/11] f2fs: describe dentry " Kelvin Zhang
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-01 16:38     ` Xinping Zhang
2026-09-02 23:52   ` Xinping Zhang
2026-09-03  1:55     ` Chao Yu via Linux-f2fs-devel
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
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 08/11] f2fs: parameterize sector conversion macros Kelvin Zhang
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
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
2026-08-31 22:08 ` [f2fs-dev] [PATCH v7 11/11] f2fs: describe node tree geometry dynamically Kelvin Zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47f696a1-1efc-4e8e-90fe-22e1ea2feaea@kernel.org \
    --to=linux-f2fs-devel@lists.sourceforge.net \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=zhangxp1998@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox