]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
fixup xfs-per-rtg-bitmap
authorChristoph Hellwig <hch@lst.de>
Wed, 31 Jul 2024 14:42:04 +0000 (07:42 -0700)
committerChristoph Hellwig <hch@lst.de>
Thu, 1 Aug 2024 01:27:14 +0000 (18:27 -0700)
Now also loads rtbitmap/summary inodes early.  Uses the AG btree based code
in repair.  Needs to be maybe split and grow an actual commit log.

Signed-off-by: Christoph Hellwig <hch@lst.de>
24 files changed:
db/block.c
db/frag.c
db/inode.c
db/inode.h
db/metadump.c
include/xfs_mount.h
libxfs/defer_item.c
libxfs/init.c
libxfs/trans.c
mkfs/proto.c
mkfs/xfs_mkfs.c
repair/bmap_repair.c
repair/dinode.c
repair/dir2.c
repair/incore.c
repair/incore.h
repair/incore_ext.c
repair/phase2.c
repair/phase4.c
repair/phase6.c
repair/rt.c
repair/rt.h
repair/scan.c
repair/xfs_repair.c

index e8326f78005de75b873098339d75d5bcf94a8659..dc7c830ccdff8c3a0fd7e4ed7ca552c34cdb1140 100644 (file)
@@ -395,7 +395,7 @@ rtextent_f(
        char            **argv)
 {
        xfs_rtblock_t   rtbno;
-       xfs_rtxnum_t    rtx;
+       uint64_t        rtx;
        char            *p;
 
        if (argc == 1) {
@@ -419,7 +419,11 @@ rtextent_f(
                return 0;
        }
 
-       rtbno = xfs_rtx_to_rtb(mp, rtx);
+       /*
+        * The user interface assumes a global RT extent number, while the
+        * in-kernel rtx is per-RTG now, thus the open coded conversion here.
+        */
+       rtbno = rtx * mp->m_sb.sb_rextsize;
        ASSERT(typtab[TYP_DATA].typnm == TYP_DATA);
        set_rt_cur(&typtab[TYP_DATA], XFS_FSB_TO_BB(mp, rtbno),
                        mp->m_sb.sb_rextsize * blkbb, DB_RING_ADD, NULL);
index 1165e824a375e73793509528262ea5fb094c4f0d..10c17e2f59953b046fb58a4828a7631c73b6e991 100644 (file)
--- a/db/frag.c
+++ b/db/frag.c
 #include "output.h"
 #include "type.h"
 #include "init.h"
+#include "faddr.h"
+#include "fprint.h"
+#include "field.h"
+#include "inode.h"
 #include "malloc.h"
 
 typedef struct extent {
@@ -148,9 +152,17 @@ frag_f(
 {
        xfs_agnumber_t  agno;
        double          answer;
+       int             ret;
 
        if (!init(argc, argv))
                return 0;
+
+       ret = init_rtmeta_inode_bitmaps(mp);
+       if (ret) {
+               dbprintf(_("error %d setting up rt metadata inode bitmaps\n"),
+                               ret);
+               return 3;
+       }
        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
                scan_ag(agno);
        if (extcount_actual)
@@ -314,7 +326,9 @@ process_inode(
                        skipd = 1;
                else if (!Rflag &&
                         (ino == mp->m_sb.sb_rbmino ||
-                         ino == mp->m_sb.sb_rsumino))
+                         is_rtbitmap_inode(ino) ||
+                         ino == mp->m_sb.sb_rsumino ||
+                         is_rtsummary_inode(ino)))
                        skipd = 1;
                else if (!qflag &&
                         (ino == mp->m_sb.sb_uquotino ||
index 4f813c9947ece093fdc6cbb7843a55099f9dd1cf..5d2f06411ccfd69978e094672440b6b9f5a0f5d5 100644 (file)
@@ -756,11 +756,13 @@ inode_next_type(void)
        case S_IFLNK:
                return TYP_SYMLINK;
        case S_IFREG:
-               if (iocur_top->ino == mp->m_sb.sb_rbmino) {
+               if (iocur_top->ino == mp->m_sb.sb_rbmino ||
+                   is_rtbitmap_inode(iocur_top->ino)) {
                        if (xfs_has_rtgroups(mp))
                                return TYP_RGBITMAP;
                        return TYP_RTBITMAP;
-               } else if (iocur_top->ino == mp->m_sb.sb_rsumino) {
+               } else if (iocur_top->ino == mp->m_sb.sb_rsumino ||
+                          is_rtsummary_inode(iocur_top->ino)) {
                        if (xfs_has_rtgroups(mp))
                                return TYP_RGSUMMARY;
                        return TYP_RTSUMMARY;
index 0f62d84e9cfae5544c9299c41e4ee6e495c8aa51..84b68150c1f36db28e328fafb78d50422c548990 100644 (file)
@@ -36,6 +36,15 @@ rtgroup_for_rtrmap_ino(struct xfs_mount *mp, xfs_ino_t ino)
 
 bool is_rtgroup_inode(xfs_ino_t ino, enum xfs_rtg_inodes type);
 
+static inline bool is_rtbitmap_inode(xfs_ino_t ino)
+{
+       return is_rtgroup_inode(ino, XFS_RTG_BITMAP);
+}
+static inline bool is_rtsummary_inode(xfs_ino_t ino)
+{
+       return is_rtgroup_inode(ino, XFS_RTG_SUMMARY);
+}
+
 static inline bool is_rtrmap_inode(xfs_ino_t ino)
 {
        return is_rtgroup_inode(ino, XFS_RTG_RMAP);
index f33d375badcf0176cad81e97595c6aeaacb5e4d7..639a78822682a50fe673d62bda1c7ccb65753eb9 100644 (file)
@@ -18,6 +18,7 @@
 #include "fprint.h"
 #include "faddr.h"
 #include "field.h"
+#include "inode.h"
 #include "dir2.h"
 #include "obfuscate.h"
 
@@ -2103,9 +2104,11 @@ ifork_data_type(
        case S_IFLNK:
                return TYP_SYMLINK;
        case S_IFREG:
-               if (ino == mp->m_sb.sb_rbmino)
+               if (ino == mp->m_sb.sb_rbmino ||
+                   is_rtbitmap_inode(ino))
                        return TYP_RTBITMAP;
-               if (ino == mp->m_sb.sb_rsumino)
+               if (ino == mp->m_sb.sb_rsumino ||
+                   is_rtsummary_inode(ino))
                        return TYP_RTSUMMARY;
                if (ino == mp->m_sb.sb_uquotino)
                        return TYP_DQBLK;
@@ -3539,6 +3542,14 @@ metadump_f(
                }
        }
 
+       ret = init_rtmeta_inode_bitmaps(mp);
+       if (ret) {
+               dbprintf(_("error %d setting up rt metadata inode bitmaps\n"),
+                               ret);
+               exitcode = 3;
+               goto out;
+       }
+
        if (metadump.version == 1)
                metadump.mdops = &metadump1_ops;
        else
index c1da387939ff9006fcc8a1a26d2de0f8b9e0f82a..3f518ba468b2273054d84da515656d3f89a8b09e 100644 (file)
@@ -54,15 +54,6 @@ typedef struct xfs_mount {
        uint                    m_rsumlevels;   /* rt summary levels */
        uint                    m_rsumsize;     /* size of rt summary, bytes */
        uint32_t                m_rgblocks;     /* size of rtgroup in rtblocks */
-       /*
-        * Optional cache of rt summary level per bitmap block with the
-        * invariant that m_rsum_cache[bbno] <= the minimum i for which
-        * rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip
-        * inode lock.
-        */
-       uint8_t                 *m_rsum_cache;
-       struct xfs_inode        *m_rbmip;       /* pointer to bitmap inode */
-       struct xfs_inode        *m_rsumip;      /* pointer to summary inode */
        struct xfs_inode        *m_metadirip;   /* ptr to metadata directory */
        struct xfs_inode        *m_rtdirip;     /* ptr to realtime metadir */
        struct xfs_buftarg      *m_ddev_targp;
index a9d17fbb45355509e8118a3eb4f344806ae2b928..9ebaa9f1fcda4ebf2e3f6af53916463e8c35fc92 100644 (file)
@@ -214,7 +214,7 @@ xfs_rtextent_free_finish_item(
        struct xfs_extent_free_item     *xefi = xefi_entry(item);
        int                             error;
 
-       error = xfs_rtfree_blocks(tp, xefi->xefi_startblock,
+       error = xfs_rtfree_blocks(tp, xefi->xefi_rtg, xefi->xefi_startblock,
                        xefi->xefi_blockcount);
        if (error != -EAGAIN)
                xfs_rtextent_free_cancel_item(item);
index 0edde09d85acfd7e8247a795fcb959510c763cdf..36d61d73e96096e5187c2848097fb22ab191c168 100644 (file)
@@ -313,11 +313,10 @@ rtmount_init(
                        progname);
                return -1;
        }
-       mp->m_rsumlevels = mp->m_sb.sb_rextslog + 1;
+       mp->m_rsumlevels = xfs_compute_rsumlevels(mp, mp->m_sb.sb_rextents);
        rsumblocks = xfs_rtsummary_blockcount(mp, mp->m_rsumlevels,
                        mp->m_sb.sb_rbmblocks);
        mp->m_rsumsize = XFS_FSB_TO_B(mp, rsumblocks);
-       mp->m_rbmip = mp->m_rsumip = NULL;
 
        /*
         * Allow debugger to be run without the realtime device present.
@@ -893,10 +892,8 @@ libxfs_mount(
                exit(1);
        }
 
-       for_each_rtgroup(mp, rgno, rtg) {
-               rtg->rtg_blockcount = xfs_rtgroup_block_count(mp,
-                                                             rtg->rtg_rgno);
-       }
+       for_each_rtgroup(mp, rgno, rtg)
+               rtg->rtg_extents = xfs_rtgroup_extents(mp, rtg->rtg_rgno);
 
        xfs_set_rtgroup_data_loaded(mp);
 
@@ -921,13 +918,9 @@ libxfs_rtmount_destroy(
                        rtg->rtg_inodes[i] = NULL;
                }
        }
+
        if (mp->m_rtdirip)
                libxfs_irele(mp->m_rtdirip);
-       if (mp->m_rsumip)
-               libxfs_irele(mp->m_rsumip);
-       if (mp->m_rbmip)
-               libxfs_irele(mp->m_rbmip);
-       mp->m_rsumip = mp->m_rbmip = mp->m_rtdirip = NULL;
 }
 
 /* Flush a device and report on writes that didn't make it to stable storage. */
index 01834eff4b77cae1376d2904750dadd24ff956bf..271a22c6b844369998cd568c0cb7d8e77a82d4b9 100644 (file)
@@ -1202,7 +1202,7 @@ libxfs_trans_alloc_inode(
        int                     error;
 
        error = libxfs_trans_alloc(mp, resv, dblocks,
-                       xfs_rtb_to_rtx(mp, rblocks),
+                       xfs_blen_to_rtbxlen(mp, rblocks),
                        force ? XFS_TRANS_RESERVE : 0, &tp);
        if (error)
                return error;
index c63eac4acd178ad4620d9b7bbff4f54a46b50ea2..a0683481cfd467a516a18eb369bd96be420da330 100644 (file)
@@ -801,17 +801,22 @@ out_rele:
 
 static void
 create_sb_metadata_file(
-       struct xfs_mount        *mp,
-       void                    (*create)(struct xfs_inode *ip))
+       struct xfs_rtgroup      *rtg,
+       enum xfs_rtg_inodes     type,
+       int                     (*create)(struct xfs_rtgroup *rtg,
+                                       struct xfs_inode *ip,
+                                       struct xfs_trans *tp,
+                                       bool init))
 {
+       struct xfs_mount        *mp = rtg->rtg_mount;
        struct xfs_icreate_args args = {
                .mode           = S_IFREG,
                .flags          = XFS_ICREATE_UNLINKABLE,
        };
+       struct xfs_inode        *ip;
+       struct xfs_trans        *tp;
        xfs_ino_t               ino;
        int                     error;
-       struct xfs_trans        *tp;
-       struct xfs_inode        *ip;
 
        error = -libxfs_trans_alloc_rollable(mp, MKFS_BLOCKRES_INODE, &tp);
        if (error)
@@ -828,57 +833,43 @@ create_sb_metadata_file(
        if (xfs_has_metadir(mp))
                libxfs_metafile_set_iflag(tp, ip);
 
-       create(ip);
+       error = -create(rtg, ip, tp, true);
+       if (error)
+               goto fail;
 
-       libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+       switch (type) {
+       case XFS_RTG_BITMAP:
+               mp->m_sb.sb_rbmino = ino;
+               break;
+       case XFS_RTG_SUMMARY:
+               mp->m_sb.sb_rsumino = ino;
+               break;
+       default:
+               fail(_("Incorrect SB inode type"), EINVAL);
+               break;
+       }
        libxfs_log_sb(tp);
 
        error = -libxfs_trans_commit(tp);
        if (error)
                goto fail;
+       rtg->rtg_inodes[type] = ip;
        return;
+
 fail:
        if (error)
                fail(_("Realtime inode allocation failed"), error);
 }
 
-/* Create the realtime bitmap inode. */
-static void
-rtbitmap_create(
-       struct xfs_inode        *ip)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-
-       ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
-       ip->i_diflags |= XFS_DIFLAG_NEWRTBM;
-       if (!xfs_has_rtgroups(mp))
-               inode_set_atime(VFS_I(ip), 0, 0);
-
-       mp->m_sb.sb_rbmino = ip->i_ino;
-       mp->m_rbmip = ip;
-}
-
-/* Create the realtime summary inode. */
-static void
-rtsummary_create(
-       struct xfs_inode        *ip)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-
-       ip->i_disk_size = mp->m_rsumsize;
-
-       mp->m_sb.sb_rsumino = ip->i_ino;
-       mp->m_rsumip = ip;
-}
-
 /*
  * Free the whole realtime area using transactions.  Each transaction may clear
  * up to 32 rtbitmap blocks.
  */
 static void
 rtfreesp_init(
-       struct xfs_mount        *mp)
+       struct xfs_rtgroup      *rtg)
 {
+       struct xfs_mount        *mp = rtg->rtg_mount;
        struct xfs_trans        *tp;
        const xfs_rtxnum_t      max_rtx = mp->m_rtx_per_rbmblock * 32;
        xfs_rtxnum_t            start_rtx = 0;
@@ -887,32 +878,34 @@ rtfreesp_init(
        /*
         * First zero the realtime bitmap and summary files.
         */
-       error = -libxfs_rtfile_initialize_blocks(mp->m_rbmip, 0,
+       error = -libxfs_rtfile_initialize_blocks(rtg, XFS_RTG_BITMAP, 0,
                        mp->m_sb.sb_rbmblocks, NULL);
        if (error)
                fail(_("Initialization of rtbitmap inode failed"), error);
 
-       error = -libxfs_rtfile_initialize_blocks(mp->m_rsumip, 0,
+       error = -libxfs_rtfile_initialize_blocks(rtg, XFS_RTG_SUMMARY, 0,
                        XFS_B_TO_FSB(mp, mp->m_rsumsize), NULL);
        if (error)
                fail(_("Initialization of rtsummary inode failed"), error);
 
+       if (!mp->m_sb.sb_rbmblocks)
+               return;
+
        /*
         * Then free the blocks into the allocator, one bitmap block at a time.
         */
-       while (start_rtx < mp->m_sb.sb_rextents) {
-               xfs_rtxlen_t    nr = min(mp->m_sb.sb_rextents - start_rtx,
-                                        max_rtx);
+       while (start_rtx < rtg->rtg_extents) {
+               xfs_rtxlen_t    nr = min(rtg->rtg_extents - start_rtx, max_rtx);
 
                /*
                 * The rt superblock, if present, must not be marked free.
                 * This may be the only rtx in the entire volume.
                 */
-               if (xfs_has_rtsb(mp) && start_rtx == 0) {
+               if (xfs_has_rtsb(mp) && rtg->rtg_rgno == 0 && start_rtx == 0) {
                        start_rtx++;
                        nr--;
 
-                       if (start_rtx == mp->m_sb.sb_rextents)
+                       if (start_rtx == rtg->rtg_extents)
                                break;
                }
 
@@ -921,13 +914,15 @@ rtfreesp_init(
                if (error)
                        res_failed(error);
 
-               libxfs_trans_ijoin(tp, mp->m_rbmip, 0);
-               error = -libxfs_rtfree_extent(tp, start_rtx, nr);
+               libxfs_trans_ijoin(tp, rtg->rtg_inodes[XFS_RTG_BITMAP], 0);
+               error = -libxfs_rtfree_extent(tp, rtg, start_rtx, nr);
                if (error) {
                        fprintf(stderr,
- _("Error initializing the realtime free space near rtx 0x%llx-0x%llx: %s"),
+ _("Error initializing the realtime free space near rgno %u rtx %lld-%lld (max %lld): %s\n"),
+                                       rtg->rtg_rgno,
                                        (unsigned long long)start_rtx,
                                        (unsigned long long)start_rtx + nr - 1,
+                                       (unsigned long long)rtg->rtg_extents,
                                        strerror(error));
                        exit(1);
                }
@@ -941,9 +936,11 @@ rtfreesp_init(
        }
 }
 
-/* Allocate rtgroup inodes and directory tree. */
+/*
+ * Allocate the realtime bitmap and summary inodes, and fill in data if any.
+ */
 static void
-rtgroups_create(
+rtinit(
        struct xfs_mount        *mp)
 {
        struct xfs_rtgroup      *rtg;
@@ -951,36 +948,32 @@ rtgroups_create(
        unsigned int            i;
        int                     error;
 
-       error = -libxfs_rtginode_mkdir_parent(mp);
-       if (error)
-               fail(_("rtgroup directory allocation failed"), error);
+       if (xfs_has_rtgroups(mp)) {
+               error = -libxfs_rtginode_mkdir_parent(mp);
+               if (error)
+                       fail(_("rtgroup directory allocation failed"), error);
+       }
 
        for_each_rtgroup(mp, rgno, rtg) {
-               for (i = 0; i < XFS_RTG_MAX; i++) {
-                       error = -libxfs_rtginode_create(rtg, i, true);
-                       if (error)
-                               fail(_("rt group inode creation failed"),
-                                               error);
+               if (!xfs_has_rtgroups(mp)) {
+                       create_sb_metadata_file(rtg, XFS_RTG_BITMAP,
+                                       xfs_rtbitmap_create);
+                       create_sb_metadata_file(rtg, XFS_RTG_SUMMARY,
+                                       xfs_rtsummary_create);
+               } else {
+
+                       for (i = 0; i < XFS_RTG_MAX; i++) {
+                               error = -libxfs_rtginode_create(rtg, i, true);
+                               if (error)
+                                       fail(_("rt group inode creation failed"),
+                                                       error);
+                       }
                }
+       
+               rtfreesp_init(rtg);
        }
 }
 
-/*
- * Allocate the realtime bitmap and summary inodes, and fill in data if any.
- */
-static void
-rtinit(
-       struct xfs_mount        *mp)
-{
-       create_sb_metadata_file(mp, rtbitmap_create);
-       create_sb_metadata_file(mp, rtsummary_create);
-
-       if (xfs_has_rtgroups(mp))
-               rtgroups_create(mp);
-
-       rtfreesp_init(mp);
-}
-
 static long
 filesize(
        int             fd)
index 2690f5dca2c48082190df44ba21531a7902599ae..fc24812c73b83b7eb4da9568dcc0b6e79eb6e021 100644 (file)
@@ -3378,7 +3378,6 @@ validate_rtdev(
        struct cli_params       *cli)
 {
        struct libxfs_init      *xi = cli->xi;
-       unsigned int            rbmblocksize = cfg->blocksize;
 
        if (!xi->rt.dev) {
                if (cli->rtsize) {
@@ -3422,10 +3421,13 @@ reported by the device (%u).\n"),
 _("cannot have an rt subvolume with zero extents\n"));
                usage();
        }
-       if (cfg->sb_feat.rtgroups)
-               rbmblocksize -= sizeof(struct xfs_rtbuf_blkinfo);
+
+       /*
+        * Note for rtgroup file systems this will be overriden in
+        * calculate_rtgroup_geometry.
+        */
        cfg->rtbmblocks = (xfs_extlen_t)howmany(cfg->rtextents,
-                                               NBBY * rbmblocksize);
+                                               NBBY * cfg->blocksize);
 }
 
 static bool
@@ -3843,6 +3845,9 @@ _("realtime group count (%llu) must be less than the maximum (%u)\n"),
                                XFS_MAX_RGNUMBER);
                usage();
        }
+
+       cfg->rtbmblocks = howmany(cfg->rgsize / cfg->rtextblocks,
+               NBBY * (cfg->blocksize - sizeof(struct xfs_rtbuf_blkinfo)));
 }
 
 static void
@@ -3941,6 +3946,10 @@ sb_set_features(
         */
        sbp->sb_bad_features2 = sbp->sb_features2;
 
+       /* This will be overriden later for real rtgroup file systems: */
+       sbp->sb_rgcount = 1;
+       sbp->sb_rgextents = UINT_MAX;
+
        if (!fp->crcs_enabled)
                return;
 
index eca8cfe250a5c758b2317bc247053ae6e0acc5ea..36f93124eec756acb8ce4ba1eb8f61ab50bfadeb 100644 (file)
@@ -322,11 +322,13 @@ xrep_bmap_find_mappings(
        int                     error;
 
        /* Iterate the rtrmaps for extents. */
-       for_each_rtgroup(rb->sc->mp, rgno, rtg) {
-               error = xrep_bmap_scan_rt(rb, rtg);
-               if (error) {
-                       libxfs_rtgroup_put(rtg);
-                       return error;
+       if (xfs_has_rtgroups(rb->sc->mp)) {
+               for_each_rtgroup(rb->sc->mp, rgno, rtg) {
+                       error = xrep_bmap_scan_rt(rb, rtg);
+                       if (error) {
+                               libxfs_rtgroup_put(rtg);
+                               return error;
+                       }
                }
        }
 
index dd35bc8b8250896d96ba581788d09e481d3d1ce1..f6b5f858b527f8ae1ff974a2c8eec14aa1e65907 100644 (file)
@@ -178,19 +178,32 @@ clear_dinode(xfs_mount_t *mp, struct xfs_dinode *dino, xfs_ino_t ino_num)
 static __inline int
 verify_dfsbno_range(
        struct xfs_mount        *mp,
-       xfs_fsblock_t           fsbno,
-       xfs_filblks_t           count)
+       struct xfs_bmbt_irec    *irec,
+       bool                    isrt)
 {
+       xfs_fsblock_t           end =
+               irec->br_startblock + irec->br_blockcount - 1;
+
        /* the start and end blocks better be in the same allocation group */
-       if (XFS_FSB_TO_AGNO(mp, fsbno) !=
-           XFS_FSB_TO_AGNO(mp, fsbno + count - 1)) {
-               return XR_DFSBNORANGE_OVERFLOW;
-       }
+       if (isrt) {
+               if (xfs_rtb_to_rgno(mp, irec->br_startblock) !=
+                   xfs_rtb_to_rgno(mp, end))
+                       return XR_DFSBNORANGE_OVERFLOW;
+
+               if (!libxfs_verify_rtbno(mp, irec->br_startblock))
+                       return XR_DFSBNORANGE_BADSTART;
+               if (!libxfs_verify_rtbno(mp, end))
+                       return XR_DFSBNORANGE_BADEND;
+       } else {
+               if (XFS_FSB_TO_AGNO(mp, irec->br_startblock) !=
+                   XFS_FSB_TO_AGNO(mp, end))
+                       return XR_DFSBNORANGE_OVERFLOW;
 
-       if (!libxfs_verify_fsbno(mp, fsbno))
-               return XR_DFSBNORANGE_BADSTART;
-       if (!libxfs_verify_fsbno(mp, fsbno + count - 1))
-               return XR_DFSBNORANGE_BADEND;
+               if (!libxfs_verify_fsbno(mp, irec->br_startblock))
+                       return XR_DFSBNORANGE_BADSTART;
+               if (!libxfs_verify_fsbno(mp, end))
+                       return XR_DFSBNORANGE_BADEND;
+       }
 
        return XR_DFSBNORANGE_VALID;
 }
@@ -479,17 +492,21 @@ process_bmbt_reclist_int(
        xfs_extnum_t            i;
        int                     state;
        xfs_agnumber_t          agno;
-       xfs_agblock_t           agbno;
+       xfs_agblock_t           agbno, first_agbno;
        xfs_agblock_t           ebno;
        xfs_extlen_t            blen;
        xfs_agnumber_t          locked_agno = -1;
        int                     error = 1;
        int                     error2;
+       bool                    isrt = false;
 
-       if (type == XR_INO_RTDATA)
+       if (type == XR_INO_RTDATA) {
+               if (whichfork == XFS_DATA_FORK)
+                       isrt = true;
                ftype = ftype_real_time;
-       else
+       } else {
                ftype = ftype_regular;
+       }
 
        for (i = 0; i < *numrecs; i++) {
                libxfs_bmbt_disk_get_all((rp +i), &irec);
@@ -544,7 +561,7 @@ _("zero length extent (off = %" PRIu64 ", fsbno = %" PRIu64 ") in ino %" PRIu64
                        goto done;
                }
 
-               if (type == XR_INO_RTDATA && whichfork == XFS_DATA_FORK) {
+               if (isrt && !xfs_has_rtgroups(mp)) {
                        pthread_mutex_lock(&rt_lock.lock);
                        error2 = process_rt_rec(mp, &irec, ino, tot, check_dups,
                                        zap_metadata);
@@ -562,8 +579,7 @@ _("zero length extent (off = %" PRIu64 ", fsbno = %" PRIu64 ") in ino %" PRIu64
                /*
                 * regular file data fork or attribute fork
                 */
-               switch (verify_dfsbno_range(mp, irec.br_startblock,
-                                               irec.br_blockcount)) {
+               switch (verify_dfsbno_range(mp, &irec, isrt)) {
                        case XR_DFSBNORANGE_VALID:
                                break;
 
@@ -626,12 +642,23 @@ _("Fatal error: inode %" PRIu64 " - blkmap_set_ext(): %s\n"
                }
 
                /*
-                * Profiling shows that the following loop takes the
-                * most time in all of xfs_repair.
+                * For rtgroup enabled file systems we treat the RTGs as
+                * basically another set of AGs tacked on at the end, but
+                * otherwise reuse all the existing code.  That's why we'll
+                * see odd "agno" value here.
                 */
-               agno = XFS_FSB_TO_AGNO(mp, irec.br_startblock);
-               agbno = XFS_FSB_TO_AGBNO(mp, irec.br_startblock);
-               ebno = agbno + irec.br_blockcount;
+               if (isrt) {
+                       xfs_rgnumber_t rgno;
+
+                       first_agbno = xfs_rtb_to_rgbno(mp, irec.br_startblock,
+                                       &rgno);
+                       agno = mp->m_sb.sb_agcount + rgno;
+               } else {
+                       agno = XFS_FSB_TO_AGNO(mp, irec.br_startblock);
+                       first_agbno = XFS_FSB_TO_AGBNO(mp, irec.br_startblock);
+               }
+               agbno = first_agbno;
+               ebno = first_agbno + irec.br_blockcount;
                if (agno != locked_agno) {
                        if (locked_agno != -1)
                                pthread_mutex_unlock(&ag_locks[locked_agno].lock);
@@ -639,12 +666,23 @@ _("Fatal error: inode %" PRIu64 " - blkmap_set_ext(): %s\n"
                        locked_agno = agno;
                }
 
+               /*
+                * Profiling shows that the following loop takes the most time
+                * in all of xfs_repair.
+                */
                for (b = irec.br_startblock;
                     agbno < ebno;
                     b += blen, agbno += blen) {
                        state = get_bmap_ext(agno, agbno, ebno, &blen);
                        switch (state)  {
                        case XR_E_FREE:
+                               /*
+                                * We never do a scan pass of the rt bitmap, so unknown
+                                * blocks are marked as free.
+                                */
+                               if (isrt)
+                                       break;
+                               fallthrough;
                        case XR_E_FREE1:
                                do_warn(
 _("%s fork in ino %" PRIu64 " claims free block %" PRIu64 "\n"),
@@ -678,7 +716,8 @@ _("%s fork in inode %" PRIu64 " claims metadata block %" PRIu64 "\n"),
 
                        case XR_E_INUSE:
                        case XR_E_MULT:
-                               if (type == XR_INO_DATA &&
+                               if ((type == XR_INO_DATA ||
+                                    type == XR_INO_RTDATA) &&
                                    xfs_has_reflink(mp)) {
                                        if (irec.br_state == XFS_EXT_NORM)
                                                break;
@@ -724,8 +763,8 @@ _("illegal state %d in block map %" PRIu64 "\n"),
                 * After a successful rebuild we'll try this scan again.
                 * (If the rebuild fails we won't come back here.)
                 */
-               agbno = XFS_FSB_TO_AGBNO(mp, irec.br_startblock);
-               ebno = agbno + irec.br_blockcount;
+               agbno = first_agbno;
+               ebno = first_agbno + irec.br_blockcount;
                for (; agbno < ebno; agbno += blen) {
                        state = get_bmap_ext(agno, agbno, ebno, &blen);
                        switch (state)  {
@@ -757,7 +796,7 @@ _("illegal state %d in block map %" PRIu64 "\n"),
                        }
                }
                if (collect_rmaps && !zap_metadata) /* && !check_dups */
-                       rmap_add_rec(mp, ino, whichfork, &irec, false);
+                       rmap_add_rec(mp, ino, whichfork, &irec, isrt);
                *tot += irec.br_blockcount;
        }
        error = 0;
@@ -2039,6 +2078,7 @@ _("bad # of extents (%" PRIu64 ") for %s inode %" PRIu64 "\n"),
  * Returns 0 if it's valid, non-zero if it needs to be cleared.
  */
 
+/* XXX: this isn't just sb but metadata inodes now? */
 static int
 process_check_sb_inodes(
        xfs_mount_t             *mp,
@@ -2088,10 +2128,12 @@ process_check_sb_inodes(
                }
                return 0;
        }
-       if (lino == mp->m_sb.sb_rsumino)
+       if (lino == mp->m_sb.sb_rsumino ||
+           is_rtsummary_inode(lino))
                return process_check_rt_inode(mp, dinoc, lino, type, dirty,
                                XR_INO_RTSUM, _("realtime summary"));
-       if (lino == mp->m_sb.sb_rbmino)
+       if (lino == mp->m_sb.sb_rbmino ||
+           is_rtbitmap_inode(lino))
                return process_check_rt_inode(mp, dinoc, lino, type, dirty,
                                XR_INO_RTBITMAP, _("realtime bitmap"));
        if (is_rtrmap_inode(lino))
@@ -3425,9 +3467,11 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
        case S_IFREG:
                if (be16_to_cpu(dino->di_flags) & XFS_DIFLAG_REALTIME)
                        type = XR_INO_RTDATA;
-               else if (lino == mp->m_sb.sb_rbmino)
+               else if (lino == mp->m_sb.sb_rbmino ||
+                        is_rtbitmap_inode(lino))
                        type = XR_INO_RTBITMAP;
-               else if (lino == mp->m_sb.sb_rsumino)
+               else if (lino == mp->m_sb.sb_rsumino ||
+                        is_rtsummary_inode(lino))
                        type = XR_INO_RTSUM;
                else if (lino == mp->m_sb.sb_uquotino)
                        type = XR_INO_UQUOTA;
index 25fa151ca0cdde1c2b38b19fbb9d30af585d9788..d489a742aa5788497c7101784fc72015d8d613d1 100644 (file)
@@ -259,10 +259,12 @@ process_sf_dir2(
                         * bother checking if the child inode is free or not.
                         */
                        junkit = 0;
-               } else if (lino == mp->m_sb.sb_rbmino)  {
+               } else if (lino == mp->m_sb.sb_rbmino ||
+                          is_rtbitmap_inode(lino)) {
                        junkit = 1;
                        junkreason = _("realtime bitmap");
-               } else if (lino == mp->m_sb.sb_rsumino)  {
+               } else if (lino == mp->m_sb.sb_rsumino ||
+                          is_rtsummary_inode(lino)) {
                        junkit = 1;
                        junkreason = _("realtime summary");
                } else if (lino == mp->m_sb.sb_uquotino)  {
@@ -746,9 +748,11 @@ process_dir2_data(
                         * bother checking if the child inode is free or not.
                         */
                        clearino = 0;
-               } else if (ent_ino == mp->m_sb.sb_rbmino) {
+               } else if (ent_ino == mp->m_sb.sb_rbmino ||
+                          is_rtbitmap_inode(ent_ino)) {
                        clearreason = _("realtime bitmap");
-               } else if (ent_ino == mp->m_sb.sb_rsumino) {
+               } else if (ent_ino == mp->m_sb.sb_rsumino ||
+                          is_rtsummary_inode(ent_ino)) {
                        clearreason = _("realtime summary");
                } else if (ent_ino == mp->m_sb.sb_uquotino) {
                        clearreason = _("user quota");
index 98afa691136bd18e09a0edf5dbafa2f1e1e965c8..869c3a06693ab317248d0c79af744461f4925c27 100644 (file)
@@ -243,7 +243,8 @@ free_rt_bmap(xfs_mount_t *mp)
 void
 reset_bmaps(xfs_mount_t *mp)
 {
-       xfs_agnumber_t  agno;
+       unsigned int    nr_groups = mp->m_sb.sb_agcount + mp->m_sb.sb_rgcount;
+       unsigned int    agno;
        xfs_agblock_t   ag_size;
        int             ag_hdr_block;
 
@@ -275,6 +276,22 @@ reset_bmaps(xfs_mount_t *mp)
                btree_insert(ag_bmap[agno], ag_size, &states[XR_E_BAD_STATE]);
        }
 
+       for ( ; agno < nr_groups; agno++) {
+               btree_clear(ag_bmap[agno]);
+               if (agno == mp->m_sb.sb_agcount && xfs_has_rtsb(mp)) {
+                       btree_insert(ag_bmap[agno], 0, &states[XR_E_INUSE_FS]);
+                       btree_insert(ag_bmap[agno], mp->m_sb.sb_rextsize,
+                                       &states[XR_E_FREE]);
+               } else {
+                       btree_insert(ag_bmap[agno], 0, &states[XR_E_FREE]);
+               }
+
+               btree_insert(ag_bmap[agno],
+                       xfs_rtgroup_extents(mp, (agno - mp->m_sb.sb_agcount)) <<
+                               mp->m_sb.sb_rextslog,
+                       &states[XR_E_BAD_STATE]);
+       }
+
        if (mp->m_sb.sb_logstart != 0) {
                set_bmap_ext(XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart),
                             XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
@@ -286,19 +303,22 @@ reset_bmaps(xfs_mount_t *mp)
 }
 
 void
-init_bmaps(xfs_mount_t *mp)
+init_bmaps(
+       struct xfs_mount        *mp)
 {
-       xfs_agnumber_t i;
+       unsigned int            nr_groups =
+               mp->m_sb.sb_agcount + mp->m_sb.sb_rgcount;
+       unsigned int            i;
 
-       ag_bmap = calloc(mp->m_sb.sb_agcount, sizeof(struct btree_root *));
+       ag_bmap = calloc(nr_groups, sizeof(struct btree_root *));
        if (!ag_bmap)
                do_error(_("couldn't allocate block map btree roots\n"));
 
-       ag_locks = calloc(mp->m_sb.sb_agcount, sizeof(struct aglock));
+       ag_locks = calloc(nr_groups, sizeof(struct aglock));
        if (!ag_locks)
                do_error(_("couldn't allocate block map locks\n"));
 
-       for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
+       for (i = 0; i < nr_groups; i++)  {
                btree_init(&ag_bmap[i]);
                pthread_mutex_init(&ag_locks[i].lock, NULL);
        }
@@ -309,19 +329,22 @@ init_bmaps(xfs_mount_t *mp)
 }
 
 void
-free_bmaps(xfs_mount_t *mp)
+free_bmaps(
+       struct xfs_mount        *mp)
 {
-       xfs_agnumber_t i;
+       unsigned int            nr_groups =
+               mp->m_sb.sb_agcount + mp->m_sb.sb_rgcount;
+       unsigned int            i;
 
        pthread_mutex_destroy(&rt_lock.lock);
 
-       for (i = 0; i < mp->m_sb.sb_agcount; i++)
+       for (i = 0; i < nr_groups; i++)
                pthread_mutex_destroy(&ag_locks[i].lock);
 
        free(ag_locks);
        ag_locks = NULL;
 
-       for (i = 0; i < mp->m_sb.sb_agcount; i++)
+       for (i = 0; i < nr_groups; i++)
                btree_destroy(ag_bmap[i]);
 
        free(ag_bmap);
index 9b8227e742ad03c8b058de82c17c13157d92e260..058c233749cbf115fbf05ec834ab2b4fa2507b70 100644 (file)
@@ -698,7 +698,7 @@ xfs_rootrec_inodes_inuse(
        struct xfs_mount        *mp)
 {
        if (xfs_has_metadir(mp))
-               return 4; /* sb_rootino, sb_rbmino, sb_rsumino, sb_metadirino */
+               return 2; /* sb_rootino, sb_metadirino */
        return 3; /* sb_rootino, sb_rbmino, sb_rsumino */
 }
 
index 59c5d6f502c308da5e707a611ae1cca3de48844f..a31ef066ef356c46da2d7e02bb9c7d2891069415 100644 (file)
@@ -593,7 +593,6 @@ release_rt_extent_tree()
 void
 free_rt_dup_extent_tree(xfs_mount_t *mp)
 {
-       ASSERT(mp->m_sb.sb_rblocks != 0);
        free(rt_ext_tree_ptr);
        rt_ext_tree_ptr = NULL;
 }
@@ -726,8 +725,8 @@ static avl64ops_t avl64_extent_tree_ops = {
 void
 incore_ext_init(xfs_mount_t *mp)
 {
+       xfs_agnumber_t agcount = mp->m_sb.sb_agcount + mp->m_sb.sb_rgcount;
        int i;
-       xfs_agnumber_t agcount = mp->m_sb.sb_agcount;
 
        pthread_mutex_init(&rt_ext_tree_lock, NULL);
 
@@ -779,9 +778,10 @@ incore_ext_init(xfs_mount_t *mp)
 void
 incore_ext_teardown(xfs_mount_t *mp)
 {
+       xfs_agnumber_t agcount = mp->m_sb.sb_agcount + mp->m_sb.sb_rgcount;
        xfs_agnumber_t i;
 
-       for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
+       for (i = 0; i < agcount; i++)  {
                btree_destroy(dup_extent_trees[i]);
                free(extent_bno_ptrs[i]);
                free(extent_bcnt_ptrs[i]);
index d99ba574573d1c55920ae907200b76a530d9b38a..2d5965ec49c8f9b57dc95620a9afb59d08dbd76d 100644 (file)
@@ -937,16 +937,14 @@ phase2(
                struct xfs_sb   *sb = &mp->m_sb;
 
                if (xfs_has_metadir(mp))
-                       ASSERT(sb->sb_metadirino == sb->sb_rootino + 1 &&
-                              sb->sb_rbmino  == sb->sb_rootino + 2 &&
-                              sb->sb_rsumino == sb->sb_rootino + 3);
+                       ASSERT(sb->sb_metadirino == sb->sb_rootino + 1);
                else
                        ASSERT(sb->sb_rbmino  == sb->sb_rootino + 1 &&
                               sb->sb_rsumino == sb->sb_rootino + 2);
                do_warn(_("root inode chunk not found\n"));
 
                /*
-                * mark the first 3-4 inodes used, the rest are free
+                * mark the first 2-3 inodes used, the rest are free
                 */
                ino_rec = set_inode_used_alloc(mp, 0,
                                XFS_INO_TO_AGINO(mp, sb->sb_rootino));
@@ -993,27 +991,29 @@ phase2(
                        j++;
                }
 
-               if (is_inode_free(ino_rec, j))  {
-                       do_warn(_("realtime bitmap inode marked free, "));
-                       set_inode_used(ino_rec, j);
-                       if (!no_modify)
-                               do_warn(_("correcting\n"));
-                       else
-                               do_warn(_("would correct\n"));
-               }
-               set_inode_is_meta(ino_rec, j);
-               j++;
+               if (!xfs_has_rtgroups(mp)) {
+                       if (is_inode_free(ino_rec, j))  {
+                               do_warn(_("realtime bitmap inode marked free, "));
+                               set_inode_used(ino_rec, j);
+                               if (!no_modify)
+                                       do_warn(_("correcting\n"));
+                               else
+                                       do_warn(_("would correct\n"));
+                       }
+                       set_inode_is_meta(ino_rec, j);
+                       j++;
 
-               if (is_inode_free(ino_rec, j))  {
-                       do_warn(_("realtime summary inode marked free, "));
-                       set_inode_used(ino_rec, j);
-                       if (!no_modify)
-                               do_warn(_("correcting\n"));
-                       else
-                               do_warn(_("would correct\n"));
+                       if (is_inode_free(ino_rec, j))  {
+                               do_warn(_("realtime summary inode marked free, "));
+                               set_inode_used(ino_rec, j);
+                               if (!no_modify)
+                                       do_warn(_("correcting\n"));
+                               else
+                                       do_warn(_("would correct\n"));
+                       }
+                       set_inode_is_meta(ino_rec, j);
+                       j++;
                }
-               set_inode_is_meta(ino_rec, j);
-               j++;
        }
 
        /*
index 8d97b63b2ce92085941eb7558edf7f0d8fef94d0..167093da999d2eccf8f035ea97d77d408dc06663 100644 (file)
@@ -241,8 +241,10 @@ process_rmap_data(
        create_work_queue(&wq, mp, platform_nproc());
        for (i = 0; i < mp->m_sb.sb_agcount; i++)
                queue_work(&wq, check_rmap_btrees, i, NULL);
-       for (i = 0; i < mp->m_sb.sb_rgcount; i++)
-               queue_work(&wq, check_rtrmap_btrees, i, NULL);
+       if (xfs_has_rtgroups(mp)) {
+               for (i = 0; i < mp->m_sb.sb_rgcount; i++)
+                       queue_work(&wq, check_rtrmap_btrees, i, NULL);
+       }
        destroy_work_queue(&wq);
 
        if (!xfs_has_reflink(mp))
@@ -251,8 +253,10 @@ process_rmap_data(
        create_work_queue(&wq, mp, platform_nproc());
        for (i = 0; i < mp->m_sb.sb_agcount; i++)
                queue_work(&wq, compute_ag_refcounts, i, NULL);
-       for (i = 0; i < mp->m_sb.sb_rgcount; i++)
-               queue_work(&wq, compute_rt_refcounts, i, NULL);
+       if (xfs_has_rtgroups(mp)) {
+               for (i = 0; i < mp->m_sb.sb_rgcount; i++)
+                       queue_work(&wq, compute_rt_refcounts, i, NULL);
+       }
        destroy_work_queue(&wq);
 
        create_work_queue(&wq, mp, platform_nproc());
@@ -260,25 +264,129 @@ process_rmap_data(
                queue_work(&wq, process_inode_reflink_flags, i, NULL);
                queue_work(&wq, check_refcount_btrees, i, NULL);
        }
-       for (i = 0; i < mp->m_sb.sb_rgcount; i++)
-               queue_work(&wq, check_rt_refcount_btrees, i, NULL);
+       if (xfs_has_rtgroups(mp)) {
+               for (i = 0; i < mp->m_sb.sb_rgcount; i++)
+                       queue_work(&wq, check_rt_refcount_btrees, i, NULL);
+       }
        destroy_work_queue(&wq);
 }
 
+static void
+process_dup_rt_extents(
+       struct xfs_mount        *mp)
+{
+       xfs_rtxnum_t            rt_start = 0;
+       xfs_rtxlen_t            rt_len = 0;
+       xfs_rtxnum_t            rtx;
+
+       for (rtx = 0; rtx < mp->m_sb.sb_rextents; rtx++)  {
+               int state;
+
+               state = get_rtbmap(rtx);
+               switch (state) {
+               case XR_E_BAD_STATE:
+               default:
+                       do_warn(
+       _("unknown rt extent state %d, extent %" PRIu64 "\n"),
+                               state, rtx);
+                       fallthrough;
+               case XR_E_METADATA:
+               case XR_E_UNKNOWN:
+               case XR_E_FREE1:
+               case XR_E_FREE:
+               case XR_E_INUSE:
+               case XR_E_INUSE_FS:
+               case XR_E_INO:
+               case XR_E_FS_MAP:
+                       if (rt_start == 0)
+                               continue;
+                       /*
+                        * Add extent and reset extent state.
+                        */
+                       add_rt_dup_extent(rt_start, rt_len);
+                       rt_start = 0;
+                       rt_len = 0;
+                       break;
+               case XR_E_MULT:
+                       switch (rt_start)  {
+                       case 0:
+                               rt_start = rtx;
+                               rt_len = 1;
+                               break;
+                       case XFS_MAX_BMBT_EXTLEN:
+                               /*
+                                * Large extent case.
+                                */
+                               add_rt_dup_extent(rt_start, rt_len);
+                               rt_start = rtx;
+                               rt_len = 1;
+                               break;
+                       default:
+                               rt_len++;
+                               break;
+                       }
+                       break;
+               }
+       }
+
+       /*
+        * Catch the tail case, extent hitting the end of the RTG.
+        */
+       if (rt_start != 0)
+               add_rt_dup_extent(rt_start, rt_len);
+}
+
+/*
+ * Set up duplicate extent list for an AG or RTG.
+ */
+static void
+process_dup_extents(
+       xfs_agnumber_t          agno,
+       xfs_agblock_t           agbno,
+       xfs_agblock_t           ag_end)
+{
+       do {
+               int             bstate;
+               xfs_extlen_t    blen;
+
+               bstate = get_bmap_ext(agno, agbno, ag_end, &blen);
+               switch (bstate) {
+               case XR_E_FREE1:
+                       if (no_modify)
+                               do_warn(
+_("free space (%u,%u-%u) only seen by one free space btree\n"),
+                                       agno, agbno, agbno + blen - 1);
+                       break;
+               case XR_E_METADATA:
+               case XR_E_UNKNOWN:
+               case XR_E_FREE:
+               case XR_E_INUSE:
+               case XR_E_INUSE_FS:
+               case XR_E_INO:
+               case XR_E_FS_MAP:
+                       break;
+               case XR_E_MULT:
+                       add_dup_extent(agno, agbno, blen);
+                       break;
+               case XR_E_BAD_STATE:
+               default:
+                       do_warn(
+_("unknown block state, ag %d, blocks %u-%u\n"),
+                               agno, agbno, agbno + blen - 1);
+                       break;
+               }
+
+               agbno += blen;
+       } while (agbno < ag_end);
+}
+
 void
 phase4(xfs_mount_t *mp)
 {
        ino_tree_node_t         *irec;
-       xfs_rtxnum_t            rtx;
-       xfs_rtxnum_t            rt_start;
-       xfs_rtxlen_t            rt_len;
        xfs_agnumber_t          i;
-       xfs_agblock_t           j;
-       xfs_agblock_t           ag_end;
-       xfs_extlen_t            blen;
        int                     ag_hdr_len = 4 * mp->m_sb.sb_sectsize;
        int                     ag_hdr_block;
-       int                     bstate;
 
        if (rmap_needs_work(mp))
                collect_rmaps = true;
@@ -324,103 +432,28 @@ phase4(xfs_mount_t *mp)
        }
 
        for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
+               xfs_agblock_t           ag_end;
+
                ag_end = (i < mp->m_sb.sb_agcount - 1) ? mp->m_sb.sb_agblocks :
                        mp->m_sb.sb_dblocks -
                                (xfs_rfsblock_t) mp->m_sb.sb_agblocks * i;
 
-               /*
-                * set up duplicate extent list for this ag
-                */
-               for (j = ag_hdr_block; j < ag_end; j += blen)  {
-                       bstate = get_bmap_ext(i, j, ag_end, &blen);
-                       switch (bstate) {
-                       case XR_E_FREE1:
-                               if (no_modify)
-                                       do_warn(
-       _("free space (%u,%u-%u) only seen by one free space btree\n"),
-                                               i, j, j + blen - 1);
-                               break;
-                       case XR_E_BAD_STATE:
-                       default:
-                               do_warn(
-                               _("unknown block state, ag %d, blocks %u-%u\n"),
-                                       i, j, j + blen - 1);
-                               fallthrough;
-                       case XR_E_METADATA:
-                       case XR_E_UNKNOWN:
-                       case XR_E_FREE:
-                       case XR_E_INUSE:
-                       case XR_E_INUSE_FS:
-                       case XR_E_INO:
-                       case XR_E_FS_MAP:
-                               break;
-                       case XR_E_MULT:
-                               add_dup_extent(i, j, blen);
-                               break;
-                       }
-               }
+               process_dup_extents(i, ag_hdr_block, ag_end);
 
                PROG_RPT_INC(prog_rpt_done[i], 1);
        }
        print_final_rpt();
 
-       /*
-        * initialize realtime bitmap
-        */
-       rt_start = 0;
-       rt_len = 0;
-
-       for (rtx = 0; rtx < mp->m_sb.sb_rextents; rtx++)  {
-               bstate = get_rtbmap(rtx);
-               switch (bstate)  {
-               case XR_E_BAD_STATE:
-               default:
-                       do_warn(
-       _("unknown rt extent state, extent %" PRIu64 "\n"),
-                               rtx);
-                       fallthrough;
-               case XR_E_METADATA:
-               case XR_E_UNKNOWN:
-               case XR_E_FREE1:
-               case XR_E_FREE:
-               case XR_E_INUSE:
-               case XR_E_INUSE_FS:
-               case XR_E_INO:
-               case XR_E_FS_MAP:
-                       if (rt_start == 0)
-                               continue;
-                       else  {
-                               /*
-                                * add extent and reset extent state
-                                */
-                               add_rt_dup_extent(rt_start, rt_len);
-                               rt_start = 0;
-                               rt_len = 0;
-                       }
-                       break;
-               case XR_E_MULT:
-                       if (rt_start == 0)  {
-                               rt_start = rtx;
-                               rt_len = 1;
-                       } else if (rt_len == XFS_MAX_BMBT_EXTLEN)  {
-                               /*
-                                * large extent case
-                                */
-                               add_rt_dup_extent(rt_start, rt_len);
-                               rt_start = rtx;
-                               rt_len = 1;
-                       } else
-                               rt_len++;
-                       break;
+       if (xfs_has_rtgroups(mp)) {
+               for (i = 0; i < mp->m_sb.sb_rgcount; i++)  {
+                       process_dup_extents(mp->m_sb.sb_agcount + i, 0,
+                               xfs_rtgroup_extents(mp, i) <<
+                                       mp->m_sb.sb_rextslog);
                }
+       } else {
+               process_dup_rt_extents(mp);
        }
 
-       /*
-        * catch tail-case, extent hitting the end of the ag
-        */
-       if (rt_start != 0)
-               add_rt_dup_extent(rt_start, rt_len);
-
        /*
         * initialize bitmaps for all AGs
         */
@@ -453,8 +486,7 @@ phase4(xfs_mount_t *mp)
        /*
         * free up memory used to track trealtime duplicate extents
         */
-       if (rt_start != 0)
-               free_rt_dup_extent_tree(mp);
+       free_rt_dup_extent_tree(mp);
 
        /*
         * ensure consistency of quota inode pointers in superblock,
index 05cc5fb1845617802b5e8fbd2a3426b6d90cf800..511062065b6a8ec475d485f7b89b945acc19db0d 100644 (file)
@@ -495,53 +495,52 @@ mark_ino_metadata(
        set_inode_is_meta(irec, ino_offset);
 }
 
-/* Load a realtime freespace metadata inode from disk and reset it. */
-static int
-ensure_rtino(
-       struct xfs_trans                *tp,
-       xfs_ino_t                       ino,
-       struct xfs_inode                **ipp)
-{
-       struct xfs_mount                *mp = tp->t_mountp;
-       int                             error;
-
-       error = -libxfs_iget(mp, tp, ino, 0, ipp);
-       if (error)
-               return error;
-
-       reset_sbroot_ino(tp, S_IFREG, *ipp);
-       if (xfs_has_metadir(mp))
-               libxfs_metafile_set_iflag(tp, *ipp);
-       return 0;
-}
-
 static void
-mk_rbmino(
-       struct xfs_mount        *mp)
+mk_rtino(
+       struct xfs_rtgroup      *rtg,
+       enum xfs_rtg_inodes     type)
 {
+       struct xfs_mount        *mp = rtg->rtg_mount;
+       struct xfs_inode        *ip = rtg->rtg_inodes[type];
        struct xfs_trans        *tp;
-       struct xfs_inode        *ip;
        int                     error;
 
+       if (!ip) {
+               /*
+                * XXX: we probably should still re-initialize / re-create the
+                * inode if the earlier validations failed.
+                */
+               do_error(_("no %s inode for rtgroup %u\n"),
+                       xfs_rtginode_name(type), rtg->rtg_rgno);
+       }
+
        error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (error)
                res_failed(error);
 
-       /* Reset the realtime bitmap inode. */
-       error = ensure_rtino(tp, mp->m_sb.sb_rbmino, &ip);
-       if (error) {
-               do_error(
-               _("couldn't iget realtime bitmap inode -- error - %d\n"),
-                       error);
+       reset_sbroot_ino(tp, S_IFREG, ip);
+
+       switch (type) {
+       case XFS_RTG_BITMAP:
+               error = -xfs_rtbitmap_create(rtg, ip, tp, false);
+               break;
+       case XFS_RTG_SUMMARY:
+               error = -xfs_rtsummary_create(rtg, ip, tp, false);
+               break;
+       default:
+               error = EINVAL;
        }
-       ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
-       libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+       if (error)
+               do_error(_("%s inode re-initialization failed for rtgroup %u\n"),
+                       xfs_rtginode_name(type), rtg->rtg_rgno);
+
        error = -libxfs_trans_commit(tp);
        if (error)
                do_error(_("%s: commit failed, error %d\n"), __func__, error);
-       libxfs_irele(ip);
 }
 
+#if 0
 static void
 mk_rsumino(
        struct xfs_mount        *mp)
@@ -568,6 +567,7 @@ mk_rsumino(
                do_error(_("%s: commit failed, error %d\n"), __func__, error);
        libxfs_irele(ip);
 }
+#endif
 
 /* Mark a newly allocated inode in use in the incore bitmap. */
 static void
@@ -701,6 +701,34 @@ ensure_rtgroup_file(
        return true;
 }
 
+static void
+ensure_rtgroup_bitmap(
+       struct xfs_rtgroup      *rtg)
+{
+       struct xfs_mount        *mp = rtg->rtg_mount;
+
+       if (!xfs_has_rtgroups(mp))
+               return;
+       if (!ensure_rtgroup_file(rtg, XFS_RTG_BITMAP))
+               return;
+
+       fill_rtbitmap(rtg);
+}
+
+static void
+ensure_rtgroup_summary(
+       struct xfs_rtgroup      *rtg)
+{
+       struct xfs_mount        *mp = rtg->rtg_mount;
+
+       if (!xfs_has_rtgroups(mp))
+               return;
+       if (!ensure_rtgroup_file(rtg, XFS_RTG_SUMMARY))
+               return;
+
+       fill_rtsummary(rtg);
+}
+
 static void
 ensure_rtgroup_rmapbt(
        struct xfs_rtgroup      *rtg,
@@ -3214,8 +3242,10 @@ mark_inode(
 static void
 mark_standalone_inodes(xfs_mount_t *mp)
 {
-       mark_inode(mp, mp->m_sb.sb_rbmino);
-       mark_inode(mp, mp->m_sb.sb_rsumino);
+       if (!xfs_has_rtgroups(mp)) {
+               mark_inode(mp, mp->m_sb.sb_rbmino);
+               mark_inode(mp, mp->m_sb.sb_rsumino);
+       }
 
        if (!fs_quotas)
                return;
@@ -3359,6 +3389,43 @@ traverse_ags(
        do_inode_prefetch(mp, ag_stride, traverse_function, false, true);
 }
 
+static void
+reset_rt_sb_inodes(
+       struct xfs_mount        *mp)
+{
+       struct xfs_rtgroup      *rtg;
+
+       if (no_modify) {
+               if (need_rbmino)
+                       do_warn(_("would reinitialize realtime bitmap inode\n"));
+               if (need_rsumino)
+                       do_warn(_("would reinitialize realtime summary inode\n"));
+               return;
+       }
+
+       rtg = xfs_rtgroup_grab(mp, 0);
+
+       if (need_rbmino)  {
+               do_warn(_("reinitializing realtime bitmap inode\n"));
+               mk_rtino(rtg, XFS_RTG_BITMAP);
+               need_rbmino = 0;
+       }
+
+       if (need_rsumino)  {
+               do_warn(_("reinitializing realtime summary inode\n"));
+               mk_rtino(rtg, XFS_RTG_SUMMARY);
+               need_rsumino = 0;
+       }
+
+       do_log(
+_("        - resetting contents of realtime bitmap and summary inodes\n"));
+
+       fill_rtbitmap(rtg);
+       fill_rtsummary(rtg);
+
+       xfs_rtgroup_rele(rtg);
+}
+
 static void
 reset_rt_metadata_inodes(
        struct xfs_mount        *mp)
@@ -3394,7 +3461,17 @@ reset_rt_metadata_inodes(
                        est_fdblocks = mp->m_sb.sb_fdblocks - metadata_blocks;
        }
 
+       /*
+        * This isn't the whole story, but it keeps the message that we've had
+        * for years and which is expected in xfstests and more.
+        */
+       if (!no_modify)
+               do_log(
+_("        - resetting contents of realtime bitmap and summary inodes\n"));
+
        for_each_rtgroup(mp, rgno, rtg) {
+               ensure_rtgroup_bitmap(rtg);
+               ensure_rtgroup_summary(rtg);
                ensure_rtgroup_rmapbt(rtg, est_fdblocks);
                ensure_rtgroup_refcountbt(rtg, est_fdblocks);
        }
@@ -3492,35 +3569,10 @@ phase6(xfs_mount_t *mp)
                }
        }
 
-       if (need_rbmino)  {
-               if (!no_modify)  {
-                       do_warn(_("reinitializing realtime bitmap inode\n"));
-                       mk_rbmino(mp);
-                       need_rbmino = 0;
-               } else  {
-                       do_warn(_("would reinitialize realtime bitmap inode\n"));
-               }
-       }
-
-       if (need_rsumino)  {
-               if (!no_modify)  {
-                       do_warn(_("reinitializing realtime summary inode\n"));
-                       mk_rsumino(mp);
-                       need_rsumino = 0;
-               } else  {
-                       do_warn(_("would reinitialize realtime summary inode\n"));
-               }
-       }
-
        if (xfs_has_rtgroups(mp))
                reset_rt_metadata_inodes(mp);
-
-       if (!no_modify)  {
-               do_log(
-_("        - resetting contents of realtime bitmap and summary inodes\n"));
-               fill_rtbitmap(mp);
-               fill_rtsummary(mp);
-       }
+       else
+               reset_rt_sb_inodes(mp);
 
        if (reserve_perag)
                unreserve_ag_blocks(mp);
index 221074eda3d7f7bb909a0d8eaa47c45fac1488cf..df0e139674fc8d44992dce45f7cbeba7b79ff01c 100644 (file)
 static struct bitmap           *rtg_inodes[XFS_RTG_MAX];
 
 /* Computed rt bitmap/summary data */
-static union xfs_rtword_raw    *btmcompute;
-static union xfs_suminfo_raw   *sumcompute;
+struct rtg_computed {
+       union xfs_rtword_raw    *bmp;
+       union xfs_suminfo_raw   *sum;
+};
+struct rtg_computed *rt_computed;
 
 static inline void
 set_rtword(
@@ -48,14 +51,13 @@ inc_sumcount(
                p->old++;
 }
 
-/*
- * generate the real-time bitmap and summary info based on the
- * incore realtime extent map.
- */
-void
-generate_rtinfo(
-       struct xfs_mount        *mp)
+static void
+generate_rtg_rtinfo(
+       struct xfs_rtgroup      *rtg)
 {
+       struct rtg_computed     *comp = &rt_computed[rtg->rtg_rgno];
+       struct xfs_mount        *mp = rtg->rtg_mount;
+       unsigned int            idx = mp->m_sb.sb_agcount + rtg->rtg_rgno;
        unsigned int            bitsperblock =
                mp->m_blockwsize << XFS_NBWORDLOG;
        xfs_rtxnum_t            extno = 0;
@@ -65,36 +67,46 @@ generate_rtinfo(
        bool                    in_extent = false;
        union xfs_rtword_raw    *words;
 
-       btmcompute = calloc(libxfs_rtbitmap_wordcount(mp, mp->m_sb.sb_rextents),
+       comp->bmp = calloc(libxfs_rtbitmap_wordcount(mp),
                        sizeof(union xfs_rtword_raw));
-       if (!btmcompute)
+       if (!comp->bmp)
                do_error(
 _("couldn't allocate memory for incore realtime bitmap.\n"));
-       words = btmcompute;
+       words = comp->bmp;
 
-       sumcompute = calloc(libxfs_rtsummary_wordcount(mp, mp->m_rsumlevels,
+       comp->sum = calloc(libxfs_rtsummary_wordcount(mp, mp->m_rsumlevels,
                        mp->m_sb.sb_rbmblocks), sizeof(union xfs_suminfo_raw));
-       if (!sumcompute)
+       if (!comp->sum)
                do_error(
 _("couldn't allocate memory for incore realtime summary info.\n"));
 
-       ASSERT(mp->m_rbmip == NULL);
-
        /*
         * Slower but simple, don't play around with trying to set things one
         * word at a time, just set bit as required.  Have to track start and
         * end (size) of each range of free extents to set the summary info
         * properly.
         */
-       while (extno < mp->m_sb.sb_rextents)  {
+       while (extno < rtg->rtg_extents) {
                xfs_rtword_t            freebit = 1;
                xfs_rtword_t            bits = 0;
-               int                     i;
+               int                     state, i;
 
                set_rtword(mp, words, 0);
-               for (i = 0; i < sizeof(xfs_rtword_t) * NBBY &&
-                               extno < mp->m_sb.sb_rextents; i++, extno++)  {
-                       if (get_rtbmap(extno) == XR_E_FREE)  {
+               for (i = 0; i < sizeof(xfs_rtword_t) * NBBY; i++) {
+                       if (extno == rtg->rtg_extents)
+                               break;
+
+                       /*
+                        * Note: for the RTG case it might make sense to use
+                        * get_bmap_ext here and generate multiple bitmap
+                        * entries per lookup.
+                        */
+                       if (xfs_has_rtgroups(mp))
+                               state = get_bmap(idx,
+                                       extno * mp->m_sb.sb_rextsize);
+                       else
+                               state = get_rtbmap(extno);
+                       if (state == XR_E_FREE)  {
                                sb_frextents++;
                                bits |= freebit;
 
@@ -109,11 +121,12 @@ _("couldn't allocate memory for incore realtime summary info.\n"));
 
                                offs = xfs_rtsumoffs(mp, libxfs_highbit64(len),
                                                start_bmbno);
-                               inc_sumcount(mp, sumcompute, offs);
+                               inc_sumcount(mp, comp->sum, offs);
                                in_extent = false;
                        }
 
                        freebit <<= 1;
+                       extno++;
                }
                set_rtword(mp, words, bits);
                words++;
@@ -127,8 +140,28 @@ _("couldn't allocate memory for incore realtime summary info.\n"));
                xfs_rtsumoff_t  offs;
 
                offs = xfs_rtsumoffs(mp, libxfs_highbit64(len), start_bmbno);
-               inc_sumcount(mp, sumcompute, offs);
+               inc_sumcount(mp, comp->sum, offs);
        }
+}
+
+/*
+ * generate the real-time bitmap and summary info based on the
+ * incore realtime extent map.
+ */
+void
+generate_rtinfo(
+       struct xfs_mount        *mp)
+{
+       struct xfs_rtgroup      *rtg;
+       xfs_rgnumber_t          rgno;
+
+       rt_computed = calloc(mp->m_sb.sb_rgcount, sizeof(struct rtg_computed));
+       if (!rt_computed)
+               do_error(
+       _("couldn't allocate memory for incore realtime info.\n"));
+
+       for_each_rtgroup(mp, rgno, rtg)
+               generate_rtg_rtinfo(rtg);
 
        if (mp->m_sb.sb_frextents != sb_frextents) {
                do_warn(_("sb_frextents %" PRIu64 ", counted %" PRIu64 "\n"),
@@ -138,12 +171,13 @@ _("couldn't allocate memory for incore realtime summary info.\n"));
 
 static void
 check_rtwords(
-       struct xfs_mount        *mp,
+       struct xfs_rtgroup      *rtg,
        const char              *filename,
        unsigned long long      bno,
        void                    *ondisk,
        void                    *incore)
 {
+       struct xfs_mount        *mp = rtg->rtg_mount;
        unsigned int            wordcnt = mp->m_blockwsize;
        union xfs_rtword_raw    *o = ondisk, *i = incore;
        int                     badstart = -1;
@@ -157,8 +191,9 @@ check_rtwords(
                        /* Report a range of inconsistency that just ended. */
                        if (badstart >= 0)
                                do_warn(
- _("discrepancy in %s at dblock 0x%llx words 0x%x-0x%x/0x%x\n"),
-                                       filename, bno, badstart, j - 1, wordcnt);
+ _("discrepancy in %s (%u) at dblock 0x%llx words 0x%x-0x%x/0x%x\n"),
+                                       filename, rtg->rtg_rgno, bno,
+                                       badstart, j - 1, wordcnt);
                        badstart = -1;
                        continue;
                }
@@ -169,40 +204,39 @@ check_rtwords(
 
        if (badstart >= 0)
                do_warn(
- _("discrepancy in %s at dblock 0x%llx words 0x%x-0x%x/0x%x\n"),
-                                       filename, bno, badstart, wordcnt,
-                                       wordcnt);
+ _("discrepancy in %s (%u) at dblock 0x%llx words 0x%x-0x%x/0x%x\n"),
+                       filename, rtg->rtg_rgno, bno,
+                       badstart, wordcnt, wordcnt);
 }
 
 static void
 check_rtfile_contents(
-       struct xfs_mount        *mp,
-       bool                    is_summary)
+       struct xfs_rtgroup      *rtg,
+       enum xfs_rtg_inodes     type)
 {
-       struct xfs_inode        *ip;
-       const struct xfs_buf_ops *buf_ops = xfs_rtblock_ops(mp, is_summary);
-       const char              *filename;
-       xfs_ino_t               ino;
+       struct xfs_mount        *mp = rtg->rtg_mount;
+       const char              *filename = xfs_rtginode_name(type);
+       struct xfs_inode        *ip = rtg->rtg_inodes[type];
+       const struct xfs_buf_ops *buf_ops = NULL;
        void                    *buf;
-       xfs_filblks_t           filelen;
+       xfs_fileoff_t           filelen;
        xfs_fileoff_t           bno = 0;
        int                     error;
 
-       if (is_summary) {
-               filename = _("rtsummary");
-               ino = mp->m_sb.sb_rsumino;
-               buf = sumcompute;
-               filelen = XFS_B_TO_FSB(mp, mp->m_rsumsize);
-       } else {
-               filename = _("rtbitmap");
-               ino = mp->m_sb.sb_rbmino;
-               buf = btmcompute;
+       if (type == XFS_RTG_BITMAP) {
+               if (xfs_has_rtgroups(mp))
+                       buf_ops = &xfs_rtbitmap_buf_ops;
+               buf = rt_computed[rtg->rtg_rgno].bmp;
                filelen = mp->m_sb.sb_rbmblocks;
+       } else {
+               if (xfs_has_rtgroups(mp))
+                       buf_ops = &xfs_rtsummary_buf_ops;
+               buf = rt_computed[rtg->rtg_rgno].sum;
+               filelen = XFS_B_TO_FSB(mp, mp->m_rsumsize);
        }
 
-       error = -libxfs_iget(mp, NULL, ino, 0, &ip);
-       if (error) {
-               do_warn(_("unable to open %s file, err %d\n"), filename, error);
+       if (!ip) {
+               do_warn(_("unable to open %s file\n"), filename);
                return;
        }
 
@@ -245,7 +279,7 @@ check_rtfile_contents(
                if (xfs_has_rtgroups(mp)) {
                        struct xfs_rtbuf_blkinfo        *hdr = bp->b_addr;
 
-                       if (hdr->rt_owner != cpu_to_be64(ino)) {
+                       if (hdr->rt_owner != cpu_to_be64(ip->i_ino)) {
                                do_warn(
  _("corrupt owner in %s at dblock 0x%llx\n"),
                                        filename, (unsigned long long)bno);
@@ -254,90 +288,85 @@ check_rtfile_contents(
                        offset = sizeof(*hdr);
                }
 
-               check_rtwords(mp, filename, bno, bp->b_addr + offset, buf);
+               check_rtwords(rtg, filename, bno, bp->b_addr + offset, buf);
+
                buf += mp->m_blockwsize << XFS_WORDLOG;
                bno++;
                libxfs_buf_relse(bp);
        }
-
-       libxfs_irele(ip);
 }
 
 void
 check_rtbitmap(
        struct xfs_mount        *mp)
 {
+       struct xfs_rtgroup      *rtg;
+       xfs_rgnumber_t          rgno;
+
        if (need_rbmino)
                return;
 
-       check_rtfile_contents(mp, false);
+       for_each_rtgroup(mp, rgno, rtg)
+               check_rtfile_contents(rtg, XFS_RTG_BITMAP);
 }
 
 void
 check_rtsummary(
        struct xfs_mount        *mp)
 {
+       struct xfs_rtgroup      *rtg;
+       xfs_rgnumber_t          rgno;
+
        if (need_rsumino)
                return;
 
-       check_rtfile_contents(mp, true);
+       for_each_rtgroup(mp, rgno, rtg)
+               check_rtfile_contents(rtg, XFS_RTG_SUMMARY);
 }
 
 void
 fill_rtbitmap(
-       struct xfs_mount        *mp)
+       struct xfs_rtgroup      *rtg)
 {
-       struct xfs_trans        *tp;
-       struct xfs_inode        *ip;
        int                     error;
 
-       error = -libxfs_trans_alloc_empty(mp, &tp);
-       if (error)
-               do_error(
-_("couldn't allocate empty transaction, error %d\n"), error);
-       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rbmino, 0, &ip);
-       if (error)
-               do_error(
-_("couldn't iget realtime bitmap inode, error %d\n"), error);
-       libxfs_trans_cancel(tp);
+       /*
+        * For file systems without a RT subvolume we have the bitmap and
+        * summary files, but they are empty.  In that case rt_computed is
+        * NULL.
+        */
+       if (!rt_computed)
+               return;
 
-       error = -libxfs_rtfile_initialize_blocks(ip, 0, mp->m_sb.sb_rbmblocks,
-                       btmcompute);
+       error = -libxfs_rtfile_initialize_blocks(rtg, XFS_RTG_BITMAP,
+                       0, rtg->rtg_mount->m_sb.sb_rbmblocks,
+                       rt_computed[rtg->rtg_rgno].bmp);
        if (error)
                do_error(
 _("couldn't re-initialize realtime bitmap inode, error %d\n"), error);
-       libxfs_irele(ip);
 }
 
 void
 fill_rtsummary(
-       struct xfs_mount        *mp)
+       struct xfs_rtgroup      *rtg)
 {
-       struct xfs_trans        *tp;
-       struct xfs_inode        *ip;
+       struct xfs_mount        *mp = rtg->rtg_mount;
        int                     error;
 
-       error = -libxfs_trans_alloc_empty(mp, &tp);
-       if (error)
-               do_error(
-_("couldn't allocate empty transaction, error %d\n"), error);
-       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rsumino, 0, &ip);
-       if (error) {
-               do_error(
-_("couldn't iget realtime summary inode, error - %d\n"), error);
-       }
-       libxfs_trans_cancel(tp);
+       /*
+        * For file systems without a RT subvolume we have the bitmap and
+        * summary files, but they are empty.  In that case rt_computed is
+        * NULL.
+        */
+       if (!rt_computed)
+               return;
 
-       mp->m_rsumip = ip;
-       error = -libxfs_rtfile_initialize_blocks(ip, 0,
-                       mp->m_rsumsize >> mp->m_sb.sb_blocklog,
-                       sumcompute);
-       mp->m_rsumip = NULL;
+       error = -libxfs_rtfile_initialize_blocks(rtg, XFS_RTG_SUMMARY,
+                       0, mp->m_rsumsize >> mp->m_sb.sb_blocklog,
+                       rt_computed[rtg->rtg_rgno].sum);
        if (error)
                do_error(
 _("couldn't re-initialize realtime summary inode, error %d\n"), error);
-
-       libxfs_irele(ip);
 }
 
 void
@@ -453,7 +482,8 @@ set_rtginode(
                return error;
 
        ip = rtg->rtg_inodes[type];
-       if (!ip) /* inode type not enabled */
+       if (!ip /* inode type not enabled */ ||
+           !xfs_has_rtgroups(rtg->rtg_mount))
                return 0;
 
        if (bitmap_test(rtg_inodes[type], ip->i_ino, 1))
@@ -471,8 +501,8 @@ discover_rtgroup_inodes(
        int                     error, err2;
        int                     i;
 
-       if (!xfs_has_rtgroups(mp))
-               return;
+//     if (!xfs_has_rtgroups(mp))
+//             return;
 
        for (i = 0; i < XFS_RTG_MAX; i++) {
                error = bitmap_alloc(&rtg_inodes[i]);
@@ -513,8 +543,8 @@ free_rtgroup_inodes(
 {
        int                     i;
 
-       if (!xfs_has_rtgroups(mp))
-               return;
+//     if (!xfs_has_rtgroups(mp))
+//             return;
 
        for (i = 0; i < XFS_RTG_MAX; i++)
                bitmap_free(&rtg_inodes[i]);
index 8e80f1719308c811ad72a91e01dc87f4882ac917..56e265340fcb956b8be0a20118744ac105b25387 100644 (file)
@@ -10,8 +10,8 @@ void generate_rtinfo(struct xfs_mount *mp);
 void check_rtbitmap(struct xfs_mount *mp);
 void check_rtsummary(struct xfs_mount *mp);
 
-void fill_rtbitmap(struct xfs_mount *mp);
-void fill_rtsummary(struct xfs_mount *mp);
+void fill_rtbitmap(struct xfs_rtgroup *rtg);
+void fill_rtsummary(struct xfs_rtgroup *rtg);
 
 void check_rtsb(struct xfs_mount *mp);
 void rewrite_rtsb(struct xfs_mount *mp);
@@ -36,6 +36,15 @@ rtgroup_for_rtrefcount_inode(struct xfs_mount *mp, xfs_ino_t ino)
 
 bool is_rtgroup_inode(xfs_ino_t ino, enum xfs_rtg_inodes type);
 
+static inline bool is_rtbitmap_inode(xfs_ino_t ino)
+{
+       return is_rtgroup_inode(ino, XFS_RTG_BITMAP);
+}
+static inline bool is_rtsummary_inode(xfs_ino_t ino)
+{
+       return is_rtgroup_inode(ino, XFS_RTG_SUMMARY);
+}
+
 static inline bool is_rtrmap_inode(xfs_ino_t ino)
 {
        return is_rtgroup_inode(ino, XFS_RTG_RMAP);
index 8bfd0c36b10e99289a6aed82496db66d6d528fb8..55f4c6f5ece43c709eb88988594a19fceee132d9 100644 (file)
@@ -1989,6 +1989,7 @@ process_rtrefc_reclist(
        struct refc_priv        *refc_priv,
        const char              *name)
 {
+       xfs_rgnumber_t          rgno = refc_priv->rgno;
        xfs_rtblock_t           lastblock = 0;
        xfs_rtblock_t           rtbno, next_rtbno;
        int                     state;
@@ -2028,7 +2029,7 @@ _("leftover rt CoW extent has invalid startblock in record %u of %s\n"),
                }
                end = rgbno + len;
 
-               rtbno = xfs_rgbno_to_rtb(mp, refc_priv->rgno, rgbno);
+               rtbno = xfs_rgbno_to_rtb(mp, rgno, rgbno);
                if (!libxfs_verify_rtbno(mp, rtbno)) {
                        do_warn(
 _("invalid start block %llu in record %u of %s\n"),
@@ -2037,7 +2038,7 @@ _("invalid start block %llu in record %u of %s\n"),
                        continue;
                }
 
-               next_rtbno = xfs_rgbno_to_rtb(mp, refc_priv->rgno, end);
+               next_rtbno = xfs_rgbno_to_rtb(mp, rgno, end);
                if (len == 0 || end <= rgbno ||
                    !libxfs_verify_rtbno(mp, next_rtbno - 1)) {
                        do_warn(
@@ -2047,36 +2048,38 @@ _("invalid length %llu in record %u of %s\n"),
                        continue;
                }
 
+               if (nr < 2 || nr > XFS_REFC_REFCOUNT_MAX) {
+                       do_warn(
+_("invalid rt reference count %u in record %u of %s\n"),
+                                       nr, i, name);
+                       suspect++;
+                       continue;
+               }
+
                if (nr == 1) {
-                       xfs_rtxnum_t    rtx, next_rtx;
+                       xfs_rgblock_t           b;
+                       xfs_extlen_t            blen;
+
+                       for (b = rgbno; b < end; b += len) {
+                               state = get_bmap_ext(rgno, b, end, &blen);
+                               blen = min(blen, len);
 
-                       rtx = xfs_rtb_to_rtx(mp, rtbno);
-                       next_rtx = xfs_rtb_to_rtx(mp, next_rtbno);
-                       for (; rtx < next_rtx; rtx++) {
-                               state = get_rtbmap(rtx);
                                switch (state) {
                                case XR_E_UNKNOWN:
                                case XR_E_COW:
                                        do_warn(
 _("leftover CoW rtextent (%llu)\n"),
-                                               (unsigned long long)rtx);
-                                       suspect++;
-                                       set_rtbmap(rtx, XR_E_FREE);
+                                               (unsigned long long)rgbno);
+                                       set_bmap_ext(rgno, b, len, XR_E_FREE);
                                        break;
                                default:
                                        do_warn(
 _("rtextent (%llu) claimed, state is %d\n"),
-                                               (unsigned long long)rtx, state);
-                                       suspect++;
+                                               (unsigned long long)rgbno, state);
                                        break;
                                }
+                               suspect++;
                        }
-               } else if (nr < 2 || nr > XFS_REFC_REFCOUNT_MAX) {
-                       do_warn(
-_("invalid rt reference count %u in record %u of %s\n"),
-                                       nr, i, name);
-                       suspect++;
-                       continue;
                }
 
                if (b && b <= lastblock) {
index c3f1fa8f44d5b7ac2081f209f0bd78e96657ac03..aebfd84b034f8c60b092629ea180c4ab405deca9 100644 (file)
@@ -814,13 +814,14 @@ _("sb root inode value %" PRIu64 " valid but in unaligned location (expected %"P
                 * directory.
                 */
                check_metadir_inode(mp, rootino);
-               rootino++;
        }
 
-       validate_sb_ino(&mp->m_sb.sb_rbmino, rootino + 1,
-                       _("realtime bitmap"));
-       validate_sb_ino(&mp->m_sb.sb_rsumino, rootino + 2,
-                       _("realtime summary"));
+       if (!xfs_has_rtgroups(mp)) {
+               validate_sb_ino(&mp->m_sb.sb_rbmino, rootino + 1,
+                               _("realtime bitmap"));
+               validate_sb_ino(&mp->m_sb.sb_rsumino, rootino + 2,
+                               _("realtime summary"));
+       }
 }
 
 /*