__return_address);
 }
 
+/*
+ * Make sure this record is in order and doesn't stray outside of the parent
+ * keys.
+ */
+STATIC void
+xfs_scrub_btree_rec(
+       struct xfs_scrub_btree  *bs)
+{
+       struct xfs_btree_cur    *cur = bs->cur;
+       union xfs_btree_rec     *rec;
+       union xfs_btree_key     key;
+       union xfs_btree_key     hkey;
+       union xfs_btree_key     *keyp;
+       struct xfs_btree_block  *block;
+       struct xfs_btree_block  *keyblock;
+       struct xfs_buf          *bp;
+
+       block = xfs_btree_get_block(cur, 0, &bp);
+       rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
+
+       trace_xfs_scrub_btree_rec(bs->sc, cur, 0);
+
+       /* If this isn't the first record, are they in order? */
+       if (!bs->firstrec && !cur->bc_ops->recs_inorder(cur, &bs->lastrec, rec))
+               xfs_scrub_btree_set_corrupt(bs->sc, cur, 0);
+       bs->firstrec = false;
+       memcpy(&bs->lastrec, rec, cur->bc_ops->rec_len);
+
+       if (cur->bc_nlevels == 1)
+               return;
+
+       /* Is this at least as large as the parent low key? */
+       cur->bc_ops->init_key_from_rec(&key, rec);
+       keyblock = xfs_btree_get_block(cur, 1, &bp);
+       keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[1], keyblock);
+       if (cur->bc_ops->diff_two_keys(cur, &key, keyp) < 0)
+               xfs_scrub_btree_set_corrupt(bs->sc, cur, 1);
+
+       if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
+               return;
+
+       /* Is this no larger than the parent high key? */
+       cur->bc_ops->init_high_key_from_rec(&hkey, rec);
+       keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[1], keyblock);
+       if (cur->bc_ops->diff_two_keys(cur, keyp, &hkey) < 0)
+               xfs_scrub_btree_set_corrupt(bs->sc, cur, 1);
+}
+
+/*
+ * Make sure this key is in order and doesn't stray outside of the parent
+ * keys.
+ */
+STATIC void
+xfs_scrub_btree_key(
+       struct xfs_scrub_btree  *bs,
+       int                     level)
+{
+       struct xfs_btree_cur    *cur = bs->cur;
+       union xfs_btree_key     *key;
+       union xfs_btree_key     *keyp;
+       struct xfs_btree_block  *block;
+       struct xfs_btree_block  *keyblock;
+       struct xfs_buf          *bp;
+
+       block = xfs_btree_get_block(cur, level, &bp);
+       key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block);
+
+       trace_xfs_scrub_btree_key(bs->sc, cur, level);
+
+       /* If this isn't the first key, are they in order? */
+       if (!bs->firstkey[level] &&
+           !cur->bc_ops->keys_inorder(cur, &bs->lastkey[level], key))
+               xfs_scrub_btree_set_corrupt(bs->sc, cur, level);
+       bs->firstkey[level] = false;
+       memcpy(&bs->lastkey[level], key, cur->bc_ops->key_len);
+
+       if (level + 1 >= cur->bc_nlevels)
+               return;
+
+       /* Is this at least as large as the parent low key? */
+       keyblock = xfs_btree_get_block(cur, level + 1, &bp);
+       keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], keyblock);
+       if (cur->bc_ops->diff_two_keys(cur, key, keyp) < 0)
+               xfs_scrub_btree_set_corrupt(bs->sc, cur, level);
+
+       if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
+               return;
+
+       /* Is this no larger than the parent high key? */
+       key = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block);
+       keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], keyblock);
+       if (cur->bc_ops->diff_two_keys(cur, keyp, key) < 0)
+               xfs_scrub_btree_set_corrupt(bs->sc, cur, level);
+}
+
 /*
  * Check a btree pointer.  Returns true if it's ok to use this pointer.
  * Callers do not need to set the corrupt flag.
        struct xfs_scrub_btree          bs = {0};
        union xfs_btree_ptr             ptr;
        union xfs_btree_ptr             *pp;
+       union xfs_btree_rec             *recp;
        struct xfs_btree_block          *block;
        int                             level;
        struct xfs_buf                  *bp;
                                continue;
                        }
 
-                       if (xfs_scrub_should_terminate(sc, &error))
+                       /* Records in order for scrub? */
+                       xfs_scrub_btree_rec(&bs);
+
+                       /* Call out to the record checker. */
+                       recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
+                       error = bs.scrub_rec(&bs, recp);
+                       if (error)
+                               break;
+                       if (xfs_scrub_should_terminate(sc, &error) ||
+                           (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
                                break;
 
                        cur->bc_ptrs[level]++;
                        continue;
                }
 
+               /* Keys in order for scrub? */
+               xfs_scrub_btree_key(&bs, level);
+
                /* Drill another level deeper. */
                pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block);
                if (!xfs_scrub_btree_ptr_ok(&bs, level, pp)) {
 
                  __entry->ret_ip)
 );
 
+DECLARE_EVENT_CLASS(xfs_scrub_sbtree_class,
+       TP_PROTO(struct xfs_scrub_context *sc, struct xfs_btree_cur *cur,
+                int level),
+       TP_ARGS(sc, cur, level),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(int, type)
+               __field(xfs_btnum_t, btnum)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agblock_t, bno)
+               __field(int, level)
+               __field(int, nlevels)
+               __field(int, ptr)
+       ),
+       TP_fast_assign(
+               xfs_fsblock_t fsbno = xfs_scrub_btree_cur_fsbno(cur, level);
+
+               __entry->dev = sc->mp->m_super->s_dev;
+               __entry->type = sc->sm->sm_type;
+               __entry->btnum = cur->bc_btnum;
+               __entry->agno = XFS_FSB_TO_AGNO(cur->bc_mp, fsbno);
+               __entry->bno = XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno);
+               __entry->level = level;
+               __entry->nlevels = cur->bc_nlevels;
+               __entry->ptr = cur->bc_ptrs[level];
+       ),
+       TP_printk("dev %d:%d type %u btnum %d agno %u agbno %u level %d nlevels %d ptr %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->type,
+                 __entry->btnum,
+                 __entry->agno,
+                 __entry->bno,
+                 __entry->level,
+                 __entry->nlevels,
+                 __entry->ptr)
+)
+#define DEFINE_SCRUB_SBTREE_EVENT(name) \
+DEFINE_EVENT(xfs_scrub_sbtree_class, name, \
+       TP_PROTO(struct xfs_scrub_context *sc, struct xfs_btree_cur *cur, \
+                int level), \
+       TP_ARGS(sc, cur, level))
+
+DEFINE_SCRUB_SBTREE_EVENT(xfs_scrub_btree_rec);
+DEFINE_SCRUB_SBTREE_EVENT(xfs_scrub_btree_key);
+
 #endif /* _TRACE_XFS_SCRUB_TRACE_H */
 
 #undef TRACE_INCLUDE_PATH