xfs_fileoff_t           lastoff;
        bool                    is_rt;
        bool                    is_shared;
+       bool                    was_loaded;
        int                     whichfork;
 };
 
 
 /* Cross-reference a single rtdev extent record. */
 STATIC void
-xchk_bmap_rt_extent_xref(
-       struct xchk_bmap_info   *info,
+xchk_bmap_rt_iextent_xref(
        struct xfs_inode        *ip,
-       struct xfs_btree_cur    *cur,
+       struct xchk_bmap_info   *info,
        struct xfs_bmbt_irec    *irec)
 {
-       if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
-               return;
-
        xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
                        irec->br_blockcount);
 }
 
 /* Cross-reference a single datadev extent record. */
 STATIC void
-xchk_bmap_extent_xref(
-       struct xchk_bmap_info   *info,
+xchk_bmap_iextent_xref(
        struct xfs_inode        *ip,
-       struct xfs_btree_cur    *cur,
+       struct xchk_bmap_info   *info,
        struct xfs_bmbt_irec    *irec)
 {
        struct xfs_mount        *mp = info->sc->mp;
        xfs_extlen_t            len;
        int                     error;
 
-       if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
-               return;
-
        agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
        agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
        len = irec->br_blockcount;
 
 /* Scrub a single extent record. */
 STATIC int
-xchk_bmap_extent(
+xchk_bmap_iextent(
        struct xfs_inode        *ip,
-       struct xfs_btree_cur    *cur,
        struct xchk_bmap_info   *info,
        struct xfs_bmbt_irec    *irec)
 {
        struct xfs_mount        *mp = info->sc->mp;
-       struct xfs_buf          *bp = NULL;
        xfs_filblks_t           end;
        int                     error = 0;
 
-       if (cur)
-               xfs_btree_get_block(cur, 0, &bp);
-
        /*
         * Check for out-of-order extents.  This record could have come
         * from the incore list, for which there is no ordering check.
                xchk_fblock_set_corrupt(info->sc, info->whichfork,
                                irec->br_startoff);
 
+       if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
+               return 0;
+
        if (info->is_rt)
-               xchk_bmap_rt_extent_xref(info, ip, cur, irec);
+               xchk_bmap_rt_iextent_xref(ip, info, irec);
        else
-               xchk_bmap_extent_xref(info, ip, cur, irec);
+               xchk_bmap_iextent_xref(ip, info, irec);
 
        info->lastoff = irec->br_startoff + irec->br_blockcount;
        return error;
        union xfs_btree_rec     *rec)
 {
        struct xfs_bmbt_irec    irec;
+       struct xfs_bmbt_irec    iext_irec;
+       struct xfs_iext_cursor  icur;
        struct xchk_bmap_info   *info = bs->private;
        struct xfs_inode        *ip = bs->cur->bc_private.b.ip;
        struct xfs_buf          *bp = NULL;
        struct xfs_btree_block  *block;
+       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, info->whichfork);
        uint64_t                owner;
        int                     i;
 
                }
        }
 
-       /* Set up the in-core record and scrub it. */
+       /*
+        * Check that the incore extent tree contains an extent that matches
+        * this one exactly.  We validate those cached bmaps later, so we don't
+        * need to check them here.  If the incore extent tree was just loaded
+        * from disk by the scrubber, we assume that its contents match what's
+        * on disk (we still hold the ILOCK) and skip the equivalence check.
+        */
+       if (!info->was_loaded)
+               return 0;
+
        xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
-       return xchk_bmap_extent(ip, bs->cur, info, &irec);
+       if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur,
+                               &iext_irec) ||
+           irec.br_startoff != iext_irec.br_startoff ||
+           irec.br_startblock != iext_irec.br_startblock ||
+           irec.br_blockcount != iext_irec.br_blockcount ||
+           irec.br_state != iext_irec.br_state)
+               xchk_fblock_set_corrupt(bs->sc, info->whichfork,
+                               irec.br_startoff);
+       return 0;
 }
 
 /* Scan the btree records. */
        struct xchk_bmap_info   *info)
 {
        struct xfs_owner_info   oinfo;
+       struct xfs_ifork        *ifp = XFS_IFORK_PTR(sc->ip, whichfork);
        struct xfs_mount        *mp = sc->mp;
        struct xfs_inode        *ip = sc->ip;
        struct xfs_btree_cur    *cur;
        int                     error;
 
+       /* Load the incore bmap cache if it's not loaded. */
+       info->was_loaded = ifp->if_flags & XFS_IFEXTENTS;
+       if (!info->was_loaded) {
+               error = xfs_iread_extents(sc->tp, ip, whichfork);
+               if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
+                       goto out;
+       }
+
+       /* Check the btree structure. */
        cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork);
        xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
        error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info);
        xfs_btree_del_cursor(cur, error);
+out:
        return error;
 }
 
        if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
                goto out;
 
-       /* Now try to scrub the in-memory extent list. */
-        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(sc->tp, ip, whichfork);
-               if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
-                       goto out;
-       }
-
        /* Find the offset of the last extent in the mapping. */
        error = xfs_bmap_last_offset(ip, &endoff, whichfork);
        if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
        for_each_xfs_iext(ifp, &icur, &irec) {
                if (xchk_should_terminate(sc, &error) ||
                    (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
-                       break;
+                       goto out;
                if (isnullstartblock(irec.br_startblock))
                        continue;
                if (irec.br_startoff >= endoff) {
                                        irec.br_startoff);
                        goto out;
                }
-               error = xchk_bmap_extent(ip, NULL, &info, &irec);
+               error = xchk_bmap_iextent(ip, &info, &irec);
                if (error)
                        goto out;
        }