]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Skip FREEOBJECTS for objects which can't exist
authorFabian Grünbichler <f.gruenbichler@proxmox.com>
Tue, 26 Sep 2017 12:03:21 +0000 (14:03 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 10 Oct 2017 22:35:49 +0000 (15:35 -0700)
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 <pcd@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Closes #5699
Closes #6507
Closes #6616

module/zfs/dmu_send.c

index dee4cd775e9b716fc067673dd443666c527ecb62..c63ab43e1a02c75052ceb9e2a2adcf944b084023 100644 (file)
@@ -454,6 +454,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,