]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: repair free space btrees
authorDarrick J. Wong <djwong@kernel.org>
Mon, 15 Apr 2024 23:07:37 +0000 (16:07 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 17 Apr 2024 21:06:25 +0000 (14:06 -0700)
Source kernel commit: 4bdfd7d15747b170ce93a06fafccaf20544b6684

Rebuild the free space btrees from the gaps in the rmap btree.  Refer to
the case study in Documentation/filesystems/xfs-online-fsck-design.rst
for more details.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
libxfs/xfs_ag.h
libxfs/xfs_ag_resv.c
libxfs/xfs_alloc.c
libxfs/xfs_alloc.h
libxfs/xfs_alloc_btree.c
libxfs/xfs_types.h

index 2e0aef87d633e0922ffa6ad9d27528156cc1225c..f16cb7a174d40094a31fed5f3699c505fb1584e9 100644 (file)
@@ -80,6 +80,15 @@ struct xfs_perag {
         */
        uint16_t        pag_checked;
        uint16_t        pag_sick;
+
+#ifdef CONFIG_XFS_ONLINE_REPAIR
+       /*
+        * Alternate btree heights so that online repair won't trip the write
+        * verifiers while rebuilding the AG btrees.
+        */
+       uint8_t         pagf_repair_levels[XFS_BTNUM_AGF];
+#endif
+
        spinlock_t      pag_state_lock;
 
        spinlock_t      pagb_lock;      /* lock for pagb_tree */
index 29bbcb55d7318d0f4db49156061c3906789e00fc..3a80b1613e182d4f2ba73d6634036a86cce0648a 100644 (file)
@@ -410,6 +410,8 @@ xfs_ag_resv_free_extent(
                fallthrough;
        case XFS_AG_RESV_NONE:
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len);
+               fallthrough;
+       case XFS_AG_RESV_IGNORE:
                return;
        }
 
index aaa1596157e9ad23af325fb2f15e8591f85acaec..352efbeca9f439eeaa0fc5df0f4878d470a43b8c 100644 (file)
@@ -242,11 +242,9 @@ xfs_alloc_btrec_to_irec(
 /* Simple checks for free space records. */
 xfs_failaddr_t
 xfs_alloc_check_irec(
-       struct xfs_btree_cur            *cur,
-       const struct xfs_alloc_rec_incore *irec)
+       struct xfs_perag                        *pag,
+       const struct xfs_alloc_rec_incore       *irec)
 {
-       struct xfs_perag                *pag = cur->bc_ag.pag;
-
        if (irec->ar_blockcount == 0)
                return __this_address;
 
@@ -295,7 +293,7 @@ xfs_alloc_get_rec(
                return error;
 
        xfs_alloc_btrec_to_irec(rec, &irec);
-       fa = xfs_alloc_check_irec(cur, &irec);
+       fa = xfs_alloc_check_irec(cur->bc_ag.pag, &irec);
        if (fa)
                return xfs_alloc_complain_bad_rec(cur, fa, &irec);
 
@@ -3940,7 +3938,7 @@ xfs_alloc_query_range_helper(
        xfs_failaddr_t                          fa;
 
        xfs_alloc_btrec_to_irec(rec, &irec);
-       fa = xfs_alloc_check_irec(cur, &irec);
+       fa = xfs_alloc_check_irec(cur->bc_ag.pag, &irec);
        if (fa)
                return xfs_alloc_complain_bad_rec(cur, fa, &irec);
 
index 851cafbd64494efa43e888645330e041707a3610..0b956f8b9d5a771a3c21184710b9b86c71b5d9a6 100644 (file)
@@ -185,7 +185,7 @@ xfs_alloc_get_rec(
 union xfs_btree_rec;
 void xfs_alloc_btrec_to_irec(const union xfs_btree_rec *rec,
                struct xfs_alloc_rec_incore *irec);
-xfs_failaddr_t xfs_alloc_check_irec(struct xfs_btree_cur *cur,
+xfs_failaddr_t xfs_alloc_check_irec(struct xfs_perag *pag,
                const struct xfs_alloc_rec_incore *irec);
 
 int xfs_read_agf(struct xfs_perag *pag, struct xfs_trans *tp, int flags,
index 5ec14288d57082a9071545f81f6a2c2fe69c53c6..a472ec6d21a20748ec3f000a47ce96c394e70688 100644 (file)
@@ -321,7 +321,18 @@ xfs_allocbt_verify(
        if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC))
                btnum = XFS_BTNUM_CNTi;
        if (pag && xfs_perag_initialised_agf(pag)) {
-               if (level >= pag->pagf_levels[btnum])
+               unsigned int    maxlevel = pag->pagf_levels[btnum];
+
+#ifdef CONFIG_XFS_ONLINE_REPAIR
+               /*
+                * Online repair could be rewriting the free space btrees, so
+                * we'll validate against the larger of either tree while this
+                * is going on.
+                */
+               maxlevel = max_t(unsigned int, maxlevel,
+                                pag->pagf_repair_levels[btnum]);
+#endif
+               if (level >= maxlevel)
                        return __this_address;
        } else if (level >= mp->m_alloc_maxlevels)
                return __this_address;
index 533200c4ccc25aa876ae30cd852066f143a2d1a1..035bf703d719a8863e30884c9aab40110f2c4e01 100644 (file)
@@ -208,6 +208,13 @@ enum xfs_ag_resv_type {
        XFS_AG_RESV_AGFL,
        XFS_AG_RESV_METADATA,
        XFS_AG_RESV_RMAPBT,
+
+       /*
+        * Don't increase fdblocks when freeing extent.  This is a pony for
+        * the bnobt repair functions to re-free the free space without
+        * altering fdblocks.  If you think you need this you're wrong.
+        */
+       XFS_AG_RESV_IGNORE,
 };
 
 /* Results of scanning a btree keyspace to check occupancy. */