xfs: rtbitmap scrubber should verify written extents
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 2 Jul 2020 15:42:12 +0000 (08:42 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Tue, 7 Jul 2020 14:15:09 +0000 (07:15 -0700)
Ensure that the realtime bitmap file is backed entirely by written
extents.  No holes, no unwritten blocks, etc.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
fs/xfs/scrub/rtbitmap.c

index c642bc2..c777c98 100644 (file)
@@ -13,6 +13,7 @@
 #include "xfs_trans.h"
 #include "xfs_rtalloc.h"
 #include "xfs_inode.h"
+#include "xfs_bmap.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 
@@ -58,6 +59,41 @@ xchk_rtbitmap_rec(
        return 0;
 }
 
+/* Make sure the entire rtbitmap file is mapped with written extents. */
+STATIC int
+xchk_rtbitmap_check_extents(
+       struct xfs_scrub        *sc)
+{
+       struct xfs_mount        *mp = sc->mp;
+       struct xfs_bmbt_irec    map;
+       xfs_rtblock_t           off;
+       int                     nmap;
+       int                     error = 0;
+
+       for (off = 0; off < mp->m_sb.sb_rbmblocks;) {
+               if (xchk_should_terminate(sc, &error) ||
+                   (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
+                       break;
+
+               /* Make sure we have a written extent. */
+               nmap = 1;
+               error = xfs_bmapi_read(mp->m_rbmip, off,
+                               mp->m_sb.sb_rbmblocks - off, &map, &nmap,
+                               XFS_DATA_FORK);
+               if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
+                       break;
+
+               if (nmap != 1 || !xfs_bmap_is_written_extent(&map)) {
+                       xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
+                       break;
+               }
+
+               off += map.br_blockcount;
+       }
+
+       return error;
+}
+
 /* Scrub the realtime bitmap. */
 int
 xchk_rtbitmap(
@@ -70,6 +106,10 @@ xchk_rtbitmap(
        if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
                return error;
 
+       error = xchk_rtbitmap_check_extents(sc);
+       if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
+               return error;
+
        error = xfs_rtalloc_query_all(sc->tp, xchk_rtbitmap_rec, sc);
        if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
                goto out;