]> 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>
Tue, 15 Oct 2024 19:44:38 +0000 (12:44 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 1 Nov 2024 20:44:58 +0000 (13:44 -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 3e521cd0c76063cbbfca3ec2c119cab98358eaf4..60033b0e7a4b722f8235b40f8bb81b279c7116f8 100644 (file)
 #define xfs_rtfree_extent              libxfs_rtfree_extent
 #define xfs_rtfree_blocks              libxfs_rtfree_blocks
 #define xfs_update_rtsb                        libxfs_update_rtsb
+#define xfs_rtgroup_get                        libxfs_rtgroup_get
 #define xfs_rtgroup_put                        libxfs_rtgroup_put
 #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_mount_rextsize          libxfs_sb_mount_rextsize
index 42bfeee9eafbcb854dddb578b0f8ca34fef96281..2135147fcf935468fa2b6430254e3731790140b7 100644 (file)
@@ -646,7 +646,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);
@@ -663,7 +663,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 82925da720d3d7a92d7b10fde6ad7517489ce957..47d6459709d762bfa9fdb99f2d31c594aaeee017 100644 (file)
@@ -708,7 +708,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, isrt);
                *tot += irec.br_blockcount;
        }
        error = 0;
index fa0afb61841348078646daf41419c62e1576703d..422c2f888aee88e26eef7369427e1eaebc4e60b8 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,17 @@ 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) {
+               agno = xfs_rtb_to_rgno(mp, irec->br_startblock);
+               agbno = xfs_rtb_to_rgbno(mp, irec->br_startblock);
+               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 +388,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 +415,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 +484,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 +493,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 +610,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 +873,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 +1006,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 +1116,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 +1242,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 +1562,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 +1575,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 +1778,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);