From: Kelvin Zhang <zhangxp1998@gmail.com>
To: linux-f2fs-devel@lists.sourceforge.net
Cc: Jaegeuk Kim <jaegeuk@kernel.org>, Chao Yu <chao@kernel.org>,
Daeho Jeong <daeho43@gmail.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH v9 07/11] f2fs: describe xattr block layout dynamically
Date: Thu, 3 Sep 2026 16:56:19 -0700 [thread overview]
Message-ID: <c7005ebefcad46d6a0bf3b0653fbd3692b86a360.1788479509.git.zhangxp1998@gmail.com> (raw)
In-Reply-To: <cover.1788479509.git.zhangxp1998@gmail.com>
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 | 7 ++++---
fs/f2fs/node.c | 2 +-
fs/f2fs/super.c | 17 +++++++++++++++--
fs/f2fs/xattr.c | 8 +++++---
fs/f2fs/xattr.h | 11 ++++++-----
include/linux/f2fs_fs.h | 3 +++
6 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index fda9ee3bfc61..79c0a1301996 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -337,12 +337,13 @@ 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(i_blocksize(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",
+ f2fs_warn(sbi, "%s: inode (ino=%llx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %zu",
__func__, inode->i_ino, fi->i_inline_xattr_size,
- MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE);
+ MIN_INLINE_XATTR_SIZE,
+ (size_t)MAX_INLINE_XATTR_SIZE(i_blocksize(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 c1d76674ab7c..4c95229ac3f1 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(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(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(sbi->blocksize);
+
+ 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 7cd7ce58334b..75beab2d1ee3 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -71,21 +71,22 @@ 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 \
- (F2FS_DEF_ADDRS_PER_INODE(F2FS_BLKSIZE) - \
+#define MAX_INLINE_XATTR_SIZE(blocksize) \
+ (F2FS_DEF_ADDRS_PER_INODE(blocksize) - \
F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \
DEF_INLINE_RESERVED_SIZE - \
MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index bec31591b398..e98bff846b23 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -15,7 +15,10 @@
#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 */
#define F2FS_MAX_EXTENSION 64 /* # of extension entries */
#define F2FS_EXTENSION_LEN 8 /* max size of extension */
--
2.53.0
next prev parent reply other threads:[~2026-09-03 23:56 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 23:54 [PATCH v9 00/11] f2fs: prepare metadata layouts for runtime block sizes Kelvin Zhang
2026-09-03 23:54 ` [PATCH v9 01/11] f2fs: initialize sb_info early in f2fs_fill_super Kelvin Zhang
2026-09-04 1:48 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 02/11] f2fs: describe SIT block layout dynamically Kelvin Zhang
2026-09-04 1:54 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 03/11] f2fs: describe NAT " Kelvin Zhang
2026-09-04 1:55 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 04/11] f2fs: describe orphan " Kelvin Zhang
2026-09-04 1:56 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 05/11] f2fs: describe dentry " Kelvin Zhang
2026-09-04 1:58 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 06/11] f2fs: describe {i,d,id}node " Kelvin Zhang
2026-09-04 2:08 ` Chao Yu
2026-09-03 23:56 ` Kelvin Zhang [this message]
2026-09-04 2:15 ` [PATCH v9 07/11] f2fs: describe xattr " Chao Yu
2026-09-03 23:56 ` [PATCH v9 08/11] f2fs: parameterize sector conversion macros Kelvin Zhang
2026-09-04 2:16 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 09/11] f2fs: parameterize byte and block " Kelvin Zhang
2026-09-04 2:17 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 10/11] f2fs: describe node tree geometry dynamically Kelvin Zhang
2026-09-04 2:18 ` Chao Yu
2026-09-03 23:56 ` [PATCH v9 11/11] f2fs: parameterize block size and mask macros Kelvin Zhang
2026-09-04 2:20 ` Chao Yu
2026-09-08 20:00 ` [f2fs-dev] [PATCH v9 00/11] f2fs: prepare metadata layouts for runtime block sizes patchwork-bot+f2fs
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=c7005ebefcad46d6a0bf3b0653fbd3692b86a360.1788479509.git.zhangxp1998@gmail.com \
--to=zhangxp1998@gmail.com \
--cc=chao@kernel.org \
--cc=daeho43@gmail.com \
--cc=jaegeuk@kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/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®