]> 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, 9 Jan 2024 17:40:19 +0000 (09:40 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 10 Apr 2024 00:21:44 +0000 (17:21 -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 724e8abf872313c2e717da1e54b823d293d4bbfe..495b258b0968b0b831a8d7718fe439051e3b918d 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_secondary_sbs       libxfs_rtgroup_update_secondary_sbs
 #define xfs_rtgroup_update_super       libxfs_rtgroup_update_super
 #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 976cbfa429eeb3fc6364db6af42de418a9016be3..292255ec004921bf2ac7705caf46122245cc479a 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 b535249bbc75c6fc3dca50d4e9da1144999ac3f0..6707accd52c1c6ca9be63d4232931633e18b5837 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(
@@ -141,6 +187,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]);
 }
 
 /*
@@ -155,6 +208,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);
@@ -190,22 +248,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;
 }
 
@@ -238,6 +306,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)
 {
@@ -246,12 +315,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"));
 
@@ -276,7 +345,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;
@@ -285,11 +355,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);
 
@@ -303,7 +381,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 */
@@ -330,7 +408,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);
 }
 
 /*
@@ -399,6 +477,7 @@ rmap_add_agbtree_mapping(
                .rm_blockcount  = len,
        };
        struct xfs_perag        *pag;
+       struct xfs_ag_rmap      *x;
 
        if (!rmap_needs_work(mp))
                return 0;
@@ -407,7 +486,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
@@ -523,7 +603,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;
 
@@ -786,7 +866,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",
@@ -919,12 +999,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;
 
@@ -1029,16 +1109,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));
@@ -1154,7 +1235,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;
@@ -1474,7 +1555,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);
 }
 
 /*
@@ -1485,7 +1568,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);
 }
 
 /*
@@ -1686,7 +1771,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 683a51af3fc511b5aabc291b32c1e6c15c383422..e2d61c0d239b76eae63e8f8eee6c62ea6b8a651d 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);
 
 #endif /* RMAP_H_ */