From: Dave Chinner <dgc@kernel.org>
To: linux-xfs@vger.kernel.org
Cc: cem@kernel.org
Subject: [PATCH 33/48] xfs: convert inode items to host format during recovery
Date: Tue, 13 Oct 2026 17:01:23 +1100 [thread overview]
Message-ID: <20261013060204.3138690-34-dgc@kernel.org> (raw)
In-Reply-To: <20261013060204.3138690-1-dgc@kernel.org>
The inode item format header is logged in either the host format or the older
32 bit on-disk format. Recovery converted between them in the commit handler
and carried a separately allocated copy through the rest of the function.
Convert the format header to host format in ->validate_item() as the item is
decoded, so the rest of recovery treats region 0 as a host format header
without regard for the on-disk format. The commit handler and readahead now use
the header directly. The separate allocation and its cleanup are removed.
Assisted-by: LLM
Signed-off-by: Dave Chinner <dgc@kernel.org>
---
fs/xfs/xfs_inode_item_recover.c | 108 +++++++++++++++++++++++---------
1 file changed, 79 insertions(+), 29 deletions(-)
diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c
index 8da95131ab55..48acb0aa3b6c 100644
--- a/fs/xfs/xfs_inode_item_recover.c
+++ b/fs/xfs/xfs_inode_item_recover.c
@@ -30,17 +30,10 @@ xlog_recover_inode_ra_pass2(
struct xlog *log,
struct xlog_recover_item *item)
{
- if (item->ri_buf[0].iov_len == sizeof(struct xfs_inode_log_format)) {
- struct xfs_inode_log_format *ilfp = item->ri_buf[0].iov_base;
+ struct xfs_inode_log_format *ilfp = item->ri_buf[0].iov_base;
- xlog_buf_readahead(log, ilfp->ilf_blkno, ilfp->ilf_len,
- &xfs_inode_buf_ra_ops);
- } else {
- struct xfs_inode_log_format_32 *ilfp = item->ri_buf[0].iov_base;
-
- xlog_buf_readahead(log, ilfp->ilf_blkno, ilfp->ilf_len,
- &xfs_inode_buf_ra_ops);
- }
+ xlog_buf_readahead(log, ilfp->ilf_blkno, ilfp->ilf_len,
+ &xfs_inode_buf_ra_ops);
}
/*
@@ -304,6 +297,75 @@ xlog_recover_inode_dbroot(
return 0;
}
+/*
+ * An inode item is a format header region, the log dinode core, and up to two
+ * fork regions, so it has two to four regions. The exact count depends on the
+ * fields logged and is checked once the format header is decoded.
+ */
+static int
+xlog_recover_inode_nregions(
+ struct xlog *log,
+ uint16_t nregions)
+{
+ if (nregions < 2 || nregions > 4)
+ return -EFSCORRUPTED;
+ return nregions;
+}
+
+/*
+ * The format header (region 0) is logged in either the host format or the 32
+ * bit on-disk format, so it must match one of those two sizes.
+ */
+static int
+xlog_recover_inode_validate_region(
+ struct xlog *log,
+ struct xlog_recover_item *item,
+ int region_index)
+{
+ size_t len = item->ri_buf[region_index].iov_len;
+
+ if (region_index > 0)
+ return 0;
+
+ if (len != sizeof(struct xfs_inode_log_format) &&
+ len != sizeof(struct xfs_inode_log_format_32)) {
+ xfs_warn(log->l_mp,
+ "INODE: bad format region length %zu recovered.", len);
+ return -EFSCORRUPTED;
+ }
+
+ return 0;
+}
+
+/*
+ * Convert the format header to host format so the rest of recovery can treat
+ * region 0 as a struct xfs_inode_log_format without regard for the on-disk
+ * format. A header already in host format is left in place.
+ */
+static int
+xlog_recover_inode_validate_item(
+ struct xlog *log,
+ struct xlog_recover_item *item)
+{
+ struct xfs_inode_log_format *in_f;
+ int error;
+
+ if (item->ri_buf[0].iov_len == sizeof(struct xfs_inode_log_format))
+ return 0;
+
+ in_f = kmalloc_obj(struct xfs_inode_log_format, GFP_KERNEL | __GFP_NOFAIL);
+ error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
+ if (error) {
+ kfree(in_f);
+ return error;
+ }
+
+ kvfree(item->ri_buf[0].iov_base);
+ item->ri_buf[0].iov_base = in_f;
+ item->ri_buf[0].iov_len = sizeof(struct xfs_inode_log_format);
+ return 0;
+}
+
STATIC int
xlog_recover_inode_commit_pass2(
struct xlog *log,
@@ -311,7 +373,7 @@ xlog_recover_inode_commit_pass2(
struct xlog_recover_item *item,
xfs_lsn_t current_lsn)
{
- struct xfs_inode_log_format *in_f;
+ struct xfs_inode_log_format *in_f = item->ri_buf[0].iov_base;
struct xfs_mount *mp = log->l_mp;
struct xfs_buf *bp;
struct xfs_dinode *dip;
@@ -323,35 +385,22 @@ xlog_recover_inode_commit_pass2(
uint fields;
struct xfs_log_dinode *ldip;
uint isize;
- int need_free = 0;
xfs_failaddr_t fa;
- if (item->ri_buf[0].iov_len == sizeof(struct xfs_inode_log_format)) {
- in_f = item->ri_buf[0].iov_base;
- } else {
- in_f = kmalloc_obj(struct xfs_inode_log_format,
- GFP_KERNEL | __GFP_NOFAIL);
- need_free = 1;
- error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
- if (error)
- goto error;
- }
-
/*
* Inode buffers can be freed, look out for it,
* and do not replay the inode.
*/
if (xlog_is_buffer_cancelled(log, in_f->ilf_blkno, in_f->ilf_len)) {
- error = 0;
trace_xfs_log_recover_inode_cancel(log, in_f);
- goto error;
+ return 0;
}
trace_xfs_log_recover_inode_recover(log, in_f);
error = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len,
0, &bp, &xfs_inode_buf_ops);
if (error)
- goto error;
+ return error;
ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
dip = xfs_buf_offset(bp, in_f->ilf_boffset);
@@ -608,14 +657,15 @@ xlog_recover_inode_commit_pass2(
out_release:
xfs_buf_relse(bp);
-error:
- if (need_free)
- kfree(in_f);
return error;
}
const struct xlog_recover_item_ops xlog_inode_item_ops = {
.item_type = XFS_LI_INODE,
+ .min_hdr_len = sizeof(struct xfs_inode_log_format_32),
+ .validate_nregions = xlog_recover_inode_nregions,
+ .validate_region = xlog_recover_inode_validate_region,
+ .validate_item = xlog_recover_inode_validate_item,
.ra_pass2 = xlog_recover_inode_ra_pass2,
.commit_pass2 = xlog_recover_inode_commit_pass2,
};
--
2.55.0
next prev parent reply other threads:[~2026-10-13 6:02 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 6:00 [RFC] [PATCH 00/48] Validate journal log items during log recovery Dave Chinner
2026-10-13 6:00 ` [PATCH 01/48] xfs: set the unmount record operation header length Dave Chinner
2026-10-13 6:00 ` [PATCH 02/48] xfs: add log recovery item validation design document Dave Chinner
2026-10-13 6:00 ` [PATCH 03/48] xfs: lift transaction header parsing out of the region assembly Dave Chinner
2026-10-13 6:00 ` [PATCH 04/48] xfs: track transaction header decode state explicitly Dave Chinner
2026-10-13 6:00 ` [PATCH 05/48] xfs: track the log item being rebuilt with an explicit pointer Dave Chinner
2026-10-13 6:00 ` [PATCH 06/48] xfs: complete log items explicitly during recovery Dave Chinner
2026-10-13 6:00 ` [PATCH 07/48] xfs: add log item validation infrastructure to log recovery Dave Chinner
2026-10-13 6:00 ` [PATCH 08/48] xfs: recover the transaction header as a validated item type Dave Chinner
2026-10-13 6:00 ` [PATCH 09/48] xfs: factor out xlog_recover_validate_ophdr() Dave Chinner
2026-10-13 6:01 ` [PATCH 10/48] xfs: validate operation header length and alignment during recovery Dave Chinner
2026-10-13 6:01 ` [PATCH 11/48] xfs: validate the operation header padding " Dave Chinner
2026-10-13 6:01 ` [PATCH 12/48] xfs: validate the operation header flags " Dave Chinner
2026-10-13 6:01 ` [PATCH 13/48] xfs: enforce zero length control records " Dave Chinner
2026-10-13 6:01 ` [PATCH 14/48] xfs: validate the unmount record " Dave Chinner
2026-10-13 6:01 ` [PATCH 15/48] xfs: handle zero length continuation op headers " Dave Chinner
2026-10-13 6:01 ` [PATCH 16/48] xfs: bound the assembled region size " Dave Chinner
2026-10-13 6:01 ` [PATCH 17/48] xfs: dump the corrupt region when log item validation fails Dave Chinner
2026-10-13 6:01 ` [PATCH 18/48] xfs: validate fixed size log items during recovery Dave Chinner
2026-10-13 6:01 ` [PATCH 19/48] xfs: validate extent free " Dave Chinner
2026-10-13 6:01 ` [PATCH 20/48] xfs: validate and convert extent free intents " Dave Chinner
2026-10-13 6:01 ` [PATCH 21/48] xfs: validate and convert extent free done items " Dave Chinner
2026-10-13 6:01 ` [PATCH 22/48] xfs: validate rmap update intents " Dave Chinner
2026-10-13 6:01 ` [PATCH 23/48] xfs: validate rmap update done items " Dave Chinner
2026-10-13 6:01 ` [PATCH 24/48] xfs: validate refcount update intents " Dave Chinner
2026-10-13 6:01 ` [PATCH 25/48] xfs: validate refcount update done items " Dave Chinner
2026-10-13 6:01 ` [PATCH 26/48] xfs: validate bmap update intents " Dave Chinner
2026-10-13 6:01 ` [PATCH 27/48] xfs: validate bmap update done items " Dave Chinner
2026-10-13 6:01 ` [PATCH 28/48] xfs: validate mapping exchange intents " Dave Chinner
2026-10-13 6:01 ` [PATCH 29/48] xfs: validate mapping exchange done items " Dave Chinner
2026-10-13 6:01 ` [PATCH 30/48] xfs: validate dquot " Dave Chinner
2026-10-13 6:01 ` [PATCH 31/48] xfs: validate attr done " Dave Chinner
2026-10-13 6:01 ` [PATCH 32/48] xfs: validate attr intents " Dave Chinner
2026-10-13 6:01 ` Dave Chinner [this message]
2026-10-13 6:01 ` [PATCH 34/48] xfs: allow xfs_imap() to map without an inode btree lookup Dave Chinner
2026-10-13 6:01 ` [PATCH 35/48] xfs: validate the inode item format header during recovery Dave Chinner
2026-10-13 6:01 ` [PATCH 36/48] xfs: validate the logged inode core " Dave Chinner
2026-10-13 6:01 ` [PATCH 37/48] xfs: validate the logged inode forks " Dave Chinner
2026-10-13 6:01 ` [PATCH 38/48] xfs: validate logged local fork contents " Dave Chinner
2026-10-13 6:01 ` [PATCH 39/48] xfs: validate logged extent " Dave Chinner
2026-10-13 6:01 ` [PATCH 40/48] xfs: allow a long format btree root to be checked without a cursor Dave Chinner
2026-10-13 6:01 ` [PATCH 41/48] xfs: validate logged btree fork roots during recovery Dave Chinner
2026-10-13 6:01 ` [PATCH 42/48] xfs: validate logged metadata " Dave Chinner
2026-10-13 6:01 ` [PATCH 43/48] xfs: validate buffer item region count " Dave Chinner
2026-10-13 6:01 ` [PATCH 44/48] xfs: validate buffer item regions " Dave Chinner
2026-10-13 6:01 ` [PATCH 45/48] xfs: validate the whole buffer item " Dave Chinner
2026-10-13 6:01 ` [PATCH 46/48] xfs: remove redundant buffer checks from recovery replay Dave Chinner
2026-10-13 6:01 ` [PATCH 47/48] xfs: fail recovery on a buffer type mismatch Dave Chinner
2026-10-13 6:01 ` [PATCH 48/48] xfs: validate logged dquot buffers during recovery Dave Chinner
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=20261013060204.3138690-34-dgc@kernel.org \
--to=dgc@kernel.org \
--cc=cem@kernel.org \
--cc=linux-xfs@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