From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A1D1B397347 for ; Thu, 3 Sep 2026 23:11:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788477110; cv=none; b=MFGjhJWIoCd3OQyJ05GRuRV4RgfadXntaacw30sjrRHgeewRyGNmqfCXWIbPkLMRmbMRB40j7cljffZnHFhNMtH3dTtb2ROHRzpQ6fwvYNprOXwVaUWDlS71pv9SK1j8yhLNBMDKefpEJeWI/G2uPSXoV2dno6AZAjNZO0QPLI8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788477110; c=relaxed/simple; bh=Sz1G0zlz4u5afeRzBLtAp00tEeH67JMRrxu/MardOTM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ifPYLpwEqWuTG5+VLGhJSBerTFbEp5MigmElbYLNDyOCZ0fyNraCS7mBbOiVh/5EQ+oYF4sUtsfeMRFnMkPLv3nIwmXJMVi5LeH8rhRAykE3PGrYEnqv29yNPNlbhoPU4vgTg6cexD9Cms3rqOt3jMhMZ5nKlhYcreKoxByiYuA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dfngvV11; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dfngvV11" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-cc1cc1b42b5so509898a12.2 for ; Thu, 03 Sep 2026 16:11:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788477108; x=1789081908; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=oI0SdKfcZHgfXMNdZMI4amVSwVJWRyNSiFrZzvdLQQc=; b=dfngvV11bLAtlx46kv6rfr4/Pubf2UJcZFd4wnrPki0K8p1FrWxQnrpw7f5cl/ecCV SbgWpnFPc4j6QEuhmt4zPhNKU6cfdzbB7vReJ2q4mhuPJQn05WrDVSt9GBQoglKnpp8f RQ2R7S3p/GBMlk9ZWli1D2Smklpl4Ybh4XuSIVJraAQg3FOnOeQi45e/zH2IRDf9AuHk Y791pDbE+e7CAjEI1UK94QIo3HVRZsMUBJQQBFgRUCR+CRQdq6X+Mn4fnZKfs1qrsxSG Pw1qUpoNIqA56i/1QFf0vZ1nKRMFbD4UJhJKNvy49h1pRKVa/lvrfvEoPW8uSJ9NnL7T mIBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788477108; x=1789081908; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=oI0SdKfcZHgfXMNdZMI4amVSwVJWRyNSiFrZzvdLQQc=; b=iEV0vublZ7w255jTHOOHdsWM8hFLTlI9/oARatfh3YoL5f2CV1sN7Y1ptyjoLwrdgm te/YWRJ1s7HtQbMNOzyGzQaQuGdZh9BU7pEKpi+Lo4cjh8B8baqWrhdyChCMCZk4FDH4 M3jaty92soSxbZ4Uwv6nw7ljfynsy1dURmrvhaGa4kAmeLbIN5xyJiR6TqWl52i313dt PYNUM6Or0MpJBgmHGs+A22PcLCn8b4JNTnpdKgF1VwUCwklnwc3MtoBsBfpmxtmgIRGI BIXzEjsIiGrrtCOvFGhwguG7sN5oDDPRYcdgzYw67bR9nqkCnqasOgiWA1NoAqXvTXls vQIQ== X-Forwarded-Encrypted: i=1; AKwUvByMCrhAwFvEH3HQTZiEDnQhkwn+/9RkwH903h3nsrwJeOLmC6iHsHwIQuYGGVZ9xxJ3zt3yl264CQqXdes=@vger.kernel.org X-Gm-Message-State: AFuF++lOVm0jERXu252hbJjuCe7nIdFxUswxC9IkAHWqQ29KTrZPIZZW HyPuo8dpPu/H3PSc3s9yHbfltbM44c0VlIFbL/aAQ0D5KcUqiWHSZdWT X-Gm-Gg: AYBFou2P76iZhggBkPECko5n42nomqwy76/x6gfuOOL3sXAoO/rTDle1iHGkE0ejKUD QSy5anXZQbAdBe7+OWCbYnsC/jqTy2zx/PYpLoI3i1mRNKQK1d5Osj2lUDE2rBQJ/jXKfx251MJ P1k+DzDJSdFbBmUSR9i26o/P/yVDmYVPu9hWUy2oCZEzWwBnfdDORo7/+CGqXf8Xf+zYvYu2Eux LS5+v2HQhpkOBI6ftOOBZsfZIh0h76hIEKhW68EriM2uM/KrcE3HQIdWjnP5GpTQfPnn7745U2c MmorJEmI8bIdzfgHZ3FfXLO8gVQrxfmBp4vfyPnyA9Y9tWRuyDPzZjeO/plshkG8IGH1rG2Ikbw zaW7gLWTx8yHZBhLwmQ4GP+gHnO0Wd4pgzIlQeMfiawhHRlKerlepLMYGe86HRZlyN0hotcjHvs OQ1vNxE0Gk2PE5L3ICsTzAyIqewzoGzyW3lGamJJ2iunlN+y0hYgljRguyG0Rl1kK8Tw== X-Received: by 2002:a17:90b:1343:b0:38e:9eb2:9d43 with SMTP id 98e67ed59e1d1-39b261b1bcfmr3039830a91.16.1788477107926; Thu, 03 Sep 2026 16:11:47 -0700 (PDT) Received: from [127.0.1.1] ([2601:647:4184:b3f0:29c4:4984:db20:3bb4]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39b260cd2aasm1135006a91.3.2026.09.03.16.11.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Sep 2026 16:11:47 -0700 (PDT) From: Kelvin Zhang To: linux-f2fs-devel@lists.sourceforge.net Cc: Jaegeuk Kim , Chao Yu , Daeho Jeong , linux-kernel@vger.kernel.org Subject: [PATCH v8 07/11] f2fs: describe xattr block layout dynamically Date: Thu, 3 Sep 2026 16:11:34 -0700 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 --- 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 87fc0a8ec246..df5572084af0 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