diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 5c45e7d53f2c..0dd2ce013f91 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -199,6 +199,9 @@ dump_record(dmu_sendarg_t *dsp, void *payload, int payload_len) * Note that we send free records even for a full send, because we want to be * able to receive a full send as a clone, which requires a list of all the free * and freeobject records that were generated on the source. + * + * Disable this behaviour by setting zfs_send_set_freerecords_bit to false to + * workaround receiving implementations that cannot handle such streams. */ static int dump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset, @@ -223,6 +226,16 @@ dump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset, (object == dsp->dsa_last_data_object && offset > dsp->dsa_last_data_offset)); + /* + * If we are doing a non-incremental send, then there can't + * be any data in the dataset we're receiving into. Unless we're receiving + * a full send as a clone, a free record would simply be a no-op. + * If we disable the tunable for this, save space by not sending it to + * begin with. + */ + if (!zfs_send_set_freerecords_bit && !dsp->dsa_drr->drr_u.drr_begin.drr_fromguid) + return (0); + if (length != -1ULL && offset + length < offset) length = -1ULL; @@ -455,6 +468,10 @@ dump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs) { struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects); + /* See comment in dump_free(). */ + if (!zfs_send_set_freerecords_bit && !dsp->dsa_drr->drr_u.drr_begin.drr_fromguid) + return (0); + /* * If there is a pending op, but it's not PENDING_FREEOBJECTS, * push it out, since free block aggregation can only be done for