]> granicus.if.org Git - zfs/commitdiff
zfs send -p send properties only for snapshots that are actually sent
authorAndriy Gapon <avg@icyb.net.ua>
Thu, 15 May 2014 08:42:19 +0000 (11:42 +0300)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 2 Oct 2014 23:52:02 +0000 (16:52 -0700)
... as opposed to sending properties of all snapshots of the relevant
filesystem.  The previous behavior results in properties being set on
all snapshots on the receiving side, which is quite slow.

Behavior of zfs send -R is not changed.

References:
  http://thread.gmane.org/gmane.comp.file-systems.openzfs.devel/346

Ported-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #2729
Issue #2210

lib/libzfs/libzfs_sendrecv.c

index 3b4acc956907762b37d6aaa34c4411f9f62395d6..ef5747f6459452454a97e7bdf425962bd59641fb 100644 (file)
@@ -577,6 +577,8 @@ typedef struct send_data {
        const char *fromsnap;
        const char *tosnap;
        boolean_t recursive;
+       boolean_t seenfrom;
+       boolean_t seento;
 
        /*
         * The header nvlist is of the following format:
@@ -611,20 +613,39 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
        uint64_t guid = zhp->zfs_dmustats.dds_guid;
        char *snapname;
        nvlist_t *nv;
+       boolean_t isfromsnap, istosnap;
 
        snapname = strrchr(zhp->zfs_name, '@')+1;
+       isfromsnap = (sd->fromsnap != NULL &&
+           strcmp(sd->fromsnap, snapname) == 0);
+       istosnap = (sd->tosnap != NULL && (strcmp(sd->tosnap, snapname) == 0));
 
-       VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
        /*
         * NB: if there is no fromsnap here (it's a newly created fs in
         * an incremental replication), we will substitute the tosnap.
         */
-       if ((sd->fromsnap && strcmp(snapname, sd->fromsnap) == 0) ||
-           (sd->parent_fromsnap_guid == 0 && sd->tosnap &&
-           strcmp(snapname, sd->tosnap) == 0)) {
+       if (isfromsnap || (sd->parent_fromsnap_guid == 0 && istosnap)) {
                sd->parent_fromsnap_guid = guid;
        }
 
+       if (!sd->recursive) {
+               if (!sd->seenfrom && isfromsnap) {
+                       sd->seenfrom = B_TRUE;
+                       zfs_close(zhp);
+                       return (0);
+               }
+
+               if (sd->seento || !sd->seenfrom) {
+                       zfs_close(zhp);
+                       return (0);
+               }
+
+               if (istosnap)
+                       sd->seento = B_TRUE;
+       }
+
+       VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
+
        VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
        send_iterate_prop(zhp, nv);
        VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv));