Index: stand/libsa/zfs/zfsimpl.c =================================================================== --- stand/libsa/zfs/zfsimpl.c +++ stand/libsa/zfs/zfsimpl.c @@ -151,6 +151,8 @@ static uint64_t dnode_cache_bn; static char *dnode_cache_buf; +static int zfs_dnode_stat(const spa_t *spa, const dnode_phys_t *dn, struct stat *sb); + static int zio_read(const spa_t *spa, const blkptr_t *bp, void *buf); static int zfs_get_root(const spa_t *spa, uint64_t *objid); static int zfs_rlookup(const spa_t *spa, uint64_t objnum, char *result); @@ -2349,6 +2351,19 @@ return (EIO); } + /* + * Handle odd block sizes, mirrors dmu_read_impl(). Data can't exist + * past the first block, so we'll clip the read to the portion of the + * buffer within bsize and zero out the remainder. + */ + if (dnode->dn_maxblkid == 0) { + size_t newbuflen; + + newbuflen = offset > bsize ? 0 : MIN(buflen, bsize - offset); + bzero((char *)buf + newbuflen, buflen - newbuflen); + buflen = newbuflen; + } + /* * Note: bsize may not be a power of two here so we need to do an * actual divide rather than a bitshift. @@ -3521,7 +3536,7 @@ } static int -zfs_dnode_stat(const spa_t *spa, dnode_phys_t *dn, struct stat *sb) +zfs_dnode_stat(const spa_t *spa, const dnode_phys_t *dn, struct stat *sb) { if (dn->dn_bonustype != DMU_OT_SA) {