mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daeho Jeong <daeho43@gmail.com>
To: Kelvin Zhang <zhangxp1998@gmail.com>
Cc: linux-f2fs-devel@lists.sourceforge.net, jaegeuk@kernel.org,
	 linux-kernel@vger.kernel.org
Subject: Re: [f2fs-dev] [PATCH v7 07/11] f2fs: describe xattr block layout dynamically
Date: Mon, 31 Aug 2026 18:10:01 -0700	[thread overview]
Message-ID: <CACOAw_ymXA1ytnL0W91B-L2OuuBzz2PRj2tVgZw332kTvO2nZw@mail.gmail.com> (raw)
In-Reply-To: <65b4a84c4504019ea6b208f424917f9df4eed2dd.1788213716.git.zhangxp1998@gmail.com>

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

  reply	other threads:[~2026-09-01  1:10 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 22:05 [PATCH v7 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
2026-08-31 22:05 ` [PATCH v7 01/11] f2fs: initialize sb_info early in f2fs_fill_super Kelvin Zhang
2026-09-01  0:48   ` Chao Yu
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [PATCH v7 02/11] f2fs: describe SIT block layout dynamically Kelvin Zhang
2026-08-31 22:08 ` [PATCH v7 03/11] f2fs: describe NAT " Kelvin Zhang
2026-09-01  0:38   ` [f2fs-dev] " Daeho Jeong
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [PATCH v7 04/11] f2fs: describe orphan " Kelvin Zhang
2026-09-01 11:34   ` Chao Yu
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [PATCH v7 05/11] f2fs: describe dentry " Kelvin Zhang
2026-08-31 22:08 ` [PATCH v7 06/11] f2fs: describe {i,d,id}node " Kelvin Zhang
2026-09-01  0:56   ` [f2fs-dev] [PATCH v7 06/11] f2fs: describe {i, d, id}node " Daeho Jeong
2026-09-01 16:38     ` Xinping Zhang
2026-09-01 11:48   ` [PATCH v7 06/11] f2fs: describe {i,d,id}node " Chao Yu
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [PATCH v7 07/11] f2fs: describe xattr " Kelvin Zhang
2026-09-01  1:10   ` Daeho Jeong [this message]
2026-09-01 16:38     ` [f2fs-dev] " Xinping Zhang
2026-08-31 22:08 ` [PATCH v7 08/11] f2fs: parameterize sector conversion macros Kelvin Zhang
2026-08-31 22:08 ` [PATCH v7 09/11] f2fs: parameterize byte and block " Kelvin Zhang
2026-09-01  1:14   ` [f2fs-dev] " Daeho Jeong
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [PATCH v7 10/11] f2fs: parameterize block size and mask macros Kelvin Zhang
2026-09-01 12:03   ` Chao Yu
2026-09-01 16:38     ` Xinping Zhang
2026-08-31 22:08 ` [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=CACOAw_ymXA1ytnL0W91B-L2OuuBzz2PRj2tVgZw332kTvO2nZw@mail.gmail.com \
    --to=daeho43@gmail.com \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --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

all inboxes | Powered by JetHome®