summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Grünbichler <[email protected]>2017-09-26 14:03:21 +0200
committerTony Hutter <[email protected]>2017-10-16 10:57:55 -0700
commit8d688ce66acab2b92a10361f9ee617c1d729770c (patch)
tree1870fbbf5a329f5f9e8d45129697a64d5c01d043
parentb544fe4123167e15bb0687e3918e8569a55fed3e (diff)
Skip FREEOBJECTS for objects which can't exist
When sending an incremental stream based on a snapshot, the receiving side must have the same base snapshot. Thus we do not need to send FREEOBJECTS records for any objects past the maximum one which exists locally. This allows us to send incremental streams (again) to older ZFS implementations (e.g. ZoL < 0.7) which actually try to free all objects in a FREEOBJECTS record, instead of bailing out early. Reviewed by: Paul Dagnelie <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Fabian Grünbichler <[email protected]> Closes #5699 Closes #6507 Closes #6616
-rw-r--r--module/zfs/dmu_send.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c
index 0fd2d6a5e..344e42018 100644
--- a/module/zfs/dmu_send.c
+++ b/module/zfs/dmu_send.c
@@ -421,6 +421,22 @@ static int
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,