This is a note to let you know that I've just added the patch titled xfs: make xchk_iget safer in the presence of corrupt inode btrees to the 6.6-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: xfs-make-xchk_iget-safer-in-the-presence-of-corrupt-inode-btrees.patch and it can be found in the queue-6.6 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From stable+bounces-32420-greg=kroah.com@xxxxxxxxxxxxxxx Wed Mar 27 01:13:28 2024 From: Catherine Hoang <catherine.hoang@xxxxxxxxxx> Date: Tue, 26 Mar 2024 17:12:20 -0700 Subject: xfs: make xchk_iget safer in the presence of corrupt inode btrees To: stable@xxxxxxxxxxxxxxx Cc: linux-xfs@xxxxxxxxxxxxxxx Message-ID: <20240327001233.51675-12-catherine.hoang@xxxxxxxxxx> From: "Darrick J. Wong" <djwong@xxxxxxxxxx> commit 3f113c2739b1b068854c7ffed635c2bd790d1492 upstream. When scrub is trying to iget an inode, ensure that it won't end up deadlocked on a cycle in the inode btree by using an empty transaction to store all the buffers. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> Reviewed-by: Dave Chinner <dchinner@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> Signed-off-by: Catherine Hoang <catherine.hoang@xxxxxxxxxx> Acked-by: Darrick J. Wong <djwong@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/xfs/scrub/common.c | 6 ++++-- fs/xfs/scrub/common.h | 25 +++++++++++++++++++++++++ fs/xfs/scrub/inode.c | 4 ++-- 3 files changed, 31 insertions(+), 4 deletions(-) --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -733,6 +733,8 @@ xchk_iget( xfs_ino_t inum, struct xfs_inode **ipp) { + ASSERT(sc->tp != NULL); + return xfs_iget(sc->mp, sc->tp, inum, XFS_IGET_UNTRUSTED, 0, ipp); } @@ -882,8 +884,8 @@ xchk_iget_for_scrubbing( if (!xfs_verify_ino(sc->mp, sc->sm->sm_ino)) return -ENOENT; - /* Try a regular untrusted iget. */ - error = xchk_iget(sc, sc->sm->sm_ino, &ip); + /* Try a safe untrusted iget. */ + error = xchk_iget_safe(sc, sc->sm->sm_ino, &ip); if (!error) return xchk_install_handle_inode(sc, ip); if (error == -ENOENT) --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -151,6 +151,11 @@ void xchk_iunlock(struct xfs_scrub *sc, void xchk_buffer_recheck(struct xfs_scrub *sc, struct xfs_buf *bp); +/* + * Grab the inode at @inum. The caller must have created a scrub transaction + * so that we can confirm the inumber by walking the inobt and not deadlock on + * a loop in the inobt. + */ int xchk_iget(struct xfs_scrub *sc, xfs_ino_t inum, struct xfs_inode **ipp); int xchk_iget_agi(struct xfs_scrub *sc, xfs_ino_t inum, struct xfs_buf **agi_bpp, struct xfs_inode **ipp); @@ -158,6 +163,26 @@ void xchk_irele(struct xfs_scrub *sc, st int xchk_install_handle_inode(struct xfs_scrub *sc, struct xfs_inode *ip); /* + * Safe version of (untrusted) xchk_iget that uses an empty transaction to + * avoid deadlocking on loops in the inobt. This should only be used in a + * scrub or repair setup routine, and only prior to grabbing a transaction. + */ +static inline int +xchk_iget_safe(struct xfs_scrub *sc, xfs_ino_t inum, struct xfs_inode **ipp) +{ + int error; + + ASSERT(sc->tp == NULL); + + error = xchk_trans_alloc(sc, 0); + if (error) + return error; + error = xchk_iget(sc, inum, ipp); + xchk_trans_cancel(sc); + return error; +} + +/* * Don't bother cross-referencing if we already found corruption or cross * referencing discrepancies. */ --- a/fs/xfs/scrub/inode.c +++ b/fs/xfs/scrub/inode.c @@ -94,8 +94,8 @@ xchk_setup_inode( if (!xfs_verify_ino(sc->mp, sc->sm->sm_ino)) return -ENOENT; - /* Try a regular untrusted iget. */ - error = xchk_iget(sc, sc->sm->sm_ino, &ip); + /* Try a safe untrusted iget. */ + error = xchk_iget_safe(sc, sc->sm->sm_ino, &ip); if (!error) return xchk_install_handle_iscrub(sc, ip); if (error == -ENOENT) Patches currently in stable-queue which might be from kroah.com@xxxxxxxxxxxxxxx are queue-6.6/xfs-fix-32-bit-truncation-in-xfs_compute_rextslog.patch queue-6.6/xfs-transfer-recovered-intent-item-ownership-in-iop_recover.patch queue-6.6/xfs-initialise-di_crc-in-xfs_log_dinode.patch queue-6.6/xfs-add-missing-nrext64-inode-flag-check-to-scrub.patch queue-6.6/xfs-consider-minlen-sized-extents-in-xfs_rtallocate_extent_block.patch queue-6.6/xfs-don-t-leak-recovered-attri-intent-items.patch queue-6.6/xfs-remove-unused-fields-from-struct-xbtree_ifakeroot.patch queue-6.6/xfs-ensure-logflagsp-is-initialized-in-xfs_bmap_del_extent_real.patch queue-6.6/xfs-convert-rt-bitmap-extent-lengths-to-xfs_rtbxlen_t.patch queue-6.6/xfs-fix-perag-leak-when-growfs-fails.patch queue-6.6/xfs-pass-the-xfs_defer_pending-object-to-iop_recover.patch queue-6.6/xfs-update-dir3-leaf-block-metadata-after-swap.patch queue-6.6/xfs-make-rextslog-computation-consistent-with-mkfs.patch queue-6.6/xfs-move-the-xfs_rtbitmap.c-declarations-to-xfs_rtbitmap.h.patch queue-6.6/xfs-recompute-growfsrtfree-transaction-reservation-while-growing-rt-volume.patch queue-6.6/xfs-force-all-buffers-to-be-written-during-btree-bulk-load.patch queue-6.6/xfs-make-xchk_iget-safer-in-the-presence-of-corrupt-inode-btrees.patch queue-6.6/xfs-reset-xfs_attr_incomplete-filter-on-node-removal.patch queue-6.6/xfs-fix-an-off-by-one-error-in-xreap_agextent_binval.patch queue-6.6/xfs-short-circuit-xfs_growfs_data_private-if-delta-is-zero.patch queue-6.6/xfs-add-lock-protection-when-remove-perag-from-radix-tree.patch queue-6.6/xfs-use-xfs_defer_pending-objects-to-recover-intent-items.patch queue-6.6/xfs-don-t-allow-overly-small-or-large-realtime-volumes.patch queue-6.6/xfs-remove-conditional-building-of-rt-geometry-validator-functions.patch