irec->ir_free = be64_to_cpu(rec->inobt.ir_free);
 }
 
+/* Simple checks for inode records. */
+xfs_failaddr_t
+xfs_inobt_check_irec(
+       struct xfs_btree_cur                    *cur,
+       const struct xfs_inobt_rec_incore       *irec)
+{
+       uint64_t                        realfree;
+
+       if (!xfs_verify_agino(cur->bc_ag.pag, irec->ir_startino))
+               return __this_address;
+       if (irec->ir_count < XFS_INODES_PER_HOLEMASK_BIT ||
+           irec->ir_count > XFS_INODES_PER_CHUNK)
+               return __this_address;
+       if (irec->ir_freecount > XFS_INODES_PER_CHUNK)
+               return __this_address;
+
+       /* if there are no holes, return the first available offset */
+       if (!xfs_inobt_issparse(irec->ir_holemask))
+               realfree = irec->ir_free;
+       else
+               realfree = irec->ir_free & xfs_inobt_irec_to_allocmask(irec);
+       if (hweight64(realfree) != irec->ir_freecount)
+               return __this_address;
+
+       return NULL;
+}
+
 /*
  * Get the data from the pointed-to record.
  */
 {
        struct xfs_mount                *mp = cur->bc_mp;
        union xfs_btree_rec             *rec;
+       xfs_failaddr_t                  fa;
        int                             error;
-       uint64_t                        realfree;
 
        error = xfs_btree_get_rec(cur, &rec, stat);
        if (error || *stat == 0)
                return error;
 
        xfs_inobt_btrec_to_irec(mp, rec, irec);
-
-       if (!xfs_verify_agino(cur->bc_ag.pag, irec->ir_startino))
-               goto out_bad_rec;
-       if (irec->ir_count < XFS_INODES_PER_HOLEMASK_BIT ||
-           irec->ir_count > XFS_INODES_PER_CHUNK)
-               goto out_bad_rec;
-       if (irec->ir_freecount > XFS_INODES_PER_CHUNK)
-               goto out_bad_rec;
-
-       /* if there are no holes, return the first available offset */
-       if (!xfs_inobt_issparse(irec->ir_holemask))
-               realfree = irec->ir_free;
-       else
-               realfree = irec->ir_free & xfs_inobt_irec_to_allocmask(irec);
-       if (hweight64(realfree) != irec->ir_freecount)
+       fa = xfs_inobt_check_irec(cur, irec);
+       if (fa)
                goto out_bad_rec;
 
        return 0;
 
 out_bad_rec:
        xfs_warn(mp,
-               "%s Inode BTree record corruption in AG %d detected!",
+               "%s Inode BTree record corruption in AG %d detected at %pS!",
                cur->bc_btnum == XFS_BTNUM_INO ? "Used" : "Free",
-               cur->bc_ag.pag->pag_agno);
+               cur->bc_ag.pag->pag_agno, fa);
        xfs_warn(mp,
 "start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x",
                irec->ir_startino, irec->ir_count, irec->ir_freecount,
        struct xfs_ialloc_count_inodes  *ci = priv;
 
        xfs_inobt_btrec_to_irec(cur->bc_mp, rec, &irec);
+       if (xfs_inobt_check_irec(cur, &irec) != NULL)
+               return -EFSCORRUPTED;
+
        ci->count += irec.ir_count;
        ci->freecount += irec.ir_freecount;
 
 
 void xfs_inobt_btrec_to_irec(struct xfs_mount *mp,
                const union xfs_btree_rec *rec,
                struct xfs_inobt_rec_incore *irec);
+xfs_failaddr_t xfs_inobt_check_irec(struct xfs_btree_cur *cur,
+               const struct xfs_inobt_rec_incore *irec);
 int xfs_ialloc_has_inodes_at_extent(struct xfs_btree_cur *cur,
                xfs_agblock_t bno, xfs_extlen_t len, bool *exists);
 int xfs_ialloc_has_inode_record(struct xfs_btree_cur *cur, xfs_agino_t low,
 
        return true;
 }
 
-/* Count the number of free inodes. */
-static unsigned int
-xchk_iallocbt_freecount(
-       xfs_inofree_t                   freemask)
-{
-       BUILD_BUG_ON(sizeof(freemask) != sizeof(__u64));
-       return hweight64(freemask);
-}
-
 /*
  * Check that an inode's allocation status matches ir_free in the inobt
  * record.  First we try querying the in-core inode state, and if the inode
        int                             holecount;
        int                             i;
        int                             error = 0;
-       unsigned int                    real_freecount;
        uint16_t                        holemask;
 
        xfs_inobt_btrec_to_irec(mp, rec, &irec);
-
-       if (irec.ir_count > XFS_INODES_PER_CHUNK ||
-           irec.ir_freecount > XFS_INODES_PER_CHUNK)
-               xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
-
-       real_freecount = irec.ir_freecount +
-                       (XFS_INODES_PER_CHUNK - irec.ir_count);
-       if (real_freecount != xchk_iallocbt_freecount(irec.ir_free))
+       if (xfs_inobt_check_irec(bs->cur, &irec) != NULL) {
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
+               return 0;
+       }
 
        agino = irec.ir_startino;
        /* Record has to be properly aligned within the AG. */
-       if (!xfs_verify_agino(pag, agino) ||
-           !xfs_verify_agino(pag, agino + XFS_INODES_PER_CHUNK - 1)) {
+       if (!xfs_verify_agino(pag, agino + XFS_INODES_PER_CHUNK - 1)) {
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
                goto out;
        }