]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: repair rtbitmap block headers
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:06 +0000 (14:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 16 Jul 2024 22:49:16 +0000 (15:49 -0700)
Check and repair the new block headers attached to rtbitmap blocks.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
repair/phase6.c
repair/rt.c
repair/sb.c

index 95300f98974ace9ddc28e8bf0526867faf6a38db..971e671504fef377aa05fddd15b2fe4ec7313bc7 100644 (file)
@@ -616,6 +616,7 @@ fill_rbmino(xfs_mount_t *mp)
                        .tp             = tp,
                };
                union xfs_rtword_raw    *ondisk;
+               xfs_daddr_t             daddr;
 
                /*
                 * fill the file one block at a time
@@ -630,11 +631,9 @@ fill_rbmino(xfs_mount_t *mp)
 
                ASSERT(map.br_startblock != HOLESTARTBLOCK);
 
-               error = -libxfs_trans_read_buf(
-                               mp, tp, mp->m_dev,
-                               XFS_FSB_TO_DADDR(mp, map.br_startblock),
+               daddr = XFS_FSB_TO_DADDR(mp, map.br_startblock);
+               error = -libxfs_trans_read_buf(mp, tp, mp->m_dev, daddr,
                                XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
-
                if (error) {
                        do_warn(
 _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %" PRIu64 "\n"),
@@ -646,6 +645,18 @@ _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %
                ondisk = xfs_rbmblock_wordptr(&args, 0);
                memcpy(ondisk, bmp, mp->m_blockwsize << XFS_WORDLOG);
 
+               if (xfs_has_rtgroups(mp)) {
+                       struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
+
+                       bp->b_ops = &xfs_rtbitmap_buf_ops;
+                       hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC);
+                       hdr->rt_owner = cpu_to_be64(ip->i_ino);
+                       hdr->rt_lsn = 0;
+                       hdr->rt_blkno = cpu_to_be64(daddr);
+                       platform_uuid_copy(&hdr->rt_uuid,
+                                       &mp->m_sb.sb_meta_uuid);
+               }
+
                libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
 
                bmp += mp->m_blockwsize;
index e0acc35305827fe78f70b7f6f3e2783844801929..6c27caac710ce94e6bc91ce4d7664c813c68e35d 100644 (file)
@@ -192,7 +192,8 @@ check_rtfile_contents(
        const char              *filename,
        xfs_ino_t               ino,
        void                    *buf,
-       xfs_fileoff_t           filelen)
+       xfs_fileoff_t           filelen,
+       const struct xfs_buf_ops *buf_ops)
 {
        struct xfs_bmbt_irec    map;
        struct xfs_buf          *bp;
@@ -214,12 +215,10 @@ check_rtfile_contents(
        }
 
        while (bno < filelen)  {
-               xfs_filblks_t   maplen;
+               xfs_daddr_t     daddr;
                int             nmap = 1;
 
-               /* Read up to 1MB at a time. */
-               maplen = min(filelen - bno, XFS_B_TO_FSBT(mp, 1048576));
-               error = -libxfs_bmapi_read(ip, bno, maplen, &map, &nmap, 0);
+               error = -libxfs_bmapi_read(ip, bno, 1, &map, &nmap, 0);
                if (error) {
                        do_warn(_("unable to read %s mapping, err %d\n"),
                                        filename, error);
@@ -232,19 +231,39 @@ check_rtfile_contents(
                        break;
                }
 
-               error = -libxfs_buf_read_uncached(mp->m_dev,
-                               XFS_FSB_TO_DADDR(mp, map.br_startblock),
+               daddr = XFS_FSB_TO_DADDR(mp, map.br_startblock);
+               error = -libxfs_buf_read_uncached(mp->m_dev, daddr,
                                XFS_FSB_TO_BB(mp, map.br_blockcount),
-                               0, &bp, NULL);
+                               0, &bp, buf_ops);
                if (error) {
                        do_warn(_("unable to read %s at dblock 0x%llx, err %d\n"),
                                        filename, (unsigned long long)bno, error);
                        break;
                }
 
-               check_rtwords(mp, filename, bno, bp->b_addr, buf);
+               if (buf_ops == &xfs_rtbitmap_buf_ops) {
+                       struct xfs_rtalloc_args         args = {
+                               .mp                     = mp,
+                       };
+                       struct xfs_rtbuf_blkinfo        *hdr = bp->b_addr;
+                       union xfs_rtword_raw            *incore = buf;
+                       union xfs_rtword_raw            *ondisk;
+
+                       if (hdr->rt_owner != cpu_to_be64(ino)) {
+                               do_warn(
+ _("corrupt owner in %s at dblock 0x%llx\n"),
+                                       filename, (unsigned long long)bno);
+                       }
+
+                       args.rbmbp = bp;
+                       ondisk = xfs_rbmblock_wordptr(&args, 0);
+                       check_rtwords(mp, filename, bno, ondisk, incore);
+                       buf += mp->m_blockwsize << XFS_WORDLOG;
+               } else {
+                       check_rtwords(mp, filename, bno, bp->b_addr, buf);
+                       buf += XFS_FSB_TO_B(mp, map.br_blockcount);
+               }
 
-               buf += XFS_FSB_TO_B(mp, map.br_blockcount);
                bno += map.br_blockcount;
                libxfs_buf_relse(bp);
        }
@@ -256,11 +275,15 @@ void
 check_rtbitmap(
        struct xfs_mount        *mp)
 {
+       const struct xfs_buf_ops *buf_ops = NULL;
+
        if (need_rbmino)
                return;
+       if (xfs_has_rtgroups(mp))
+               buf_ops = &xfs_rtbitmap_buf_ops;
 
        check_rtfile_contents(mp, "rtbitmap", mp->m_sb.sb_rbmino, btmcompute,
-                       mp->m_sb.sb_rbmblocks);
+                       mp->m_sb.sb_rbmblocks, buf_ops);
 }
 
 void
@@ -271,7 +294,7 @@ check_rtsummary(
                return;
 
        check_rtfile_contents(mp, "rtsummary", mp->m_sb.sb_rsumino, sumcompute,
-                       XFS_B_TO_FSB(mp, mp->m_rsumsize));
+                       XFS_B_TO_FSB(mp, mp->m_rsumsize), NULL);
 }
 
 void
index 7205d65a45c8f54cf438759fd8f114d9ebbd2299..ec28803b8847eac3cc6cc163c3ac5c2fbf1ab60d 100644 (file)
@@ -507,6 +507,8 @@ verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb)
                if (sb->sb_frextents != 0)
                        return(XR_BAD_RT_GEO_DATA);
        } else  {
+               unsigned int    rbmblock_bytes = sb->sb_blocksize;
+
                /*
                 * if we have a real-time partition, sanity-check geometry
                 */
@@ -519,8 +521,11 @@ verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb)
                if (sb->sb_rextslog != libxfs_compute_rextslog(sb->sb_rextents))
                        return(XR_BAD_RT_GEO_DATA);
 
+               if (xfs_sb_version_hasrtgroups(sb))
+                       rbmblock_bytes -= sizeof(struct xfs_rtbuf_blkinfo);
+
                if (sb->sb_rbmblocks != (xfs_extlen_t) howmany(sb->sb_rextents,
-                                               NBBY * sb->sb_blocksize))
+                                               NBBY * rbmblock_bytes))
                        return(XR_BAD_RT_GEO_DATA);
        }