]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: create a new set of incore rmap information for rt groups
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:23 +0000 (14:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jul 2024 22:37:20 +0000 (15:37 -0700)
Create a parallel set of "xfs_ag_rmap" structures to cache information
about reverse mappings for the realtime groups.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/libxfs_api_defs.h
repair/agbtree.c
repair/dinode.c
repair/rmap.c
repair/rmap.h

index 89f3942d1a6250b0598fede347e751eba5b2df9f..2eace2577874c24e838da0c37e18455ff2fe057c 100644 (file)
 
 #define xfs_rtfree_extent              libxfs_rtfree_extent
 #define xfs_rtfree_blocks              libxfs_rtfree_blocks
+#define xfs_rtgroup_get                        libxfs_rtgroup_get
 #define xfs_rtgroup_put                        libxfs_rtgroup_put
 #define xfs_rtgroup_update_super       libxfs_rtgroup_update_super
 #define xfs_rtrmapbt_droot_maxrecs     libxfs_rtrmapbt_droot_maxrecs
 #define xfs_rtrmapbt_maxlevels_ondisk  libxfs_rtrmapbt_maxlevels_ondisk
 #define xfs_rtrmapbt_init_cursor       libxfs_rtrmapbt_init_cursor
 #define xfs_rtrmapbt_maxrecs           libxfs_rtrmapbt_maxrecs
+#define xfs_rtrmapbt_mem_init          libxfs_rtrmapbt_mem_init
+#define xfs_rtrmapbt_mem_cursor                libxfs_rtrmapbt_mem_cursor
 
 #define xfs_sb_from_disk               libxfs_sb_from_disk
 #define xfs_sb_quota_from_disk         libxfs_sb_quota_from_disk
index c8f75f49e6b36359efbf53710ac9b45cbe695a07..8910df9fe1ec0610e4f0523dc96a36757443b492 100644 (file)
@@ -647,7 +647,7 @@ init_rmapbt_cursor(
 
        /* Compute how many blocks we'll need. */
        error = -libxfs_btree_bload_compute_geometry(btr->cur, &btr->bload,
-                       rmap_record_count(sc->mp, agno));
+                       rmap_record_count(sc->mp, false, agno));
        if (error)
                do_error(
 _("Unable to compute rmap btree geometry, error %d.\n"), error);
@@ -664,7 +664,8 @@ build_rmap_tree(
 {
        int                     error;
 
-       error = rmap_init_mem_cursor(sc->mp, NULL, agno, &btr->rmapbt_cursor);
+       error = rmap_init_mem_cursor(sc->mp, NULL, false, agno,
+                       &btr->rmapbt_cursor);
        if (error)
                do_error(
 _("Insufficient memory to construct rmap cursor.\n"));
index 92eb19a38f53bbbbf4e8a21ac418311af3f8eb60..1f1f028ba35655d8d4f4b34df2d25f6124fa266f 100644 (file)
@@ -657,7 +657,7 @@ _("illegal state %d in block map %" PRIu64 "\n"),
                        }
                }
                if (collect_rmaps && !zap_metadata) /* && !check_dups */
-                       rmap_add_rec(mp, ino, whichfork, &irec);
+                       rmap_add_rec(mp, ino, whichfork, &irec, false);
                *tot += irec.br_blockcount;
        }
        error = 0;
index dc4a50085519439f8a43c8db5799bdba8b2e58c3..c6ae0f1b8fb7de3d4bc557f9c5139bb2c7b44bc7 100644 (file)
@@ -24,7 +24,7 @@
 # define dbg_printf(f, a...)
 #endif
 
-/* per-AG rmap object anchor */
+/* allocation group (AG or rtgroup) rmap object anchor */
 struct xfs_ag_rmap {
        /* root of rmap observations btree */
        struct xfbtree          ar_xfbtree;
@@ -42,9 +42,17 @@ struct xfs_ag_rmap {
 };
 
 static struct xfs_ag_rmap *ag_rmaps;
+static struct xfs_ag_rmap *rg_rmaps;
 bool rmapbt_suspect;
 static bool refcbt_suspect;
 
+static struct xfs_ag_rmap *rmaps_for_group(bool isrt, unsigned int group)
+{
+       if (isrt)
+               return &rg_rmaps[group];
+       return &ag_rmaps[group];
+}
+
 static inline int rmap_compare(const void *a, const void *b)
 {
        return libxfs_rmap_compare(a, b);
@@ -83,6 +91,44 @@ rmaps_destroy(
        xmbuf_free(ag_rmap->ar_xmbtp);
 }
 
+/* Initialize the in-memory rmap btree for collecting realtime rmap records. */
+STATIC void
+rmaps_init_rt(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno,
+       struct xfs_ag_rmap      *ag_rmap)
+{
+       char                    *descr;
+       unsigned long long      maxbytes;
+       int                     error;
+
+       if (!xfs_has_realtime(mp))
+               return;
+
+       /*
+        * Each rtgroup rmap btree file can consume the entire data device,
+        * even if the metadata space reservation will be smaller than that.
+        */
+       maxbytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks);
+       descr = kasprintf(GFP_KERNEL,
+                       "xfs_repair (%s): rtgroup %u rmap records",
+                       mp->m_fsname, rgno);
+       error = -xmbuf_alloc(mp, descr, maxbytes, &ag_rmap->ar_xmbtp);
+       kfree(descr);
+       if (error)
+               goto nomem;
+
+       error = -libxfs_rtrmapbt_mem_init(mp, &ag_rmap->ar_xfbtree,
+                       ag_rmap->ar_xmbtp, rgno);
+       if (error)
+               goto nomem;
+
+       return;
+nomem:
+       do_error(
+_("Insufficient memory while allocating realtime reverse mapping btree."));
+}
+
 /* Initialize the in-memory rmap btree for collecting per-AG rmap records. */
 STATIC void
 rmaps_init_ag(
@@ -150,6 +196,13 @@ rmaps_init(
 
        for (i = 0; i < mp->m_sb.sb_agcount; i++)
                rmaps_init_ag(mp, i, &ag_rmaps[i]);
+
+       rg_rmaps = calloc(mp->m_sb.sb_rgcount, sizeof(struct xfs_ag_rmap));
+       if (!rg_rmaps)
+               do_error(_("couldn't allocate per-rtgroup reverse map roots\n"));
+
+       for (i = 0; i < mp->m_sb.sb_rgcount; i++)
+               rmaps_init_rt(mp, i, &rg_rmaps[i]);
 }
 
 /*
@@ -164,6 +217,11 @@ rmaps_free(
        if (!rmap_needs_work(mp))
                return;
 
+       for (i = 0; i < mp->m_sb.sb_rgcount; i++)
+               rmaps_destroy(mp, &rg_rmaps[i]);
+       free(rg_rmaps);
+       rg_rmaps = NULL;
+
        for (i = 0; i < mp->m_sb.sb_agcount; i++)
                rmaps_destroy(mp, &ag_rmaps[i]);
        free(ag_rmaps);
@@ -199,22 +257,32 @@ int
 rmap_init_mem_cursor(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
+       bool                    isrt,
        xfs_agnumber_t          agno,
        struct xfs_btree_cur    **rmcurp)
 {
        struct xfbtree          *xfbt;
-       struct xfs_perag        *pag;
+       struct xfs_perag        *pag = NULL;
+       struct xfs_rtgroup      *rtg = NULL;
        int                     error;
 
-       xfbt = &ag_rmaps[agno].ar_xfbtree;
-       pag = libxfs_perag_get(mp, agno);
-       *rmcurp = libxfs_rmapbt_mem_cursor(pag, tp, xfbt);
+       xfbt = &rmaps_for_group(isrt, agno)->ar_xfbtree;
+       if (isrt) {
+               rtg = libxfs_rtgroup_get(mp, agno);
+               *rmcurp = libxfs_rtrmapbt_mem_cursor(rtg, tp, xfbt);
+       } else {
+               pag = libxfs_perag_get(mp, agno);
+               *rmcurp = libxfs_rmapbt_mem_cursor(pag, tp, xfbt);
+       }
 
        error = -libxfs_btree_goto_left_edge(*rmcurp);
        if (error)
                libxfs_btree_del_cursor(*rmcurp, error);
 
-       libxfs_perag_put(pag);
+       if (pag)
+               libxfs_perag_put(pag);
+       if (rtg)
+               libxfs_rtgroup_put(rtg);
        return error;
 }
 
@@ -247,6 +315,7 @@ rmap_get_mem_rec(
 static void
 rmap_add_mem_rec(
        struct xfs_mount        *mp,
+       bool                    isrt,
        xfs_agnumber_t          agno,
        struct xfs_rmap_irec    *rmap)
 {
@@ -255,12 +324,12 @@ rmap_add_mem_rec(
        struct xfs_trans        *tp;
        int                     error;
 
-       xfbt = &ag_rmaps[agno].ar_xfbtree;
+       xfbt = &rmaps_for_group(isrt, agno)->ar_xfbtree;
        error = -libxfs_trans_alloc_empty(mp, &tp);
        if (error)
                do_error(_("allocating tx for in-memory rmap update\n"));
 
-       error = rmap_init_mem_cursor(mp, tp, agno, &rmcur);
+       error = rmap_init_mem_cursor(mp, tp, isrt, agno, &rmcur);
        if (error)
                do_error(_("reading in-memory rmap btree head\n"));
 
@@ -285,7 +354,8 @@ rmap_add_rec(
        struct xfs_mount        *mp,
        xfs_ino_t               ino,
        int                     whichfork,
-       struct xfs_bmbt_irec    *irec)
+       struct xfs_bmbt_irec    *irec,
+       bool                    isrt)
 {
        struct xfs_rmap_irec    rmap;
        xfs_agnumber_t          agno;
@@ -294,11 +364,19 @@ rmap_add_rec(
        if (!rmap_needs_work(mp))
                return;
 
-       agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
-       agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
-       ASSERT(agno != NULLAGNUMBER);
-       ASSERT(agno < mp->m_sb.sb_agcount);
-       ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks);
+       if (isrt) {
+               xfs_rgnumber_t  rgno;
+
+               agbno = xfs_rtb_to_rgbno(mp, irec->br_startblock, &rgno);
+               agno = rgno;
+               ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_rblocks);
+       } else {
+               agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
+               agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
+               ASSERT(agno != NULLAGNUMBER);
+               ASSERT(agno < mp->m_sb.sb_agcount);
+               ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks);
+       }
        ASSERT(ino != NULLFSINO);
        ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
 
@@ -312,7 +390,7 @@ rmap_add_rec(
        if (irec->br_state == XFS_EXT_UNWRITTEN)
                rmap.rm_flags |= XFS_RMAP_UNWRITTEN;
 
-       rmap_add_mem_rec(mp, agno, &rmap);
+       rmap_add_mem_rec(mp, isrt, agno, &rmap);
 }
 
 /* add a raw rmap; these will be merged later */
@@ -339,7 +417,7 @@ __rmap_add_raw_rec(
        rmap.rm_startblock = agbno;
        rmap.rm_blockcount = len;
 
-       rmap_add_mem_rec(mp, agno, &rmap);
+       rmap_add_mem_rec(mp, false, agno, &rmap);
 }
 
 /*
@@ -408,6 +486,7 @@ rmap_add_agbtree_mapping(
                .rm_blockcount  = len,
        };
        struct xfs_perag        *pag;
+       struct xfs_ag_rmap      *x;
 
        if (!rmap_needs_work(mp))
                return 0;
@@ -416,7 +495,8 @@ rmap_add_agbtree_mapping(
        assert(libxfs_verify_agbext(pag, agbno, len));
        libxfs_perag_put(pag);
 
-       return slab_add(ag_rmaps[agno].ar_agbtree_rmaps, &rmap);
+       x = rmaps_for_group(false, agno);
+       return slab_add(x->ar_agbtree_rmaps, &rmap);
 }
 
 static int
@@ -532,7 +612,7 @@ rmap_commit_agbtree_mappings(
        struct xfs_buf          *agflbp = NULL;
        struct xfs_trans        *tp;
        __be32                  *agfl_bno, *b;
-       struct xfs_ag_rmap      *ag_rmap = &ag_rmaps[agno];
+       struct xfs_ag_rmap      *ag_rmap = rmaps_for_group(false, agno);
        struct bitmap           *own_ag_bitmap = NULL;
        int                     error = 0;
 
@@ -795,7 +875,7 @@ refcount_emit(
        int                     error;
        struct xfs_slab         *rlslab;
 
-       rlslab = ag_rmaps[agno].ar_refcount_items;
+       rlslab = rmaps_for_group(false, agno)->ar_refcount_items;
        ASSERT(nr_rmaps > 0);
 
        dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n",
@@ -928,12 +1008,12 @@ compute_refcounts(
 
        if (!xfs_has_reflink(mp))
                return 0;
-       if (!rmaps_has_observations(&ag_rmaps[agno]))
+       if (!rmaps_has_observations(rmaps_for_group(false, agno)))
                return 0;
 
-       nr_rmaps = rmap_record_count(mp, agno);
+       nr_rmaps = rmap_record_count(mp, false, agno);
 
-       error = rmap_init_mem_cursor(mp, NULL, agno, &rmcur);
+       error = rmap_init_mem_cursor(mp, NULL, false, agno, &rmcur);
        if (error)
                return error;
 
@@ -1038,16 +1118,17 @@ count_btree_records(
 uint64_t
 rmap_record_count(
        struct xfs_mount        *mp,
+       bool                    isrt,
        xfs_agnumber_t          agno)
 {
        struct xfs_btree_cur    *rmcur;
        uint64_t                nr = 0;
        int                     error;
 
-       if (!rmaps_has_observations(&ag_rmaps[agno]))
+       if (!rmaps_has_observations(rmaps_for_group(isrt, agno)))
                return 0;
 
-       error = rmap_init_mem_cursor(mp, NULL, agno, &rmcur);
+       error = rmap_init_mem_cursor(mp, NULL, isrt, agno, &rmcur);
        if (error)
                do_error(_("%s while reading in-memory rmap btree\n"),
                                strerror(error));
@@ -1163,7 +1244,7 @@ rmaps_verify_btree(
        }
 
        /* Create cursors to rmap structures */
-       error = rmap_init_mem_cursor(mp, NULL, agno, &rm_cur);
+       error = rmap_init_mem_cursor(mp, NULL, false, agno, &rm_cur);
        if (error) {
                do_warn(_("Not enough memory to check reverse mappings.\n"));
                return;
@@ -1483,7 +1564,9 @@ refcount_record_count(
        struct xfs_mount        *mp,
        xfs_agnumber_t          agno)
 {
-       return slab_count(ag_rmaps[agno].ar_refcount_items);
+       struct xfs_ag_rmap      *x = rmaps_for_group(false, agno);
+
+       return slab_count(x->ar_refcount_items);
 }
 
 /*
@@ -1494,7 +1577,9 @@ init_refcount_cursor(
        xfs_agnumber_t          agno,
        struct xfs_slab_cursor  **cur)
 {
-       return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur);
+       struct xfs_ag_rmap      *x = rmaps_for_group(false, agno);
+
+       return init_slab_cursor(x->ar_refcount_items, NULL, cur);
 }
 
 /*
@@ -1695,7 +1780,7 @@ rmap_store_agflcount(
        if (!rmap_needs_work(mp))
                return;
 
-       ag_rmaps[agno].ar_flcount = count;
+       rmaps_for_group(false, agno)->ar_flcount = count;
 }
 
 /* Estimate the size of the ondisk rmapbt from the incore data. */
index 57e5d5b216650e3a02bf8222e0b57db05e021519..23871e6d60e77485aa6d193f2b47e32fdb13b52e 100644 (file)
@@ -15,7 +15,7 @@ extern void rmaps_init(struct xfs_mount *);
 extern void rmaps_free(struct xfs_mount *);
 
 void rmap_add_rec(struct xfs_mount *mp, xfs_ino_t ino, int whichfork,
-               struct xfs_bmbt_irec *irec);
+               struct xfs_bmbt_irec *irec, bool realtime);
 void rmap_add_bmbt_rec(struct xfs_mount *mp, xfs_ino_t ino, int whichfork,
                xfs_fsblock_t fsbno);
 bool rmaps_are_mergeable(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2);
@@ -26,7 +26,8 @@ int rmap_add_agbtree_mapping(struct xfs_mount *mp, xfs_agnumber_t agno,
                xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner);
 int rmap_commit_agbtree_mappings(struct xfs_mount *mp, xfs_agnumber_t agno);
 
-uint64_t rmap_record_count(struct xfs_mount *mp, xfs_agnumber_t agno);
+uint64_t rmap_record_count(struct xfs_mount *mp, bool isrt,
+               xfs_agnumber_t agno);
 extern void rmap_avoid_check(void);
 void rmaps_verify_btree(struct xfs_mount *mp, xfs_agnumber_t agno);
 
@@ -52,7 +53,7 @@ xfs_extlen_t estimate_rmapbt_blocks(struct xfs_perag *pag);
 xfs_extlen_t estimate_refcountbt_blocks(struct xfs_perag *pag);
 
 int rmap_init_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp,
-               xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp);
+               bool isrt, xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp);
 int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec);
 
 xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino);