diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 7ce83f766aa9..308b5207b3db 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -578,6 +578,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: @@ -612,20 +614,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)); @@ -746,7 +767,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) sd->parent_fromsnap_guid = 0; VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0)); VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0)); - (void) zfs_iter_snapshots(zhp, B_FALSE, send_iterate_snap, sd); + (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd); VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps)); VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops)); nvlist_free(sd->parent_snaps);