]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: use bitmap to track blocks lost during btree construction
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 10 Jul 2020 19:35:46 +0000 (15:35 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Fri, 10 Jul 2020 19:35:46 +0000 (15:35 -0400)
Use the incore bitmap structure to track blocks that were lost
during btree construction.  This makes it somewhat more efficient.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
repair/agbtree.c
repair/agbtree.h
repair/phase5.c

index c0ed39410a5d595b4b0506a67f1d7e3b2c308170..ce29321c676c25b6e9b980f5d2715304ad03e339 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <libxfs.h>
 #include "err_protos.h"
+#include "libfrog/bitmap.h"
 #include "slab.h"
 #include "rmap.h"
 #include "incore.h"
@@ -131,21 +132,21 @@ void
 finish_rebuild(
        struct xfs_mount        *mp,
        struct bt_rebuild       *btr,
-       struct xfs_slab         *lost_fsb)
+       struct bitmap           *lost_blocks)
 {
        struct bulkload_resv    *resv, *n;
+       int                     error;
 
        for_each_bulkload_reservation(&btr->newbt, resv, n) {
-               while (resv->used < resv->len) {
-                       xfs_fsblock_t   fsb = resv->fsbno + resv->used;
-                       int             error;
-
-                       error = slab_add(lost_fsb, &fsb);
-                       if (error)
-                               do_error(
-_("Insufficient memory saving lost blocks.\n"));
-                       resv->used++;
-               }
+               if (resv->used == resv->len)
+                       continue;
+
+               error = bitmap_set(lost_blocks, resv->fsbno + resv->used,
+                                  resv->len - resv->used);
+               if (error)
+                       do_error(
+_("Insufficient memory saving lost blocks, err=%d.\n"), error);
+               resv->used = resv->len;
        }
 
        bulkload_destroy(&btr->newbt, 0);
index 6bbeb0225507b0539109f352c82865cd2190a504..d8095d20714f086ead4408ec4ec30166d6b6c900 100644 (file)
@@ -34,7 +34,7 @@ struct bt_rebuild {
 };
 
 void finish_rebuild(struct xfs_mount *mp, struct bt_rebuild *btr,
-               struct xfs_slab *lost_fsb);
+               struct bitmap *lost_blocks);
 void init_freespace_cursors(struct repair_ctx *sc, xfs_agnumber_t agno,
                unsigned int free_space, unsigned int *nr_extents,
                int *extra_blocks, struct bt_rebuild *btr_bno,
index 439c106562fb4a7fad92bcc069368e95234886c9..446f7ec0a1db5d986e971b7481c4d2a929f656f3 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "libxfs.h"
+#include "libfrog/bitmap.h"
 #include "avl.h"
 #include "globals.h"
 #include "agheader.h"
@@ -211,7 +212,7 @@ build_agf_agfl(
        struct bt_rebuild       *btr_cnt,
        struct bt_rebuild       *btr_rmap,
        struct bt_rebuild       *btr_refc,
-       struct xfs_slab         *lost_fsb)
+       struct bitmap           *lost_blocks)
 {
        struct extent_tree_node *ext_ptr;
        struct xfs_buf          *agf_buf, *agfl_buf;
@@ -428,7 +429,7 @@ static void
 phase5_func(
        struct xfs_mount        *mp,
        xfs_agnumber_t          agno,
-       struct xfs_slab         *lost_fsb)
+       struct bitmap           *lost_blocks)
 {
        struct repair_ctx       sc = { .mp = mp, };
        struct bt_rebuild       btr_bno;
@@ -543,7 +544,7 @@ _("unable to rebuild AG %u.  Not enough free space in on-disk AG.\n"),
         * set up agf and agfl
         */
        build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &btr_rmap, &btr_refc,
-                       lost_fsb);
+                       lost_blocks);
 
        build_inode_btrees(&sc, agno, &btr_ino, &btr_fino);
 
@@ -553,15 +554,15 @@ _("unable to rebuild AG %u.  Not enough free space in on-disk AG.\n"),
        /*
         * tear down cursors
         */
-       finish_rebuild(mp, &btr_bno, lost_fsb);
-       finish_rebuild(mp, &btr_cnt, lost_fsb);
-       finish_rebuild(mp, &btr_ino, lost_fsb);
+       finish_rebuild(mp, &btr_bno, lost_blocks);
+       finish_rebuild(mp, &btr_cnt, lost_blocks);
+       finish_rebuild(mp, &btr_ino, lost_blocks);
        if (xfs_sb_version_hasfinobt(&mp->m_sb))
-               finish_rebuild(mp, &btr_fino, lost_fsb);
+               finish_rebuild(mp, &btr_fino, lost_blocks);
        if (xfs_sb_version_hasrmapbt(&mp->m_sb))
-               finish_rebuild(mp, &btr_rmap, lost_fsb);
+               finish_rebuild(mp, &btr_rmap, lost_blocks);
        if (xfs_sb_version_hasreflink(&mp->m_sb))
-               finish_rebuild(mp, &btr_refc, lost_fsb);
+               finish_rebuild(mp, &btr_refc, lost_blocks);
 
        /*
         * release the incore per-AG bno/bcnt trees so the extent nodes
@@ -572,48 +573,33 @@ _("unable to rebuild AG %u.  Not enough free space in on-disk AG.\n"),
        PROG_RPT_INC(prog_rpt_done[agno], 1);
 }
 
-/* Inject lost blocks back into the filesystem. */
+/* Inject this unused space back into the filesystem. */
 static int
-inject_lost_blocks(
-       struct xfs_mount        *mp,
-       struct xfs_slab         *lost_fsbs)
+inject_lost_extent(
+       uint64_t                start,
+       uint64_t                length,
+       void                    *arg)
 {
-       struct xfs_trans        *tp = NULL;
-       struct xfs_slab_cursor  *cur = NULL;
-       xfs_fsblock_t           *fsb;
+       struct xfs_mount        *mp = arg;
+       struct xfs_trans        *tp;
        int                     error;
 
-       error = init_slab_cursor(lost_fsbs, NULL, &cur);
+       error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
        if (error)
                return error;
 
-       while ((fsb = pop_slab_cursor(cur)) != NULL) {
-               error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
-               if (error)
-                       goto out_cancel;
-
-               error = -libxfs_free_extent(tp, *fsb, 1,
-                               &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE);
-               if (error)
-                       goto out_cancel;
-
-               error = -libxfs_trans_commit(tp);
-               if (error)
-                       goto out_cancel;
-               tp = NULL;
-       }
+       error = -libxfs_free_extent(tp, start, length,
+                       &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE);
+       if (error)
+               return error;
 
-out_cancel:
-       if (tp)
-               libxfs_trans_cancel(tp);
-       free_slab_cursor(&cur);
-       return error;
+       return -libxfs_trans_commit(tp);
 }
 
 void
 phase5(xfs_mount_t *mp)
 {
-       struct xfs_slab         *lost_fsb;
+       struct bitmap           *lost_blocks = NULL;
        xfs_agnumber_t          agno;
        int                     error;
 
@@ -656,12 +642,12 @@ phase5(xfs_mount_t *mp)
        if (sb_fdblocks_ag == NULL)
                do_error(_("cannot alloc sb_fdblocks_ag buffers\n"));
 
-       error = init_slab(&lost_fsb, sizeof(xfs_fsblock_t));
+       error = bitmap_alloc(&lost_blocks);
        if (error)
-               do_error(_("cannot alloc lost block slab\n"));
+               do_error(_("cannot alloc lost block bitmap\n"));
 
        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
-               phase5_func(mp, agno, lost_fsb);
+               phase5_func(mp, agno, lost_blocks);
 
        print_final_rpt();
 
@@ -704,10 +690,10 @@ _("unable to add AG %u reverse-mapping data to btree.\n"), agno);
         * Put blocks that were unnecessarily reserved for btree
         * reconstruction back into the filesystem free space data.
         */
-       error = inject_lost_blocks(mp, lost_fsb);
+       error = bitmap_iterate(lost_blocks, inject_lost_extent, mp);
        if (error)
                do_error(_("Unable to reinsert lost blocks into filesystem.\n"));
-       free_slab(&lost_fsb);
+       bitmap_free(&lost_blocks);
 
        bad_ino_btree = 0;