]> 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>
Fri, 15 Jul 2022 21:24:25 +0000 (14:24 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 22 Nov 2023 23:03:39 +0000 (15:03 -0800)
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 5d1f6b863f18a77b9818055a8be9524dbbd4ec84..161c3059dc3cf59b5c1e1cde949506dff03eacf2 100644 (file)
 #define xfs_rtsummary_wordcount                libxfs_rtsummary_wordcount
 
 #define xfs_rtfree_extent              libxfs_rtfree_extent
+#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_create                libxfs_rtrmapbt_mem_create
+#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 dccb15f966760ee17ee6fcfa73a0844d669971c4..a401c80da3834b99be384c215ddea0c0952b2a85 100644 (file)
@@ -645,7 +645,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);
@@ -662,7 +662,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 23cec00ad9ec27a82bda2df2f9f787f85459e789..41b44e6faad1d7d3c7a6c80b948fca7fcc339ddf 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 265199d21177ebb8f222c6b77b7ad1324e929b9a..aa47013baec1ebc98ae5aa9ee4de0197be706598 100644 (file)
@@ -26,7 +26,7 @@
 # define dbg_printf(f, a...)
 #endif
 
-/* per-AG rmap object anchor */
+/* allocation group (AG or rtgroup) rmap object anchor */
 struct xfs_ag_rmap {
        struct xfbtree  *ar_xfbtree;            /* rmap observations */
        struct xfs_slab *ar_agbtree_rmaps;      /* rmaps for rebuilt ag btrees */
@@ -36,9 +36,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);
@@ -76,6 +84,44 @@ rmaps_destroy(
        xfile_free_buftarg(target);
 }
 
+/* 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)
+{
+       struct xfs_buftarg      *target;
+       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("xfs_repair (%s): rtgroup %u rmap records",
+                       mp->m_fsname, rgno);
+       error = -xfile_alloc_buftarg(mp, descr, maxbytes, &target);
+       kfree(descr);
+       if (error)
+               goto nomem;
+
+       error = -libxfs_rtrmapbt_mem_create(mp, rgno, target,
+                       &ag_rmap->ar_xfbtree);
+       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(
@@ -135,6 +181,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]);
 }
 
 /*
@@ -149,6 +202,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);
@@ -184,26 +242,38 @@ int
 rmap_init_mem_cursor(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
+       bool                    isrt,
        xfs_agnumber_t          agno,
        struct rmap_mem_cur     *rmcur)
 {
        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;
+       xfbt = rmaps_for_group(isrt, agno)->ar_xfbtree;
        error = -xfbtree_head_read_buf(xfbt, tp, &rmcur->mhead_bp);
        if (error)
                return error;
 
-       pag = libxfs_perag_get(mp, agno);
-       rmcur->mcur = libxfs_rmapbt_mem_cursor(pag, tp, rmcur->mhead_bp, xfbt);
+       if (isrt) {
+               rtg = libxfs_rtgroup_get(mp, agno);
+               rmcur->mcur = libxfs_rtrmapbt_mem_cursor(rtg, tp,
+                               rmcur->mhead_bp, xfbt);
+       } else {
+               pag = libxfs_perag_get(mp, agno);
+               rmcur->mcur = libxfs_rmapbt_mem_cursor(pag, tp,
+                               rmcur->mhead_bp, xfbt);
+       }
 
        error = -libxfs_btree_goto_left_edge(rmcur->mcur);
        if (error)
                rmap_free_mem_cursor(tp, rmcur, error);
 
-       libxfs_perag_put(pag);
+       if (pag)
+               libxfs_perag_put(pag);
+       if (rtg)
+               libxfs_rtgroup_put(rtg);
        return error;
 }
 
@@ -248,6 +318,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)
 {
@@ -256,12 +327,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"));
 
@@ -286,7 +357,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;
@@ -295,11 +367,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);
 
@@ -313,7 +393,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 */
@@ -340,7 +420,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);
 }
 
 /*
@@ -409,6 +489,7 @@ rmap_add_agbtree_mapping(
                .rm_blockcount  = len,
        };
        struct xfs_perag        *pag;
+       struct xfs_ag_rmap      *x;
 
        if (!rmap_needs_work(mp))
                return 0;
@@ -417,7 +498,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
@@ -533,7 +615,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;
 
@@ -796,7 +878,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",
@@ -930,12 +1012,12 @@ compute_refcounts(
 
        if (!xfs_has_reflink(mp))
                return 0;
-       if (ag_rmaps[agno].ar_xfbtree == NULL)
+       if (rmaps_for_group(false, agno)->ar_xfbtree == NULL)
                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;
 
@@ -1040,16 +1122,17 @@ count_btree_records(
 uint64_t
 rmap_record_count(
        struct xfs_mount        *mp,
+       bool                    isrt,
        xfs_agnumber_t          agno)
 {
        struct rmap_mem_cur     rmcur;
        uint64_t                nr = 0;
        int                     error;
 
-       if (ag_rmaps[agno].ar_xfbtree == NULL)
+       if (rmaps_for_group(isrt, agno)->ar_xfbtree == NULL)
                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));
@@ -1165,7 +1248,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;
@@ -1485,7 +1568,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);
 }
 
 /*
@@ -1496,7 +1581,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);
 }
 
 /*
@@ -1697,7 +1784,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 50268b2f8ca74f80fff7e52158f326586fc8dc68..7a94ed6f90aef798e2da8d8681bdcf9cf5df1948 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);
 
@@ -57,7 +58,7 @@ struct rmap_mem_cur {
 };
 
 int rmap_init_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp,
-               xfs_agnumber_t agno, struct rmap_mem_cur *rmcur);
+               bool isrt, xfs_agnumber_t agno, struct rmap_mem_cur *rmcur);
 void rmap_free_mem_cursor(struct xfs_trans *tp, struct rmap_mem_cur *rmcur,
                int error);
 int rmap_get_mem_rec(struct rmap_mem_cur *rmcur, struct xfs_rmap_irec *irec);