dump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs)
{
struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects);
+ uint64_t maxobj = DNODES_PER_BLOCK *
+ (DMU_META_DNODE(dsp->dsa_os)->dn_maxblkid + 1);
+
+ /*
+ * ZoL < 0.7 does not handle large FREEOBJECTS records correctly,
+ * leading to zfs recv never completing. to avoid this issue, don't
+ * send FREEOBJECTS records for object IDs which cannot exist on the
+ * receiving side.
+ */
+ if (maxobj > 0) {
+ if (maxobj < firstobj)
+ return (0);
+
+ if (maxobj < firstobj + numobjs)
+ numobjs = maxobj - firstobj;
+ }
/*
* If there is a pending op, but it's not PENDING_FREEOBJECTS,
dnode_phys_t *dnp)
{
struct drr_object *drro = &(dsp->dsa_drr->drr_u.drr_object);
- int bonuslen = P2ROUNDUP(dnp->dn_bonuslen, 8);
+ int bonuslen;
if (object < dsp->dsa_resume_object) {
/*
drro->drr_blksz > SPA_OLD_MAXBLOCKSIZE)
drro->drr_blksz = SPA_OLD_MAXBLOCKSIZE;
+ bonuslen = P2ROUNDUP(dnp->dn_bonuslen, 8);
+
if ((dsp->dsa_featureflags & DMU_BACKUP_FEATURE_RAW)) {
ASSERT(BP_IS_ENCRYPTED(bp));
/*
* Since we encrypt the entire bonus area, the (raw) part
- * beyond the the bonuslen is actually nonzero, so we need
+ * beyond the bonuslen is actually nonzero, so we need
* to send it.
*/
if (bonuslen != 0) {