]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/rmap.c
libxfs: refactor manage_zones()
[thirdparty/xfsprogs-dev.git] / repair / rmap.c
index d9d086a7936e7f6e2cb44d8eea01eafd576e832a..19cceca32773292bbb773c57465a8bac28a3d6ae 100644 (file)
@@ -12,6 +12,7 @@
 #include "dinode.h"
 #include "slab.h"
 #include "rmap.h"
+#include "bitmap.h"
 
 #undef RMAP_DEBUG
 
@@ -450,16 +451,16 @@ rmap_store_ag_btree_rec(
        struct xfs_buf          *agflbp = NULL;
        struct xfs_trans        *tp;
        __be32                  *agfl_bno, *b;
+       struct xfs_ag_rmap      *ag_rmap = &ag_rmaps[agno];
+       struct bitmap           *own_ag_bitmap = NULL;
        int                     error = 0;
-       struct xfs_owner_info   oinfo;
 
        if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
                return 0;
 
        /* Release the ar_rmaps; they were put into the rmapbt during p5. */
-       free_slab(&ag_rmaps[agno].ar_rmaps);
-       error = init_slab(&ag_rmaps[agno].ar_rmaps,
-                                 sizeof(struct xfs_rmap_irec));
+       free_slab(&ag_rmap->ar_rmaps);
+       error = init_slab(&ag_rmap->ar_rmaps, sizeof(struct xfs_rmap_irec));
        if (error)
                goto err;
 
@@ -479,18 +480,50 @@ rmap_store_ag_btree_rec(
         * rmap, we only need to add rmap records for AGFL blocks past
         * that point in the AGFL because those blocks are a result of a
         * no-rmap no-shrink freelist fixup that we did earlier.
+        *
+        * However, some blocks end up on the AGFL because the free space
+        * btrees shed blocks as a result of allocating space to fix the
+        * freelist.  We already created in-core rmap records for the free
+        * space btree blocks, so we must be careful not to create those
+        * records again.  Create a bitmap of already-recorded OWN_AG rmaps.
         */
+       error = init_slab_cursor(ag_rmap->ar_raw_rmaps, rmap_compare, &rm_cur);
+       if (error)
+               goto err;
+       if (!bitmap_init(&own_ag_bitmap)) {
+               error = -ENOMEM;
+               goto err_slab;
+       }
+       while ((rm_rec = pop_slab_cursor(rm_cur)) != NULL) {
+               if (rm_rec->rm_owner != XFS_RMAP_OWN_AG)
+                       continue;
+               if (!bitmap_set(own_ag_bitmap, rm_rec->rm_startblock,
+                                       rm_rec->rm_blockcount)) {
+                       error = EFSCORRUPTED;
+                       goto err_slab;
+               }
+       }
+       free_slab_cursor(&rm_cur);
+
+       /* Create rmaps for any AGFL blocks that aren't already rmapped. */
        agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
-       b = agfl_bno + ag_rmaps[agno].ar_flcount;
-       while (*b != NULLAGBLOCK && b - agfl_bno < libxfs_agfl_size(mp)) {
-               error = rmap_add_ag_rec(mp, agno, be32_to_cpu(*b), 1,
-                               XFS_RMAP_OWN_AG);
-               if (error)
-                       goto err;
+       b = agfl_bno + ag_rmap->ar_flcount;
+       while (*b != cpu_to_be32(NULLAGBLOCK) &&
+              b - agfl_bno < libxfs_agfl_size(mp)) {
+               xfs_agblock_t   agbno;
+
+               agbno = be32_to_cpu(*b);
+               if (!bitmap_test(own_ag_bitmap, agbno, 1)) {
+                       error = rmap_add_ag_rec(mp, agno, agbno, 1,
+                                       XFS_RMAP_OWN_AG);
+                       if (error)
+                               goto err;
+               }
                b++;
        }
        libxfs_putbuf(agflbp);
        agflbp = NULL;
+       bitmap_free(&own_ag_bitmap);
 
        /* Merge all the raw rmaps into the main list */
        error = rmap_fold_raw_recs(mp, agno);
@@ -498,14 +531,15 @@ rmap_store_ag_btree_rec(
                goto err;
 
        /* Create cursors to refcount structures */
-       error = init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare,
-                       &rm_cur);
+       error = init_slab_cursor(ag_rmap->ar_rmaps, rmap_compare, &rm_cur);
        if (error)
                goto err;
 
        /* Insert rmaps into the btree one at a time */
        rm_rec = pop_slab_cursor(rm_cur);
        while (rm_rec) {
+               struct xfs_owner_info   oinfo = {};
+
                error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
                if (error)
                        goto err_slab;
@@ -515,7 +549,7 @@ rmap_store_ag_btree_rec(
                        goto err_trans;
 
                ASSERT(XFS_RMAP_NON_INODE_OWNER(rm_rec->rm_owner));
-               libxfs_rmap_ag_owner(&oinfo, rm_rec->rm_owner);
+               oinfo.oi_owner = rm_rec->rm_owner;
                error = -libxfs_rmap_alloc(tp, agbp, agno, rm_rec->rm_startblock,
                                rm_rec->rm_blockcount, &oinfo);
                if (error)
@@ -540,6 +574,8 @@ err_slab:
 err:
        if (agflbp)
                libxfs_putbuf(agflbp);
+       if (own_ag_bitmap)
+               bitmap_free(&own_ag_bitmap);
        return error;
 }
 
@@ -1297,7 +1333,7 @@ check_refcounts(
        pag->pagf_init = 0;
        libxfs_perag_put(pag);
 
-       bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL);
+       bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, agno);
        if (!bt_cur) {
                error = -ENOMEM;
                goto err;
@@ -1373,8 +1409,7 @@ fix_freelist(
        args.agno = agno;
        args.alignment = 1;
        args.pag = libxfs_perag_get(mp, agno);
-       error = -libxfs_trans_alloc_rollable(mp,
-                       libxfs_alloc_min_freelist(mp, args.pag), &tp);
+       error = -libxfs_trans_alloc_rollable(mp, 0, &tp);
        if (error)
                do_error(_("failed to fix AGFL on AG %d, error %d\n"),
                                agno, error);
@@ -1410,7 +1445,9 @@ fix_freelist(
                do_error(_("failed to fix AGFL on AG %d, error %d\n"),
                                agno, error);
        }
-       libxfs_trans_commit(tp);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(_("%s: commit failed, error %d\n"), __func__, error);
 }
 
 /*