]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: report btree block corruption errors to the health system
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 17:00:54 +0000 (10:00 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 3 Jun 2024 18:37:36 +0000 (11:37 -0700)
Source kernel commit: a78d10f45b23149f1b23019a4f4fb57dcf852e39

Whenever we encounter corrupt btree blocks, we should report that to the
health monitoring system for later reporting.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
libxfs/util.c
libxfs/xfs_alloc.c
libxfs/xfs_bmap.c
libxfs/xfs_btree.c
libxfs/xfs_health.h
libxfs/xfs_ialloc.c
libxfs/xfs_refcount.c
libxfs/xfs_rmap.c

index 2403d64b4cc02073f9697a71fd2dd515fac131d6..b45d670653cf54604c878a2388f2e56e8db430d7 100644 (file)
@@ -733,3 +733,4 @@ void xfs_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno,
                unsigned int mask) { }
 void xfs_ag_mark_sick(struct xfs_perag *pag, unsigned int mask) { }
 void xfs_bmap_mark_sick(struct xfs_inode *ip, int whichfork) { }
+void xfs_btree_mark_sick(struct xfs_btree_cur *cur) { }
index 1894a0913807d8a5c4d9eaf851be3e30717b2f86..aa084120c4c333f50d079d525438ebb549902f60 100644 (file)
@@ -271,6 +271,7 @@ xfs_alloc_complain_bad_rec(
        xfs_warn(mp,
                "start block 0x%x block count 0x%x", irec->ar_startblock,
                irec->ar_blockcount);
+       xfs_btree_mark_sick(cur);
        return -EFSCORRUPTED;
 }
 
@@ -2698,6 +2699,7 @@ xfs_exact_minlen_extent_available(
                goto out;
 
        if (*stat == 0) {
+               xfs_btree_mark_sick(cnt_cur);
                error = -EFSCORRUPTED;
                goto out;
        }
index 4d21720e9ac6661cb4d3e3e3576ee37540033c5d..f15631818b3f5a0cd1e9f93e5d7dd65a53706f04 100644 (file)
@@ -362,6 +362,8 @@ xfs_bmap_check_leaf_extents(
                        error = xfs_btree_read_bufl(mp, NULL, bno, &bp,
                                                XFS_BMAP_BTREE_REF,
                                                &xfs_bmbt_buf_ops);
+                       if (xfs_metadata_is_sick(error))
+                               xfs_btree_mark_sick(cur);
                        if (error)
                                goto error_norelse;
                }
@@ -448,6 +450,8 @@ xfs_bmap_check_leaf_extents(
                        error = xfs_btree_read_bufl(mp, NULL, bno, &bp,
                                                XFS_BMAP_BTREE_REF,
                                                &xfs_bmbt_buf_ops);
+                       if (xfs_metadata_is_sick(error))
+                               xfs_btree_mark_sick(cur);
                        if (error)
                                goto error_norelse;
                }
@@ -562,6 +566,8 @@ xfs_bmap_btree_to_extents(
 #endif
        error = xfs_btree_read_bufl(mp, tp, cbno, &cbp, XFS_BMAP_BTREE_REF,
                                &xfs_bmbt_buf_ops);
+       if (xfs_metadata_is_sick(error))
+               xfs_btree_mark_sick(cur);
        if (error)
                return error;
        cblock = XFS_BUF_TO_BLOCK(cbp);
index 663439ec3e3fae4a97d17d86297e73bd0c756854..359d3f99ecf3f0e6952b0b8113b662c840d8b45e 100644 (file)
@@ -24,6 +24,7 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_rmap_btree.h"
 #include "xfs_refcount_btree.h"
+#include "xfs_health.h"
 
 /*
  * Btree magic numbers.
@@ -174,6 +175,7 @@ xfs_btree_check_lblock(
            XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK)) {
                if (bp)
                        trace_xfs_btree_corrupt(bp, _RET_IP_);
+               xfs_btree_mark_sick(cur);
                return -EFSCORRUPTED;
        }
        return 0;
@@ -240,6 +242,7 @@ xfs_btree_check_sblock(
            XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BTREE_CHECK_SBLOCK)) {
                if (bp)
                        trace_xfs_btree_corrupt(bp, _RET_IP_);
+               xfs_btree_mark_sick(cur);
                return -EFSCORRUPTED;
        }
        return 0;
@@ -315,6 +318,7 @@ xfs_btree_check_ptr(
                                level, index);
        }
 
+       xfs_btree_mark_sick(cur);
        return -EFSCORRUPTED;
 }
 
@@ -495,6 +499,8 @@ xfs_btree_dup_cursor(
                                                   xfs_buf_daddr(bp), mp->m_bsize,
                                                   0, &bp,
                                                   cur->bc_ops->buf_ops);
+                       if (xfs_metadata_is_sick(error))
+                               xfs_btree_mark_sick(new);
                        if (error) {
                                xfs_btree_del_cursor(new, error);
                                *ncur = NULL;
@@ -1348,6 +1354,8 @@ xfs_btree_read_buf_block(
        error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
                                   mp->m_bsize, flags, bpp,
                                   cur->bc_ops->buf_ops);
+       if (xfs_metadata_is_sick(error))
+               xfs_btree_mark_sick(cur);
        if (error)
                return error;
 
@@ -1658,6 +1666,7 @@ xfs_btree_increment(
                if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
                        goto out0;
                ASSERT(0);
+               xfs_btree_mark_sick(cur);
                error = -EFSCORRUPTED;
                goto error0;
        }
@@ -1751,6 +1760,7 @@ xfs_btree_decrement(
                if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
                        goto out0;
                ASSERT(0);
+               xfs_btree_mark_sick(cur);
                error = -EFSCORRUPTED;
                goto error0;
        }
@@ -1843,6 +1853,7 @@ out_bad:
        *blkp = NULL;
        xfs_buf_mark_corrupt(bp);
        xfs_trans_brelse(cur->bc_tp, bp);
+       xfs_btree_mark_sick(cur);
        return -EFSCORRUPTED;
 }
 
@@ -1889,8 +1900,10 @@ xfs_btree_lookup(
        XFS_BTREE_STATS_INC(cur, lookup);
 
        /* No such thing as a zero-level tree. */
-       if (XFS_IS_CORRUPT(cur->bc_mp, cur->bc_nlevels == 0))
+       if (XFS_IS_CORRUPT(cur->bc_mp, cur->bc_nlevels == 0)) {
+               xfs_btree_mark_sick(cur);
                return -EFSCORRUPTED;
+       }
 
        block = NULL;
        keyno = 0;
@@ -1933,6 +1946,7 @@ xfs_btree_lookup(
                                                        XFS_ERRLEVEL_LOW,
                                                        cur->bc_mp, block,
                                                        sizeof(*block));
+                                       xfs_btree_mark_sick(cur);
                                        return -EFSCORRUPTED;
                                }
 
@@ -4366,12 +4380,16 @@ xfs_btree_visit_block(
         */
        if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
                if (be64_to_cpu(rptr.l) == XFS_DADDR_TO_FSB(cur->bc_mp,
-                                                       xfs_buf_daddr(bp)))
+                                                       xfs_buf_daddr(bp))) {
+                       xfs_btree_mark_sick(cur);
                        return -EFSCORRUPTED;
+               }
        } else {
                if (be32_to_cpu(rptr.s) == xfs_daddr_to_agbno(cur->bc_mp,
-                                                       xfs_buf_daddr(bp)))
+                                                       xfs_buf_daddr(bp))) {
+                       xfs_btree_mark_sick(cur);
                        return -EFSCORRUPTED;
+               }
        }
        return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
 }
@@ -5230,6 +5248,7 @@ xfs_btree_goto_left_edge(
                return error;
        if (stat != 0) {
                ASSERT(0);
+               xfs_btree_mark_sick(cur);
                return -EFSCORRUPTED;
        }
 
index 3c8fd060744f2c76170b7ab35af72f84f0c08fa6..8f566a78737fed838845665522583f48a00264d7 100644 (file)
@@ -37,6 +37,7 @@ struct xfs_mount;
 struct xfs_perag;
 struct xfs_inode;
 struct xfs_fsop_geom;
+struct xfs_btree_cur;
 
 /* Observable health issues for metadata spanning the entire filesystem. */
 #define XFS_SICK_FS_COUNTERS   (1 << 0)  /* summary counters */
@@ -160,6 +161,7 @@ void xfs_inode_measure_sickness(struct xfs_inode *ip, unsigned int *sick,
 
 void xfs_health_unmount(struct xfs_mount *mp);
 void xfs_bmap_mark_sick(struct xfs_inode *ip, int whichfork);
+void xfs_btree_mark_sick(struct xfs_btree_cur *cur);
 
 /* Now some helpers. */
 
index c801250a33bfa50881655a2d1e0d193d1cccfff6..92ca3d460e04bf15dc87d6f796c916eaff5b31db 100644 (file)
@@ -143,6 +143,7 @@ xfs_inobt_complain_bad_rec(
 "start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x",
                irec->ir_startino, irec->ir_count, irec->ir_freecount,
                irec->ir_free, irec->ir_holemask);
+       xfs_btree_mark_sick(cur);
        return -EFSCORRUPTED;
 }
 
index 36dd06e638870ae5a9382c334684f810e1c5ef45..00df1e64ac6c69cda19c4e83db0e938effc13bd6 100644 (file)
@@ -22,6 +22,7 @@
 #include "xfs_refcount.h"
 #include "xfs_rmap.h"
 #include "xfs_ag.h"
+#include "xfs_health.h"
 
 struct kmem_cache      *xfs_refcount_intent_cache;
 
@@ -155,6 +156,7 @@ xfs_refcount_complain_bad_rec(
        xfs_warn(mp,
                "Start block 0x%x, block count 0x%x, references 0x%x",
                irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
+       xfs_btree_mark_sick(cur);
        return -EFSCORRUPTED;
 }
 
@@ -1888,8 +1890,10 @@ xfs_refcount_recover_extent(
        struct xfs_refcount_recovery    *rr;
 
        if (XFS_IS_CORRUPT(cur->bc_mp,
-                          be32_to_cpu(rec->refc.rc_refcount) != 1))
+                          be32_to_cpu(rec->refc.rc_refcount) != 1)) {
+               xfs_btree_mark_sick(cur);
                return -EFSCORRUPTED;
+       }
 
        rr = kmalloc(sizeof(struct xfs_refcount_recovery),
                        GFP_KERNEL | __GFP_NOFAIL);
index e7681c7c852db94f697d7ee1114bb2329662c2c1..8fbc9583de749fcebfb798f6d5a8df194b894f09 100644 (file)
@@ -22,6 +22,7 @@
 #include "xfs_errortag.h"
 #include "xfs_inode.h"
 #include "xfs_ag.h"
+#include "xfs_health.h"
 
 struct kmem_cache      *xfs_rmap_intent_cache;
 
@@ -55,8 +56,10 @@ xfs_rmap_lookup_le(
        error = xfs_rmap_get_rec(cur, irec, &get_stat);
        if (error)
                return error;
-       if (!get_stat)
+       if (!get_stat) {
+               xfs_btree_mark_sick(cur);
                return -EFSCORRUPTED;
+       }
 
        return 0;
 }
@@ -276,6 +279,7 @@ xfs_rmap_complain_bad_rec(
                "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
                irec->rm_owner, irec->rm_flags, irec->rm_startblock,
                irec->rm_blockcount);
+       xfs_btree_mark_sick(cur);
        return -EFSCORRUPTED;
 }