4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012 by Delphix. All rights reserved.
25 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
41 #include <sys/mount.h>
42 #include <sys/mntent.h>
43 #include <sys/mnttab.h>
45 #include <sys/debug.h>
53 #include "zfs_namecheck.h"
55 #include "zfs_fletcher.h"
56 #include "libzfs_impl.h"
57 #include <sys/zio_checksum.h>
59 #include <sys/socket.h>
61 /* in libzfs_dataset.c */
62 extern void zfs_setprop_error(libzfs_handle_t
*, zfs_prop_t
, int, char *);
64 static int zfs_receive_impl(libzfs_handle_t
*, const char *, recvflags_t
*,
65 int, const char *, nvlist_t
*, avl_tree_t
*, char **, int, uint64_t *);
67 static const zio_cksum_t zero_cksum
= { { 0 } };
69 typedef struct dedup_arg
{
72 libzfs_handle_t
*dedup_hdl
;
75 typedef struct progress_arg
{
78 boolean_t pa_parsable
;
81 typedef struct dataref
{
87 typedef struct dedup_entry
{
88 struct dedup_entry
*dde_next
;
89 zio_cksum_t dde_chksum
;
94 #define MAX_DDT_PHYSMEM_PERCENT 20
95 #define SMALLEST_POSSIBLE_MAX_DDT_MB 128
97 typedef struct dedup_table
{
98 dedup_entry_t
**dedup_hash_array
;
99 umem_cache_t
*ddecache
;
100 uint64_t max_ddt_size
; /* max dedup table size in bytes */
101 uint64_t cur_ddt_size
; /* current dedup table size in bytes */
108 high_order_bit(uint64_t n
)
112 for (count
= 0; n
!= 0; count
++)
118 ssread(void *buf
, size_t len
, FILE *stream
)
122 if ((outlen
= fread(buf
, len
, 1, stream
)) == 0)
129 ddt_hash_append(libzfs_handle_t
*hdl
, dedup_table_t
*ddt
, dedup_entry_t
**ddepp
,
130 zio_cksum_t
*cs
, uint64_t prop
, dataref_t
*dr
)
134 if (ddt
->cur_ddt_size
>= ddt
->max_ddt_size
) {
135 if (ddt
->ddt_full
== B_FALSE
) {
136 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
137 "Dedup table full. Deduplication will continue "
138 "with existing table entries"));
139 ddt
->ddt_full
= B_TRUE
;
144 if ((dde
= umem_cache_alloc(ddt
->ddecache
, UMEM_DEFAULT
))
146 assert(*ddepp
== NULL
);
147 dde
->dde_next
= NULL
;
148 dde
->dde_chksum
= *cs
;
149 dde
->dde_prop
= prop
;
152 ddt
->cur_ddt_size
+= sizeof (dedup_entry_t
);
158 * Using the specified dedup table, do a lookup for an entry with
159 * the checksum cs. If found, return the block's reference info
160 * in *dr. Otherwise, insert a new entry in the dedup table, using
161 * the reference information specified by *dr.
163 * return value: true - entry was found
164 * false - entry was not found
167 ddt_update(libzfs_handle_t
*hdl
, dedup_table_t
*ddt
, zio_cksum_t
*cs
,
168 uint64_t prop
, dataref_t
*dr
)
171 dedup_entry_t
**ddepp
;
173 hashcode
= BF64_GET(cs
->zc_word
[0], 0, ddt
->numhashbits
);
175 for (ddepp
= &(ddt
->dedup_hash_array
[hashcode
]); *ddepp
!= NULL
;
176 ddepp
= &((*ddepp
)->dde_next
)) {
177 if (ZIO_CHECKSUM_EQUAL(((*ddepp
)->dde_chksum
), *cs
) &&
178 (*ddepp
)->dde_prop
== prop
) {
179 *dr
= (*ddepp
)->dde_ref
;
183 ddt_hash_append(hdl
, ddt
, ddepp
, cs
, prop
, dr
);
188 cksum_and_write(const void *buf
, uint64_t len
, zio_cksum_t
*zc
, int outfd
)
190 fletcher_4_incremental_native(buf
, len
, zc
);
191 return (write(outfd
, buf
, len
));
195 * This function is started in a separate thread when the dedup option
196 * has been requested. The main send thread determines the list of
197 * snapshots to be included in the send stream and makes the ioctl calls
198 * for each one. But instead of having the ioctl send the output to the
199 * the output fd specified by the caller of zfs_send()), the
200 * ioctl is told to direct the output to a pipe, which is read by the
201 * alternate thread running THIS function. This function does the
203 * 1. building a dedup table (the DDT)
204 * 2. doing checksums on each data block and inserting a record in the DDT
205 * 3. looking for matching checksums, and
206 * 4. sending a DRR_WRITE_BYREF record instead of a write record whenever
207 * a duplicate block is found.
208 * The output of this function then goes to the output fd requested
209 * by the caller of zfs_send().
214 dedup_arg_t
*dda
= arg
;
215 char *buf
= malloc(1<<20);
216 dmu_replay_record_t thedrr
;
217 dmu_replay_record_t
*drr
= &thedrr
;
218 struct drr_begin
*drrb
= &thedrr
.drr_u
.drr_begin
;
219 struct drr_end
*drre
= &thedrr
.drr_u
.drr_end
;
220 struct drr_object
*drro
= &thedrr
.drr_u
.drr_object
;
221 struct drr_write
*drrw
= &thedrr
.drr_u
.drr_write
;
222 struct drr_spill
*drrs
= &thedrr
.drr_u
.drr_spill
;
225 dmu_replay_record_t wbr_drr
= {0};
226 struct drr_write_byref
*wbr_drrr
= &wbr_drr
.drr_u
.drr_write_byref
;
228 zio_cksum_t stream_cksum
;
229 uint64_t physmem
= sysconf(_SC_PHYS_PAGES
) * sysconf(_SC_PAGESIZE
);
233 MAX((physmem
* MAX_DDT_PHYSMEM_PERCENT
)/100,
234 SMALLEST_POSSIBLE_MAX_DDT_MB
<<20);
236 numbuckets
= ddt
.max_ddt_size
/(sizeof (dedup_entry_t
));
239 * numbuckets must be a power of 2. Increase number to
240 * a power of 2 if necessary.
242 if (!ISP2(numbuckets
))
243 numbuckets
= 1 << high_order_bit(numbuckets
);
245 ddt
.dedup_hash_array
= calloc(numbuckets
, sizeof (dedup_entry_t
*));
246 ddt
.ddecache
= umem_cache_create("dde", sizeof (dedup_entry_t
), 0,
247 NULL
, NULL
, NULL
, NULL
, NULL
, 0);
248 ddt
.cur_ddt_size
= numbuckets
* sizeof (dedup_entry_t
*);
249 ddt
.numhashbits
= high_order_bit(numbuckets
) - 1;
250 ddt
.ddt_full
= B_FALSE
;
252 /* Initialize the write-by-reference block. */
253 wbr_drr
.drr_type
= DRR_WRITE_BYREF
;
254 wbr_drr
.drr_payloadlen
= 0;
256 outfd
= dda
->outputfd
;
257 ofp
= fdopen(dda
->inputfd
, "r");
258 while (ssread(drr
, sizeof (dmu_replay_record_t
), ofp
) != 0) {
260 switch (drr
->drr_type
) {
264 ZIO_SET_CHECKSUM(&stream_cksum
, 0, 0, 0, 0);
266 /* set the DEDUP feature flag for this stream */
267 fflags
= DMU_GET_FEATUREFLAGS(drrb
->drr_versioninfo
);
268 fflags
|= (DMU_BACKUP_FEATURE_DEDUP
|
269 DMU_BACKUP_FEATURE_DEDUPPROPS
);
270 DMU_SET_FEATUREFLAGS(drrb
->drr_versioninfo
, fflags
);
272 if (cksum_and_write(drr
, sizeof (dmu_replay_record_t
),
273 &stream_cksum
, outfd
) == -1)
275 if (DMU_GET_STREAM_HDRTYPE(drrb
->drr_versioninfo
) ==
276 DMU_COMPOUNDSTREAM
&& drr
->drr_payloadlen
!= 0) {
277 int sz
= drr
->drr_payloadlen
;
283 (void) ssread(buf
, sz
, ofp
);
286 if (cksum_and_write(buf
, sz
, &stream_cksum
,
295 /* use the recalculated checksum */
296 ZIO_SET_CHECKSUM(&drre
->drr_checksum
,
297 stream_cksum
.zc_word
[0], stream_cksum
.zc_word
[1],
298 stream_cksum
.zc_word
[2], stream_cksum
.zc_word
[3]);
299 if ((write(outfd
, drr
,
300 sizeof (dmu_replay_record_t
))) == -1)
307 if (cksum_and_write(drr
, sizeof (dmu_replay_record_t
),
308 &stream_cksum
, outfd
) == -1)
310 if (drro
->drr_bonuslen
> 0) {
312 P2ROUNDUP((uint64_t)drro
->drr_bonuslen
, 8),
314 if (cksum_and_write(buf
,
315 P2ROUNDUP((uint64_t)drro
->drr_bonuslen
, 8),
316 &stream_cksum
, outfd
) == -1)
324 if (cksum_and_write(drr
, sizeof (dmu_replay_record_t
),
325 &stream_cksum
, outfd
) == -1)
327 (void) ssread(buf
, drrs
->drr_length
, ofp
);
328 if (cksum_and_write(buf
, drrs
->drr_length
,
329 &stream_cksum
, outfd
) == -1)
334 case DRR_FREEOBJECTS
:
336 if (cksum_and_write(drr
, sizeof (dmu_replay_record_t
),
337 &stream_cksum
, outfd
) == -1)
346 (void) ssread(buf
, drrw
->drr_length
, ofp
);
349 * Use the existing checksum if it's dedup-capable,
350 * else calculate a SHA256 checksum for it.
353 if (ZIO_CHECKSUM_EQUAL(drrw
->drr_key
.ddk_cksum
,
355 !DRR_IS_DEDUP_CAPABLE(drrw
->drr_checksumflags
)) {
356 zio_cksum_t tmpsha256
;
358 zio_checksum_SHA256(buf
,
359 drrw
->drr_length
, &tmpsha256
);
361 drrw
->drr_key
.ddk_cksum
.zc_word
[0] =
362 BE_64(tmpsha256
.zc_word
[0]);
363 drrw
->drr_key
.ddk_cksum
.zc_word
[1] =
364 BE_64(tmpsha256
.zc_word
[1]);
365 drrw
->drr_key
.ddk_cksum
.zc_word
[2] =
366 BE_64(tmpsha256
.zc_word
[2]);
367 drrw
->drr_key
.ddk_cksum
.zc_word
[3] =
368 BE_64(tmpsha256
.zc_word
[3]);
369 drrw
->drr_checksumtype
= ZIO_CHECKSUM_SHA256
;
370 drrw
->drr_checksumflags
= DRR_CHECKSUM_DEDUP
;
373 dataref
.ref_guid
= drrw
->drr_toguid
;
374 dataref
.ref_object
= drrw
->drr_object
;
375 dataref
.ref_offset
= drrw
->drr_offset
;
377 if (ddt_update(dda
->dedup_hdl
, &ddt
,
378 &drrw
->drr_key
.ddk_cksum
, drrw
->drr_key
.ddk_prop
,
380 /* block already present in stream */
381 wbr_drrr
->drr_object
= drrw
->drr_object
;
382 wbr_drrr
->drr_offset
= drrw
->drr_offset
;
383 wbr_drrr
->drr_length
= drrw
->drr_length
;
384 wbr_drrr
->drr_toguid
= drrw
->drr_toguid
;
385 wbr_drrr
->drr_refguid
= dataref
.ref_guid
;
386 wbr_drrr
->drr_refobject
=
388 wbr_drrr
->drr_refoffset
=
391 wbr_drrr
->drr_checksumtype
=
392 drrw
->drr_checksumtype
;
393 wbr_drrr
->drr_checksumflags
=
394 drrw
->drr_checksumtype
;
395 wbr_drrr
->drr_key
.ddk_cksum
=
396 drrw
->drr_key
.ddk_cksum
;
397 wbr_drrr
->drr_key
.ddk_prop
=
398 drrw
->drr_key
.ddk_prop
;
400 if (cksum_and_write(&wbr_drr
,
401 sizeof (dmu_replay_record_t
), &stream_cksum
,
405 /* block not previously seen */
406 if (cksum_and_write(drr
,
407 sizeof (dmu_replay_record_t
), &stream_cksum
,
410 if (cksum_and_write(buf
,
412 &stream_cksum
, outfd
) == -1)
420 if (cksum_and_write(drr
, sizeof (dmu_replay_record_t
),
421 &stream_cksum
, outfd
) == -1)
427 (void) printf("INVALID record type 0x%x\n",
429 /* should never happen, so assert */
434 umem_cache_destroy(ddt
.ddecache
);
435 free(ddt
.dedup_hash_array
);
443 * Routines for dealing with the AVL tree of fs-nvlists
445 typedef struct fsavl_node
{
453 fsavl_compare(const void *arg1
, const void *arg2
)
455 const fsavl_node_t
*fn1
= arg1
;
456 const fsavl_node_t
*fn2
= arg2
;
458 if (fn1
->fn_guid
> fn2
->fn_guid
)
460 else if (fn1
->fn_guid
< fn2
->fn_guid
)
467 * Given the GUID of a snapshot, find its containing filesystem and
471 fsavl_find(avl_tree_t
*avl
, uint64_t snapguid
, char **snapname
)
473 fsavl_node_t fn_find
;
476 fn_find
.fn_guid
= snapguid
;
478 fn
= avl_find(avl
, &fn_find
, NULL
);
481 *snapname
= fn
->fn_snapname
;
482 return (fn
->fn_nvfs
);
488 fsavl_destroy(avl_tree_t
*avl
)
497 while ((fn
= avl_destroy_nodes(avl
, &cookie
)) != NULL
)
504 * Given an nvlist, produce an avl tree of snapshots, ordered by guid
507 fsavl_create(nvlist_t
*fss
)
510 nvpair_t
*fselem
= NULL
;
512 if ((fsavl
= malloc(sizeof (avl_tree_t
))) == NULL
)
515 avl_create(fsavl
, fsavl_compare
, sizeof (fsavl_node_t
),
516 offsetof(fsavl_node_t
, fn_node
));
518 while ((fselem
= nvlist_next_nvpair(fss
, fselem
)) != NULL
) {
519 nvlist_t
*nvfs
, *snaps
;
520 nvpair_t
*snapelem
= NULL
;
522 VERIFY(0 == nvpair_value_nvlist(fselem
, &nvfs
));
523 VERIFY(0 == nvlist_lookup_nvlist(nvfs
, "snaps", &snaps
));
526 nvlist_next_nvpair(snaps
, snapelem
)) != NULL
) {
530 VERIFY(0 == nvpair_value_uint64(snapelem
, &guid
));
531 if ((fn
= malloc(sizeof (fsavl_node_t
))) == NULL
) {
532 fsavl_destroy(fsavl
);
536 fn
->fn_snapname
= nvpair_name(snapelem
);
540 * Note: if there are multiple snaps with the
541 * same GUID, we ignore all but one.
543 if (avl_find(fsavl
, fn
, NULL
) == NULL
)
554 * Routines for dealing with the giant nvlist of fs-nvlists, etc.
556 typedef struct send_data
{
557 uint64_t parent_fromsnap_guid
;
558 nvlist_t
*parent_snaps
;
561 const char *fromsnap
;
566 * The header nvlist is of the following format:
569 * "fromsnap" -> string (if incremental)
573 * "name" -> string (full name; for debugging)
574 * "parentfromsnap" -> number (guid of fromsnap in parent)
576 * "props" -> { name -> value (only if set here) }
577 * "snaps" -> { name (lastname) -> number (guid) }
578 * "snapprops" -> { name (lastname) -> { name -> value } }
580 * "origin" -> number (guid) (if clone)
581 * "sent" -> boolean (not on-disk)
589 static void send_iterate_prop(zfs_handle_t
*zhp
, nvlist_t
*nv
);
592 send_iterate_snap(zfs_handle_t
*zhp
, void *arg
)
594 send_data_t
*sd
= arg
;
595 uint64_t guid
= zhp
->zfs_dmustats
.dds_guid
;
599 snapname
= strrchr(zhp
->zfs_name
, '@')+1;
601 VERIFY(0 == nvlist_add_uint64(sd
->parent_snaps
, snapname
, guid
));
603 * NB: if there is no fromsnap here (it's a newly created fs in
604 * an incremental replication), we will substitute the tosnap.
606 if ((sd
->fromsnap
&& strcmp(snapname
, sd
->fromsnap
) == 0) ||
607 (sd
->parent_fromsnap_guid
== 0 && sd
->tosnap
&&
608 strcmp(snapname
, sd
->tosnap
) == 0)) {
609 sd
->parent_fromsnap_guid
= guid
;
612 VERIFY(0 == nvlist_alloc(&nv
, NV_UNIQUE_NAME
, 0));
613 send_iterate_prop(zhp
, nv
);
614 VERIFY(0 == nvlist_add_nvlist(sd
->snapprops
, snapname
, nv
));
622 send_iterate_prop(zfs_handle_t
*zhp
, nvlist_t
*nv
)
624 nvpair_t
*elem
= NULL
;
626 while ((elem
= nvlist_next_nvpair(zhp
->zfs_props
, elem
)) != NULL
) {
627 char *propname
= nvpair_name(elem
);
628 zfs_prop_t prop
= zfs_name_to_prop(propname
);
631 if (!zfs_prop_user(propname
)) {
633 * Realistically, this should never happen. However,
634 * we want the ability to add DSL properties without
635 * needing to make incompatible version changes. We
636 * need to ignore unknown properties to allow older
637 * software to still send datasets containing these
638 * properties, with the unknown properties elided.
640 if (prop
== ZPROP_INVAL
)
643 if (zfs_prop_readonly(prop
))
647 verify(nvpair_value_nvlist(elem
, &propnv
) == 0);
648 if (prop
== ZFS_PROP_QUOTA
|| prop
== ZFS_PROP_RESERVATION
||
649 prop
== ZFS_PROP_REFQUOTA
||
650 prop
== ZFS_PROP_REFRESERVATION
) {
653 verify(nvlist_lookup_uint64(propnv
,
654 ZPROP_VALUE
, &value
) == 0);
655 if (zhp
->zfs_type
== ZFS_TYPE_SNAPSHOT
)
658 * May have no source before SPA_VERSION_RECVD_PROPS,
659 * but is still modifiable.
661 if (nvlist_lookup_string(propnv
,
662 ZPROP_SOURCE
, &source
) == 0) {
663 if ((strcmp(source
, zhp
->zfs_name
) != 0) &&
665 ZPROP_SOURCE_VAL_RECVD
) != 0))
670 if (nvlist_lookup_string(propnv
,
671 ZPROP_SOURCE
, &source
) != 0)
673 if ((strcmp(source
, zhp
->zfs_name
) != 0) &&
674 (strcmp(source
, ZPROP_SOURCE_VAL_RECVD
) != 0))
678 if (zfs_prop_user(propname
) ||
679 zfs_prop_get_type(prop
) == PROP_TYPE_STRING
) {
681 verify(nvlist_lookup_string(propnv
,
682 ZPROP_VALUE
, &value
) == 0);
683 VERIFY(0 == nvlist_add_string(nv
, propname
, value
));
686 verify(nvlist_lookup_uint64(propnv
,
687 ZPROP_VALUE
, &value
) == 0);
688 VERIFY(0 == nvlist_add_uint64(nv
, propname
, value
));
694 * recursively generate nvlists describing datasets. See comment
695 * for the data structure send_data_t above for description of contents
699 send_iterate_fs(zfs_handle_t
*zhp
, void *arg
)
701 send_data_t
*sd
= arg
;
704 uint64_t parent_fromsnap_guid_save
= sd
->parent_fromsnap_guid
;
705 uint64_t guid
= zhp
->zfs_dmustats
.dds_guid
;
708 VERIFY(0 == nvlist_alloc(&nvfs
, NV_UNIQUE_NAME
, 0));
709 VERIFY(0 == nvlist_add_string(nvfs
, "name", zhp
->zfs_name
));
710 VERIFY(0 == nvlist_add_uint64(nvfs
, "parentfromsnap",
711 sd
->parent_fromsnap_guid
));
713 if (zhp
->zfs_dmustats
.dds_origin
[0]) {
714 zfs_handle_t
*origin
= zfs_open(zhp
->zfs_hdl
,
715 zhp
->zfs_dmustats
.dds_origin
, ZFS_TYPE_SNAPSHOT
);
718 VERIFY(0 == nvlist_add_uint64(nvfs
, "origin",
719 origin
->zfs_dmustats
.dds_guid
));
722 /* iterate over props */
723 VERIFY(0 == nvlist_alloc(&nv
, NV_UNIQUE_NAME
, 0));
724 send_iterate_prop(zhp
, nv
);
725 VERIFY(0 == nvlist_add_nvlist(nvfs
, "props", nv
));
728 /* iterate over snaps, and set sd->parent_fromsnap_guid */
729 sd
->parent_fromsnap_guid
= 0;
730 VERIFY(0 == nvlist_alloc(&sd
->parent_snaps
, NV_UNIQUE_NAME
, 0));
731 VERIFY(0 == nvlist_alloc(&sd
->snapprops
, NV_UNIQUE_NAME
, 0));
732 (void) zfs_iter_snapshots(zhp
, B_FALSE
, send_iterate_snap
, sd
);
733 VERIFY(0 == nvlist_add_nvlist(nvfs
, "snaps", sd
->parent_snaps
));
734 VERIFY(0 == nvlist_add_nvlist(nvfs
, "snapprops", sd
->snapprops
));
735 nvlist_free(sd
->parent_snaps
);
736 nvlist_free(sd
->snapprops
);
738 /* add this fs to nvlist */
739 (void) snprintf(guidstring
, sizeof (guidstring
),
740 "0x%llx", (longlong_t
)guid
);
741 VERIFY(0 == nvlist_add_nvlist(sd
->fss
, guidstring
, nvfs
));
744 /* iterate over children */
746 rv
= zfs_iter_filesystems(zhp
, send_iterate_fs
, sd
);
748 sd
->parent_fromsnap_guid
= parent_fromsnap_guid_save
;
755 gather_nvlist(libzfs_handle_t
*hdl
, const char *fsname
, const char *fromsnap
,
756 const char *tosnap
, boolean_t recursive
, nvlist_t
**nvlp
, avl_tree_t
**avlp
)
759 send_data_t sd
= { 0 };
762 zhp
= zfs_open(hdl
, fsname
, ZFS_TYPE_FILESYSTEM
| ZFS_TYPE_VOLUME
);
764 return (EZFS_BADTYPE
);
766 VERIFY(0 == nvlist_alloc(&sd
.fss
, NV_UNIQUE_NAME
, 0));
767 sd
.fromsnap
= fromsnap
;
769 sd
.recursive
= recursive
;
771 if ((error
= send_iterate_fs(zhp
, &sd
)) != 0) {
779 if (avlp
!= NULL
&& (*avlp
= fsavl_create(sd
.fss
)) == NULL
) {
790 * Routines specific to "zfs send"
792 typedef struct send_dump_data
{
793 /* these are all just the short snapname (the part after the @) */
794 const char *fromsnap
;
796 char prevsnap
[ZFS_MAXNAMELEN
];
797 uint64_t prevsnap_obj
;
798 boolean_t seenfrom
, seento
, replicate
, doall
, fromorigin
;
799 boolean_t verbose
, dryrun
, parsable
, progress
;
805 snapfilter_cb_t
*filter_cb
;
808 char holdtag
[ZFS_MAXNAMELEN
];
814 estimate_ioctl(zfs_handle_t
*zhp
, uint64_t fromsnap_obj
,
815 boolean_t fromorigin
, uint64_t *sizep
)
817 zfs_cmd_t zc
= {"\0"};
818 libzfs_handle_t
*hdl
= zhp
->zfs_hdl
;
820 assert(zhp
->zfs_type
== ZFS_TYPE_SNAPSHOT
);
821 assert(fromsnap_obj
== 0 || !fromorigin
);
823 (void) strlcpy(zc
.zc_name
, zhp
->zfs_name
, sizeof (zc
.zc_name
));
824 zc
.zc_obj
= fromorigin
;
825 zc
.zc_sendobj
= zfs_prop_get_int(zhp
, ZFS_PROP_OBJSETID
);
826 zc
.zc_fromobj
= fromsnap_obj
;
827 zc
.zc_guid
= 1; /* estimate flag */
829 if (zfs_ioctl(zhp
->zfs_hdl
, ZFS_IOC_SEND
, &zc
) != 0) {
831 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
832 "warning: cannot estimate space for '%s'"), zhp
->zfs_name
);
836 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
837 "not an earlier snapshot from the same fs"));
838 return (zfs_error(hdl
, EZFS_CROSSTARGET
, errbuf
));
841 if (zfs_dataset_exists(hdl
, zc
.zc_name
,
842 ZFS_TYPE_SNAPSHOT
)) {
843 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
844 "incremental source (@%s) does not exist"),
847 return (zfs_error(hdl
, EZFS_NOENT
, errbuf
));
860 zfs_error_aux(hdl
, strerror(errno
));
861 return (zfs_error(hdl
, EZFS_BADBACKUP
, errbuf
));
864 return (zfs_standard_error(hdl
, errno
, errbuf
));
868 *sizep
= zc
.zc_objset_type
;
874 * Dumps a backup of the given snapshot (incremental from fromsnap if it's not
875 * NULL) to the file descriptor specified by outfd.
878 dump_ioctl(zfs_handle_t
*zhp
, const char *fromsnap
, uint64_t fromsnap_obj
,
879 boolean_t fromorigin
, int outfd
, nvlist_t
*debugnv
)
881 zfs_cmd_t zc
= {"\0"};
882 libzfs_handle_t
*hdl
= zhp
->zfs_hdl
;
885 assert(zhp
->zfs_type
== ZFS_TYPE_SNAPSHOT
);
886 assert(fromsnap_obj
== 0 || !fromorigin
);
888 (void) strlcpy(zc
.zc_name
, zhp
->zfs_name
, sizeof (zc
.zc_name
));
889 zc
.zc_cookie
= outfd
;
890 zc
.zc_obj
= fromorigin
;
891 zc
.zc_sendobj
= zfs_prop_get_int(zhp
, ZFS_PROP_OBJSETID
);
892 zc
.zc_fromobj
= fromsnap_obj
;
894 VERIFY(0 == nvlist_alloc(&thisdbg
, NV_UNIQUE_NAME
, 0));
895 if (fromsnap
&& fromsnap
[0] != '\0') {
896 VERIFY(0 == nvlist_add_string(thisdbg
,
897 "fromsnap", fromsnap
));
900 if (zfs_ioctl(zhp
->zfs_hdl
, ZFS_IOC_SEND
, &zc
) != 0) {
902 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
903 "warning: cannot send '%s'"), zhp
->zfs_name
);
905 VERIFY(0 == nvlist_add_uint64(thisdbg
, "error", errno
));
907 VERIFY(0 == nvlist_add_nvlist(debugnv
,
908 zhp
->zfs_name
, thisdbg
));
910 nvlist_free(thisdbg
);
914 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
915 "not an earlier snapshot from the same fs"));
916 return (zfs_error(hdl
, EZFS_CROSSTARGET
, errbuf
));
919 if (zfs_dataset_exists(hdl
, zc
.zc_name
,
920 ZFS_TYPE_SNAPSHOT
)) {
921 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
922 "incremental source (@%s) does not exist"),
925 return (zfs_error(hdl
, EZFS_NOENT
, errbuf
));
938 zfs_error_aux(hdl
, strerror(errno
));
939 return (zfs_error(hdl
, EZFS_BADBACKUP
, errbuf
));
942 return (zfs_standard_error(hdl
, errno
, errbuf
));
947 VERIFY(0 == nvlist_add_nvlist(debugnv
, zhp
->zfs_name
, thisdbg
));
948 nvlist_free(thisdbg
);
954 gather_holds(zfs_handle_t
*zhp
, send_dump_data_t
*sdd
)
956 assert(zhp
->zfs_type
== ZFS_TYPE_SNAPSHOT
);
959 * zfs_send() only sets snapholds for sends that need them,
960 * e.g. replication and doall.
962 if (sdd
->snapholds
== NULL
)
965 fnvlist_add_string(sdd
->snapholds
, zhp
->zfs_name
, sdd
->holdtag
);
969 send_progress_thread(void *arg
)
971 progress_arg_t
*pa
= arg
;
973 zfs_cmd_t zc
= {"\0"};
974 zfs_handle_t
*zhp
= pa
->pa_zhp
;
975 libzfs_handle_t
*hdl
= zhp
->zfs_hdl
;
976 unsigned long long bytes
;
982 assert(zhp
->zfs_type
== ZFS_TYPE_SNAPSHOT
);
983 (void) strlcpy(zc
.zc_name
, zhp
->zfs_name
, sizeof (zc
.zc_name
));
985 if (!pa
->pa_parsable
)
986 (void) fprintf(stderr
, "TIME SENT SNAPSHOT\n");
989 * Print the progress from ZFS_IOC_SEND_PROGRESS every second.
994 zc
.zc_cookie
= pa
->pa_fd
;
995 if (zfs_ioctl(hdl
, ZFS_IOC_SEND_PROGRESS
, &zc
) != 0)
1000 bytes
= zc
.zc_cookie
;
1002 if (pa
->pa_parsable
) {
1003 (void) fprintf(stderr
, "%02d:%02d:%02d\t%llu\t%s\n",
1004 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
,
1005 bytes
, zhp
->zfs_name
);
1007 zfs_nicenum(bytes
, buf
, sizeof (buf
));
1008 (void) fprintf(stderr
, "%02d:%02d:%02d %5s %s\n",
1009 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
,
1010 buf
, zhp
->zfs_name
);
1016 dump_snapshot(zfs_handle_t
*zhp
, void *arg
)
1018 send_dump_data_t
*sdd
= arg
;
1019 progress_arg_t pa
= { 0 };
1023 boolean_t isfromsnap
, istosnap
, fromorigin
;
1024 boolean_t exclude
= B_FALSE
;
1027 thissnap
= strchr(zhp
->zfs_name
, '@') + 1;
1028 isfromsnap
= (sdd
->fromsnap
!= NULL
&&
1029 strcmp(sdd
->fromsnap
, thissnap
) == 0);
1031 if (!sdd
->seenfrom
&& isfromsnap
) {
1032 gather_holds(zhp
, sdd
);
1033 sdd
->seenfrom
= B_TRUE
;
1034 (void) strcpy(sdd
->prevsnap
, thissnap
);
1035 sdd
->prevsnap_obj
= zfs_prop_get_int(zhp
, ZFS_PROP_OBJSETID
);
1040 if (sdd
->seento
|| !sdd
->seenfrom
) {
1045 istosnap
= (strcmp(sdd
->tosnap
, thissnap
) == 0);
1047 sdd
->seento
= B_TRUE
;
1049 if (!sdd
->doall
&& !isfromsnap
&& !istosnap
) {
1050 if (sdd
->replicate
) {
1052 nvlist_t
*snapprops
;
1054 * Filter out all intermediate snapshots except origin
1055 * snapshots needed to replicate clones.
1057 nvlist_t
*nvfs
= fsavl_find(sdd
->fsavl
,
1058 zhp
->zfs_dmustats
.dds_guid
, &snapname
);
1060 VERIFY(0 == nvlist_lookup_nvlist(nvfs
,
1061 "snapprops", &snapprops
));
1062 VERIFY(0 == nvlist_lookup_nvlist(snapprops
,
1063 thissnap
, &snapprops
));
1064 exclude
= !nvlist_exists(snapprops
, "is_clone_origin");
1071 * If a filter function exists, call it to determine whether
1072 * this snapshot will be sent.
1074 if (exclude
|| (sdd
->filter_cb
!= NULL
&&
1075 sdd
->filter_cb(zhp
, sdd
->filter_cb_arg
) == B_FALSE
)) {
1077 * This snapshot is filtered out. Don't send it, and don't
1078 * set prevsnap_obj, so it will be as if this snapshot didn't
1079 * exist, and the next accepted snapshot will be sent as
1080 * an incremental from the last accepted one, or as the
1081 * first (and full) snapshot in the case of a replication,
1082 * non-incremental send.
1088 gather_holds(zhp
, sdd
);
1089 fromorigin
= sdd
->prevsnap
[0] == '\0' &&
1090 (sdd
->fromorigin
|| sdd
->replicate
);
1094 err
= estimate_ioctl(zhp
, sdd
->prevsnap_obj
,
1097 if (sdd
->parsable
) {
1098 if (sdd
->prevsnap
[0] != '\0') {
1099 (void) fprintf(stderr
, "incremental\t%s\t%s",
1100 sdd
->prevsnap
, zhp
->zfs_name
);
1102 (void) fprintf(stderr
, "full\t%s",
1106 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1107 "send from @%s to %s"),
1108 sdd
->prevsnap
, zhp
->zfs_name
);
1111 if (sdd
->parsable
) {
1112 (void) fprintf(stderr
, "\t%llu\n",
1116 zfs_nicenum(size
, buf
, sizeof (buf
));
1117 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1118 " estimated size is %s\n"), buf
);
1122 (void) fprintf(stderr
, "\n");
1128 * If progress reporting is requested, spawn a new thread to
1129 * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
1131 if (sdd
->progress
) {
1133 pa
.pa_fd
= sdd
->outfd
;
1134 pa
.pa_parsable
= sdd
->parsable
;
1136 if ((err
= pthread_create(&tid
, NULL
,
1137 send_progress_thread
, &pa
))) {
1143 err
= dump_ioctl(zhp
, sdd
->prevsnap
, sdd
->prevsnap_obj
,
1144 fromorigin
, sdd
->outfd
, sdd
->debugnv
);
1146 if (sdd
->progress
) {
1147 (void) pthread_cancel(tid
);
1148 (void) pthread_join(tid
, NULL
);
1152 (void) strcpy(sdd
->prevsnap
, thissnap
);
1153 sdd
->prevsnap_obj
= zfs_prop_get_int(zhp
, ZFS_PROP_OBJSETID
);
1159 dump_filesystem(zfs_handle_t
*zhp
, void *arg
)
1162 send_dump_data_t
*sdd
= arg
;
1163 boolean_t missingfrom
= B_FALSE
;
1164 zfs_cmd_t zc
= {"\0"};
1166 (void) snprintf(zc
.zc_name
, sizeof (zc
.zc_name
), "%s@%s",
1167 zhp
->zfs_name
, sdd
->tosnap
);
1168 if (ioctl(zhp
->zfs_hdl
->libzfs_fd
, ZFS_IOC_OBJSET_STATS
, &zc
) != 0) {
1169 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1170 "WARNING: could not send %s@%s: does not exist\n"),
1171 zhp
->zfs_name
, sdd
->tosnap
);
1176 if (sdd
->replicate
&& sdd
->fromsnap
) {
1178 * If this fs does not have fromsnap, and we're doing
1179 * recursive, we need to send a full stream from the
1180 * beginning (or an incremental from the origin if this
1181 * is a clone). If we're doing non-recursive, then let
1182 * them get the error.
1184 (void) snprintf(zc
.zc_name
, sizeof (zc
.zc_name
), "%s@%s",
1185 zhp
->zfs_name
, sdd
->fromsnap
);
1186 if (ioctl(zhp
->zfs_hdl
->libzfs_fd
,
1187 ZFS_IOC_OBJSET_STATS
, &zc
) != 0) {
1188 missingfrom
= B_TRUE
;
1192 sdd
->seenfrom
= sdd
->seento
= sdd
->prevsnap
[0] = 0;
1193 sdd
->prevsnap_obj
= 0;
1194 if (sdd
->fromsnap
== NULL
|| missingfrom
)
1195 sdd
->seenfrom
= B_TRUE
;
1197 rv
= zfs_iter_snapshots_sorted(zhp
, dump_snapshot
, arg
);
1198 if (!sdd
->seenfrom
) {
1199 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1200 "WARNING: could not send %s@%s:\n"
1201 "incremental source (%s@%s) does not exist\n"),
1202 zhp
->zfs_name
, sdd
->tosnap
,
1203 zhp
->zfs_name
, sdd
->fromsnap
);
1205 } else if (!sdd
->seento
) {
1206 if (sdd
->fromsnap
) {
1207 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1208 "WARNING: could not send %s@%s:\n"
1209 "incremental source (%s@%s) "
1210 "is not earlier than it\n"),
1211 zhp
->zfs_name
, sdd
->tosnap
,
1212 zhp
->zfs_name
, sdd
->fromsnap
);
1214 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1216 "could not send %s@%s: does not exist\n"),
1217 zhp
->zfs_name
, sdd
->tosnap
);
1226 dump_filesystems(zfs_handle_t
*rzhp
, void *arg
)
1228 send_dump_data_t
*sdd
= arg
;
1230 boolean_t needagain
, progress
;
1232 if (!sdd
->replicate
)
1233 return (dump_filesystem(rzhp
, sdd
));
1235 /* Mark the clone origin snapshots. */
1236 for (fspair
= nvlist_next_nvpair(sdd
->fss
, NULL
); fspair
;
1237 fspair
= nvlist_next_nvpair(sdd
->fss
, fspair
)) {
1239 uint64_t origin_guid
= 0;
1241 VERIFY(0 == nvpair_value_nvlist(fspair
, &nvfs
));
1242 (void) nvlist_lookup_uint64(nvfs
, "origin", &origin_guid
);
1243 if (origin_guid
!= 0) {
1245 nvlist_t
*origin_nv
= fsavl_find(sdd
->fsavl
,
1246 origin_guid
, &snapname
);
1247 if (origin_nv
!= NULL
) {
1248 nvlist_t
*snapprops
;
1249 VERIFY(0 == nvlist_lookup_nvlist(origin_nv
,
1250 "snapprops", &snapprops
));
1251 VERIFY(0 == nvlist_lookup_nvlist(snapprops
,
1252 snapname
, &snapprops
));
1253 VERIFY(0 == nvlist_add_boolean(
1254 snapprops
, "is_clone_origin"));
1259 needagain
= progress
= B_FALSE
;
1260 for (fspair
= nvlist_next_nvpair(sdd
->fss
, NULL
); fspair
;
1261 fspair
= nvlist_next_nvpair(sdd
->fss
, fspair
)) {
1262 nvlist_t
*fslist
, *parent_nv
;
1266 uint64_t origin_guid
= 0;
1267 uint64_t parent_guid
= 0;
1269 VERIFY(nvpair_value_nvlist(fspair
, &fslist
) == 0);
1270 if (nvlist_lookup_boolean(fslist
, "sent") == 0)
1273 VERIFY(nvlist_lookup_string(fslist
, "name", &fsname
) == 0);
1274 (void) nvlist_lookup_uint64(fslist
, "origin", &origin_guid
);
1275 (void) nvlist_lookup_uint64(fslist
, "parentfromsnap",
1278 if (parent_guid
!= 0) {
1279 parent_nv
= fsavl_find(sdd
->fsavl
, parent_guid
, NULL
);
1280 if (!nvlist_exists(parent_nv
, "sent")) {
1281 /* parent has not been sent; skip this one */
1287 if (origin_guid
!= 0) {
1288 nvlist_t
*origin_nv
= fsavl_find(sdd
->fsavl
,
1290 if (origin_nv
!= NULL
&&
1291 !nvlist_exists(origin_nv
, "sent")) {
1293 * origin has not been sent yet;
1301 zhp
= zfs_open(rzhp
->zfs_hdl
, fsname
, ZFS_TYPE_DATASET
);
1304 err
= dump_filesystem(zhp
, sdd
);
1305 VERIFY(nvlist_add_boolean(fslist
, "sent") == 0);
1316 /* clean out the sent flags in case we reuse this fss */
1317 for (fspair
= nvlist_next_nvpair(sdd
->fss
, NULL
); fspair
;
1318 fspair
= nvlist_next_nvpair(sdd
->fss
, fspair
)) {
1321 VERIFY(nvpair_value_nvlist(fspair
, &fslist
) == 0);
1322 (void) nvlist_remove_all(fslist
, "sent");
1329 * Generate a send stream for the dataset identified by the argument zhp.
1331 * The content of the send stream is the snapshot identified by
1332 * 'tosnap'. Incremental streams are requested in two ways:
1333 * - from the snapshot identified by "fromsnap" (if non-null) or
1334 * - from the origin of the dataset identified by zhp, which must
1335 * be a clone. In this case, "fromsnap" is null and "fromorigin"
1338 * The send stream is recursive (i.e. dumps a hierarchy of snapshots) and
1339 * uses a special header (with a hdrtype field of DMU_COMPOUNDSTREAM)
1340 * if "replicate" is set. If "doall" is set, dump all the intermediate
1341 * snapshots. The DMU_COMPOUNDSTREAM header is used in the "doall"
1342 * case too. If "props" is set, send properties.
1345 zfs_send(zfs_handle_t
*zhp
, const char *fromsnap
, const char *tosnap
,
1346 sendflags_t
*flags
, int outfd
, snapfilter_cb_t filter_func
,
1347 void *cb_arg
, nvlist_t
**debugnvp
)
1350 send_dump_data_t sdd
= { 0 };
1352 nvlist_t
*fss
= NULL
;
1353 avl_tree_t
*fsavl
= NULL
;
1354 static uint64_t holdseq
;
1358 dedup_arg_t dda
= { 0 };
1359 int featureflags
= 0;
1361 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
1362 "cannot send '%s'"), zhp
->zfs_name
);
1364 if (fromsnap
&& fromsnap
[0] == '\0') {
1365 zfs_error_aux(zhp
->zfs_hdl
, dgettext(TEXT_DOMAIN
,
1366 "zero-length incremental source"));
1367 return (zfs_error(zhp
->zfs_hdl
, EZFS_NOENT
, errbuf
));
1370 if (zhp
->zfs_type
== ZFS_TYPE_FILESYSTEM
) {
1372 version
= zfs_prop_get_int(zhp
, ZFS_PROP_VERSION
);
1373 if (version
>= ZPL_VERSION_SA
) {
1374 featureflags
|= DMU_BACKUP_FEATURE_SA_SPILL
;
1378 if (flags
->dedup
&& !flags
->dryrun
) {
1379 featureflags
|= (DMU_BACKUP_FEATURE_DEDUP
|
1380 DMU_BACKUP_FEATURE_DEDUPPROPS
);
1381 if ((err
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, pipefd
))) {
1382 zfs_error_aux(zhp
->zfs_hdl
, strerror(errno
));
1383 return (zfs_error(zhp
->zfs_hdl
, EZFS_PIPEFAILED
,
1386 dda
.outputfd
= outfd
;
1387 dda
.inputfd
= pipefd
[1];
1388 dda
.dedup_hdl
= zhp
->zfs_hdl
;
1389 if ((err
= pthread_create(&tid
, NULL
, cksummer
, &dda
))) {
1390 (void) close(pipefd
[0]);
1391 (void) close(pipefd
[1]);
1392 zfs_error_aux(zhp
->zfs_hdl
, strerror(errno
));
1393 return (zfs_error(zhp
->zfs_hdl
,
1394 EZFS_THREADCREATEFAILED
, errbuf
));
1398 if (flags
->replicate
|| flags
->doall
|| flags
->props
) {
1399 dmu_replay_record_t drr
= { 0 };
1400 char *packbuf
= NULL
;
1402 zio_cksum_t zc
= { { 0 } };
1404 if (flags
->replicate
|| flags
->props
) {
1407 VERIFY(0 == nvlist_alloc(&hdrnv
, NV_UNIQUE_NAME
, 0));
1409 VERIFY(0 == nvlist_add_string(hdrnv
,
1410 "fromsnap", fromsnap
));
1412 VERIFY(0 == nvlist_add_string(hdrnv
, "tosnap", tosnap
));
1413 if (!flags
->replicate
) {
1414 VERIFY(0 == nvlist_add_boolean(hdrnv
,
1418 err
= gather_nvlist(zhp
->zfs_hdl
, zhp
->zfs_name
,
1419 fromsnap
, tosnap
, flags
->replicate
, &fss
, &fsavl
);
1422 VERIFY(0 == nvlist_add_nvlist(hdrnv
, "fss", fss
));
1423 err
= nvlist_pack(hdrnv
, &packbuf
, &buflen
,
1433 if (!flags
->dryrun
) {
1434 /* write first begin record */
1435 drr
.drr_type
= DRR_BEGIN
;
1436 drr
.drr_u
.drr_begin
.drr_magic
= DMU_BACKUP_MAGIC
;
1437 DMU_SET_STREAM_HDRTYPE(drr
.drr_u
.drr_begin
.
1438 drr_versioninfo
, DMU_COMPOUNDSTREAM
);
1439 DMU_SET_FEATUREFLAGS(drr
.drr_u
.drr_begin
.
1440 drr_versioninfo
, featureflags
);
1441 (void) snprintf(drr
.drr_u
.drr_begin
.drr_toname
,
1442 sizeof (drr
.drr_u
.drr_begin
.drr_toname
),
1443 "%s@%s", zhp
->zfs_name
, tosnap
);
1444 drr
.drr_payloadlen
= buflen
;
1445 err
= cksum_and_write(&drr
, sizeof (drr
), &zc
, outfd
);
1447 /* write header nvlist */
1448 if (err
!= -1 && packbuf
!= NULL
) {
1449 err
= cksum_and_write(packbuf
, buflen
, &zc
,
1458 /* write end record */
1459 bzero(&drr
, sizeof (drr
));
1460 drr
.drr_type
= DRR_END
;
1461 drr
.drr_u
.drr_end
.drr_checksum
= zc
;
1462 err
= write(outfd
, &drr
, sizeof (drr
));
1472 /* dump each stream */
1473 sdd
.fromsnap
= fromsnap
;
1474 sdd
.tosnap
= tosnap
;
1476 sdd
.outfd
= pipefd
[0];
1479 sdd
.replicate
= flags
->replicate
;
1480 sdd
.doall
= flags
->doall
;
1481 sdd
.fromorigin
= flags
->fromorigin
;
1484 sdd
.verbose
= flags
->verbose
;
1485 sdd
.parsable
= flags
->parsable
;
1486 sdd
.progress
= flags
->progress
;
1487 sdd
.dryrun
= flags
->dryrun
;
1488 sdd
.filter_cb
= filter_func
;
1489 sdd
.filter_cb_arg
= cb_arg
;
1491 sdd
.debugnv
= *debugnvp
;
1494 * Some flags require that we place user holds on the datasets that are
1495 * being sent so they don't get destroyed during the send. We can skip
1496 * this step if the pool is imported read-only since the datasets cannot
1499 if (!flags
->dryrun
&& !zpool_get_prop_int(zfs_get_pool_handle(zhp
),
1500 ZPOOL_PROP_READONLY
, NULL
) &&
1501 zfs_spa_version(zhp
, &spa_version
) == 0 &&
1502 spa_version
>= SPA_VERSION_USERREFS
&&
1503 (flags
->doall
|| flags
->replicate
)) {
1505 (void) snprintf(sdd
.holdtag
, sizeof (sdd
.holdtag
),
1506 ".send-%d-%llu", getpid(), (u_longlong_t
)holdseq
);
1507 sdd
.cleanup_fd
= open(ZFS_DEV
, O_RDWR
);
1508 if (sdd
.cleanup_fd
< 0) {
1512 sdd
.snapholds
= fnvlist_alloc();
1514 sdd
.cleanup_fd
= -1;
1515 sdd
.snapholds
= NULL
;
1517 if (flags
->verbose
|| sdd
.snapholds
!= NULL
) {
1519 * Do a verbose no-op dry run to get all the verbose output
1520 * or to gather snapshot hold's before generating any data,
1521 * then do a non-verbose real run to generate the streams.
1523 sdd
.dryrun
= B_TRUE
;
1524 err
= dump_filesystems(zhp
, &sdd
);
1529 if (flags
->verbose
) {
1530 if (flags
->parsable
) {
1531 (void) fprintf(stderr
, "size\t%llu\n",
1532 (longlong_t
)sdd
.size
);
1535 zfs_nicenum(sdd
.size
, buf
, sizeof (buf
));
1536 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
1537 "total estimated size is %s\n"), buf
);
1541 /* Ensure no snaps found is treated as an error. */
1547 /* Skip the second run if dryrun was requested. */
1551 if (sdd
.snapholds
!= NULL
) {
1552 err
= zfs_hold_nvl(zhp
, sdd
.cleanup_fd
, sdd
.snapholds
);
1556 fnvlist_free(sdd
.snapholds
);
1557 sdd
.snapholds
= NULL
;
1560 sdd
.dryrun
= B_FALSE
;
1561 sdd
.verbose
= B_FALSE
;
1564 err
= dump_filesystems(zhp
, &sdd
);
1565 fsavl_destroy(fsavl
);
1568 /* Ensure no snaps found is treated as an error. */
1569 if (err
== 0 && !sdd
.seento
)
1574 (void) pthread_cancel(tid
);
1575 (void) close(pipefd
[0]);
1576 (void) pthread_join(tid
, NULL
);
1579 if (sdd
.cleanup_fd
!= -1) {
1580 VERIFY(0 == close(sdd
.cleanup_fd
));
1581 sdd
.cleanup_fd
= -1;
1584 if (!flags
->dryrun
&& (flags
->replicate
|| flags
->doall
||
1587 * write final end record. NB: want to do this even if
1588 * there was some error, because it might not be totally
1591 dmu_replay_record_t drr
= { 0 };
1592 drr
.drr_type
= DRR_END
;
1593 if (write(outfd
, &drr
, sizeof (drr
)) == -1) {
1594 return (zfs_standard_error(zhp
->zfs_hdl
,
1599 return (err
|| sdd
.err
);
1602 err
= zfs_standard_error(zhp
->zfs_hdl
, err
, errbuf
);
1604 fsavl_destroy(fsavl
);
1606 fnvlist_free(sdd
.snapholds
);
1608 if (sdd
.cleanup_fd
!= -1)
1609 VERIFY(0 == close(sdd
.cleanup_fd
));
1611 (void) pthread_cancel(tid
);
1612 (void) close(pipefd
[0]);
1613 (void) pthread_join(tid
, NULL
);
1619 * Routines specific to "zfs recv"
1623 recv_read(libzfs_handle_t
*hdl
, int fd
, void *buf
, int ilen
,
1624 boolean_t byteswap
, zio_cksum_t
*zc
)
1631 rv
= read(fd
, cp
, len
);
1636 if (rv
< 0 || len
!= 0) {
1637 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
1638 "failed to read from stream"));
1639 return (zfs_error(hdl
, EZFS_BADSTREAM
, dgettext(TEXT_DOMAIN
,
1640 "cannot receive")));
1645 fletcher_4_incremental_byteswap(buf
, ilen
, zc
);
1647 fletcher_4_incremental_native(buf
, ilen
, zc
);
1653 recv_read_nvlist(libzfs_handle_t
*hdl
, int fd
, int len
, nvlist_t
**nvp
,
1654 boolean_t byteswap
, zio_cksum_t
*zc
)
1659 buf
= zfs_alloc(hdl
, len
);
1663 err
= recv_read(hdl
, fd
, buf
, len
, byteswap
, zc
);
1669 err
= nvlist_unpack(buf
, len
, nvp
, 0);
1672 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "invalid "
1673 "stream (malformed nvlist)"));
1680 recv_rename(libzfs_handle_t
*hdl
, const char *name
, const char *tryname
,
1681 int baselen
, char *newname
, recvflags_t
*flags
)
1684 zfs_cmd_t zc
= {"\0"};
1686 prop_changelist_t
*clp
;
1689 zhp
= zfs_open(hdl
, name
, ZFS_TYPE_DATASET
);
1692 clp
= changelist_gather(zhp
, ZFS_PROP_NAME
, 0,
1693 flags
->force
? MS_FORCE
: 0);
1697 err
= changelist_prefix(clp
);
1701 zc
.zc_objset_type
= DMU_OST_ZFS
;
1702 (void) strlcpy(zc
.zc_name
, name
, sizeof (zc
.zc_name
));
1705 (void) strcpy(newname
, tryname
);
1707 (void) strlcpy(zc
.zc_value
, tryname
, sizeof (zc
.zc_value
));
1709 if (flags
->verbose
) {
1710 (void) printf("attempting rename %s to %s\n",
1711 zc
.zc_name
, zc
.zc_value
);
1713 err
= ioctl(hdl
->libzfs_fd
, ZFS_IOC_RENAME
, &zc
);
1715 changelist_rename(clp
, name
, tryname
);
1720 if (err
!= 0 && strncmp(name
+ baselen
, "recv-", 5) != 0) {
1723 (void) snprintf(newname
, ZFS_MAXNAMELEN
, "%.*srecv-%u-%u",
1724 baselen
, name
, getpid(), seq
);
1725 (void) strlcpy(zc
.zc_value
, newname
, sizeof (zc
.zc_value
));
1727 if (flags
->verbose
) {
1728 (void) printf("failed - trying rename %s to %s\n",
1729 zc
.zc_name
, zc
.zc_value
);
1731 err
= ioctl(hdl
->libzfs_fd
, ZFS_IOC_RENAME
, &zc
);
1733 changelist_rename(clp
, name
, newname
);
1734 if (err
&& flags
->verbose
) {
1735 (void) printf("failed (%u) - "
1736 "will try again on next pass\n", errno
);
1739 } else if (flags
->verbose
) {
1741 (void) printf("success\n");
1743 (void) printf("failed (%u)\n", errno
);
1746 (void) changelist_postfix(clp
);
1747 changelist_free(clp
);
1753 recv_destroy(libzfs_handle_t
*hdl
, const char *name
, int baselen
,
1754 char *newname
, recvflags_t
*flags
)
1756 zfs_cmd_t zc
= {"\0"};
1758 prop_changelist_t
*clp
;
1760 boolean_t defer
= B_FALSE
;
1763 zhp
= zfs_open(hdl
, name
, ZFS_TYPE_DATASET
);
1766 clp
= changelist_gather(zhp
, ZFS_PROP_NAME
, 0,
1767 flags
->force
? MS_FORCE
: 0);
1768 if (zfs_get_type(zhp
) == ZFS_TYPE_SNAPSHOT
&&
1769 zfs_spa_version(zhp
, &spa_version
) == 0 &&
1770 spa_version
>= SPA_VERSION_USERREFS
)
1775 err
= changelist_prefix(clp
);
1779 zc
.zc_objset_type
= DMU_OST_ZFS
;
1780 zc
.zc_defer_destroy
= defer
;
1781 (void) strlcpy(zc
.zc_name
, name
, sizeof (zc
.zc_name
));
1784 (void) printf("attempting destroy %s\n", zc
.zc_name
);
1785 err
= ioctl(hdl
->libzfs_fd
, ZFS_IOC_DESTROY
, &zc
);
1788 (void) printf("success\n");
1789 changelist_remove(clp
, zc
.zc_name
);
1792 (void) changelist_postfix(clp
);
1793 changelist_free(clp
);
1796 * Deferred destroy might destroy the snapshot or only mark it to be
1797 * destroyed later, and it returns success in either case.
1799 if (err
!= 0 || (defer
&& zfs_dataset_exists(hdl
, name
,
1800 ZFS_TYPE_SNAPSHOT
))) {
1801 err
= recv_rename(hdl
, name
, NULL
, baselen
, newname
, flags
);
1807 typedef struct guid_to_name_data
{
1811 } guid_to_name_data_t
;
1814 guid_to_name_cb(zfs_handle_t
*zhp
, void *arg
)
1816 guid_to_name_data_t
*gtnd
= arg
;
1819 if (gtnd
->skip
!= NULL
&&
1820 strcmp(zhp
->zfs_name
, gtnd
->skip
) == 0) {
1824 if (zhp
->zfs_dmustats
.dds_guid
== gtnd
->guid
) {
1825 (void) strcpy(gtnd
->name
, zhp
->zfs_name
);
1830 err
= zfs_iter_children(zhp
, guid_to_name_cb
, gtnd
);
1836 * Attempt to find the local dataset associated with this guid. In the case of
1837 * multiple matches, we attempt to find the "best" match by searching
1838 * progressively larger portions of the hierarchy. This allows one to send a
1839 * tree of datasets individually and guarantee that we will find the source
1840 * guid within that hierarchy, even if there are multiple matches elsewhere.
1843 guid_to_name(libzfs_handle_t
*hdl
, const char *parent
, uint64_t guid
,
1846 /* exhaustive search all local snapshots */
1847 char pname
[ZFS_MAXNAMELEN
];
1848 guid_to_name_data_t gtnd
;
1857 (void) strlcpy(pname
, parent
, sizeof (pname
));
1860 * Search progressively larger portions of the hierarchy. This will
1861 * select the "most local" version of the origin snapshot in the case
1862 * that there are multiple matching snapshots in the system.
1864 while ((cp
= strrchr(pname
, '/')) != NULL
) {
1866 /* Chop off the last component and open the parent */
1868 zhp
= make_dataset_handle(hdl
, pname
);
1873 err
= zfs_iter_children(zhp
, guid_to_name_cb
, >nd
);
1879 * Remember the dataset that we already searched, so we
1880 * skip it next time through.
1889 * Return +1 if guid1 is before guid2, 0 if they are the same, and -1 if
1890 * guid1 is after guid2.
1893 created_before(libzfs_handle_t
*hdl
, avl_tree_t
*avl
,
1894 uint64_t guid1
, uint64_t guid2
)
1897 char *fsname
, *snapname
;
1898 char buf
[ZFS_MAXNAMELEN
];
1900 zfs_handle_t
*guid1hdl
, *guid2hdl
;
1901 uint64_t create1
, create2
;
1908 nvfs
= fsavl_find(avl
, guid1
, &snapname
);
1909 VERIFY(0 == nvlist_lookup_string(nvfs
, "name", &fsname
));
1910 (void) snprintf(buf
, sizeof (buf
), "%s@%s", fsname
, snapname
);
1911 guid1hdl
= zfs_open(hdl
, buf
, ZFS_TYPE_SNAPSHOT
);
1912 if (guid1hdl
== NULL
)
1915 nvfs
= fsavl_find(avl
, guid2
, &snapname
);
1916 VERIFY(0 == nvlist_lookup_string(nvfs
, "name", &fsname
));
1917 (void) snprintf(buf
, sizeof (buf
), "%s@%s", fsname
, snapname
);
1918 guid2hdl
= zfs_open(hdl
, buf
, ZFS_TYPE_SNAPSHOT
);
1919 if (guid2hdl
== NULL
) {
1920 zfs_close(guid1hdl
);
1924 create1
= zfs_prop_get_int(guid1hdl
, ZFS_PROP_CREATETXG
);
1925 create2
= zfs_prop_get_int(guid2hdl
, ZFS_PROP_CREATETXG
);
1927 if (create1
< create2
)
1929 else if (create1
> create2
)
1934 zfs_close(guid1hdl
);
1935 zfs_close(guid2hdl
);
1941 recv_incremental_replication(libzfs_handle_t
*hdl
, const char *tofs
,
1942 recvflags_t
*flags
, nvlist_t
*stream_nv
, avl_tree_t
*stream_avl
,
1946 avl_tree_t
*local_avl
;
1947 nvpair_t
*fselem
, *nextfselem
;
1949 char newname
[ZFS_MAXNAMELEN
];
1951 boolean_t needagain
, progress
, recursive
;
1954 VERIFY(0 == nvlist_lookup_string(stream_nv
, "fromsnap", &fromsnap
));
1956 recursive
= (nvlist_lookup_boolean(stream_nv
, "not_recursive") ==
1963 needagain
= progress
= B_FALSE
;
1965 if ((error
= gather_nvlist(hdl
, tofs
, fromsnap
, NULL
,
1966 recursive
, &local_nv
, &local_avl
)) != 0)
1970 * Process deletes and renames
1972 for (fselem
= nvlist_next_nvpair(local_nv
, NULL
);
1973 fselem
; fselem
= nextfselem
) {
1974 nvlist_t
*nvfs
, *snaps
;
1975 nvlist_t
*stream_nvfs
= NULL
;
1976 nvpair_t
*snapelem
, *nextsnapelem
;
1977 uint64_t fromguid
= 0;
1978 uint64_t originguid
= 0;
1979 uint64_t stream_originguid
= 0;
1980 uint64_t parent_fromsnap_guid
, stream_parent_fromsnap_guid
;
1981 char *fsname
, *stream_fsname
;
1983 nextfselem
= nvlist_next_nvpair(local_nv
, fselem
);
1985 VERIFY(0 == nvpair_value_nvlist(fselem
, &nvfs
));
1986 VERIFY(0 == nvlist_lookup_nvlist(nvfs
, "snaps", &snaps
));
1987 VERIFY(0 == nvlist_lookup_string(nvfs
, "name", &fsname
));
1988 VERIFY(0 == nvlist_lookup_uint64(nvfs
, "parentfromsnap",
1989 &parent_fromsnap_guid
));
1990 (void) nvlist_lookup_uint64(nvfs
, "origin", &originguid
);
1993 * First find the stream's fs, so we can check for
1994 * a different origin (due to "zfs promote")
1996 for (snapelem
= nvlist_next_nvpair(snaps
, NULL
);
1997 snapelem
; snapelem
= nvlist_next_nvpair(snaps
, snapelem
)) {
2000 VERIFY(0 == nvpair_value_uint64(snapelem
, &thisguid
));
2001 stream_nvfs
= fsavl_find(stream_avl
, thisguid
, NULL
);
2003 if (stream_nvfs
!= NULL
)
2007 /* check for promote */
2008 (void) nvlist_lookup_uint64(stream_nvfs
, "origin",
2009 &stream_originguid
);
2010 if (stream_nvfs
&& originguid
!= stream_originguid
) {
2011 switch (created_before(hdl
, local_avl
,
2012 stream_originguid
, originguid
)) {
2015 zfs_cmd_t zc
= {"\0"};
2016 nvlist_t
*origin_nvfs
;
2017 char *origin_fsname
;
2020 (void) printf("promoting %s\n", fsname
);
2022 origin_nvfs
= fsavl_find(local_avl
, originguid
,
2024 VERIFY(0 == nvlist_lookup_string(origin_nvfs
,
2025 "name", &origin_fsname
));
2026 (void) strlcpy(zc
.zc_value
, origin_fsname
,
2027 sizeof (zc
.zc_value
));
2028 (void) strlcpy(zc
.zc_name
, fsname
,
2029 sizeof (zc
.zc_name
));
2030 error
= zfs_ioctl(hdl
, ZFS_IOC_PROMOTE
, &zc
);
2038 fsavl_destroy(local_avl
);
2039 nvlist_free(local_nv
);
2043 * We had/have the wrong origin, therefore our
2044 * list of snapshots is wrong. Need to handle
2045 * them on the next pass.
2051 for (snapelem
= nvlist_next_nvpair(snaps
, NULL
);
2052 snapelem
; snapelem
= nextsnapelem
) {
2054 char *stream_snapname
;
2055 nvlist_t
*found
, *props
;
2057 nextsnapelem
= nvlist_next_nvpair(snaps
, snapelem
);
2059 VERIFY(0 == nvpair_value_uint64(snapelem
, &thisguid
));
2060 found
= fsavl_find(stream_avl
, thisguid
,
2063 /* check for delete */
2064 if (found
== NULL
) {
2065 char name
[ZFS_MAXNAMELEN
];
2070 (void) snprintf(name
, sizeof (name
), "%s@%s",
2071 fsname
, nvpair_name(snapelem
));
2073 error
= recv_destroy(hdl
, name
,
2074 strlen(fsname
)+1, newname
, flags
);
2082 stream_nvfs
= found
;
2084 if (0 == nvlist_lookup_nvlist(stream_nvfs
, "snapprops",
2085 &props
) && 0 == nvlist_lookup_nvlist(props
,
2086 stream_snapname
, &props
)) {
2087 zfs_cmd_t zc
= {"\0"};
2089 zc
.zc_cookie
= B_TRUE
; /* received */
2090 (void) snprintf(zc
.zc_name
, sizeof (zc
.zc_name
),
2091 "%s@%s", fsname
, nvpair_name(snapelem
));
2092 if (zcmd_write_src_nvlist(hdl
, &zc
,
2094 (void) zfs_ioctl(hdl
,
2095 ZFS_IOC_SET_PROP
, &zc
);
2096 zcmd_free_nvlists(&zc
);
2100 /* check for different snapname */
2101 if (strcmp(nvpair_name(snapelem
),
2102 stream_snapname
) != 0) {
2103 char name
[ZFS_MAXNAMELEN
];
2104 char tryname
[ZFS_MAXNAMELEN
];
2106 (void) snprintf(name
, sizeof (name
), "%s@%s",
2107 fsname
, nvpair_name(snapelem
));
2108 (void) snprintf(tryname
, sizeof (name
), "%s@%s",
2109 fsname
, stream_snapname
);
2111 error
= recv_rename(hdl
, name
, tryname
,
2112 strlen(fsname
)+1, newname
, flags
);
2119 if (strcmp(stream_snapname
, fromsnap
) == 0)
2120 fromguid
= thisguid
;
2123 /* check for delete */
2124 if (stream_nvfs
== NULL
) {
2128 error
= recv_destroy(hdl
, fsname
, strlen(tofs
)+1,
2137 if (fromguid
== 0) {
2138 if (flags
->verbose
) {
2139 (void) printf("local fs %s does not have "
2140 "fromsnap (%s in stream); must have "
2141 "been deleted locally; ignoring\n",
2147 VERIFY(0 == nvlist_lookup_string(stream_nvfs
,
2148 "name", &stream_fsname
));
2149 VERIFY(0 == nvlist_lookup_uint64(stream_nvfs
,
2150 "parentfromsnap", &stream_parent_fromsnap_guid
));
2152 s1
= strrchr(fsname
, '/');
2153 s2
= strrchr(stream_fsname
, '/');
2156 * Check for rename. If the exact receive path is specified, it
2157 * does not count as a rename, but we still need to check the
2158 * datasets beneath it.
2160 if ((stream_parent_fromsnap_guid
!= 0 &&
2161 parent_fromsnap_guid
!= 0 &&
2162 stream_parent_fromsnap_guid
!= parent_fromsnap_guid
) ||
2163 ((flags
->isprefix
|| strcmp(tofs
, fsname
) != 0) &&
2164 (s1
!= NULL
) && (s2
!= NULL
) && strcmp(s1
, s2
) != 0)) {
2166 char tryname
[ZFS_MAXNAMELEN
];
2168 parent
= fsavl_find(local_avl
,
2169 stream_parent_fromsnap_guid
, NULL
);
2171 * NB: parent might not be found if we used the
2172 * tosnap for stream_parent_fromsnap_guid,
2173 * because the parent is a newly-created fs;
2174 * we'll be able to rename it after we recv the
2177 if (parent
!= NULL
) {
2180 VERIFY(0 == nvlist_lookup_string(parent
, "name",
2182 (void) snprintf(tryname
, sizeof (tryname
),
2183 "%s%s", pname
, strrchr(stream_fsname
, '/'));
2186 if (flags
->verbose
) {
2187 (void) printf("local fs %s new parent "
2188 "not found\n", fsname
);
2194 error
= recv_rename(hdl
, fsname
, tryname
,
2195 strlen(tofs
)+1, newname
, flags
);
2197 if (renamed
!= NULL
&& newname
[0] != '\0') {
2198 VERIFY(0 == nvlist_add_boolean(renamed
,
2209 fsavl_destroy(local_avl
);
2210 nvlist_free(local_nv
);
2212 if (needagain
&& progress
) {
2213 /* do another pass to fix up temporary names */
2215 (void) printf("another pass:\n");
2223 zfs_receive_package(libzfs_handle_t
*hdl
, int fd
, const char *destname
,
2224 recvflags_t
*flags
, dmu_replay_record_t
*drr
, zio_cksum_t
*zc
,
2225 char **top_zfs
, int cleanup_fd
, uint64_t *action_handlep
)
2227 nvlist_t
*stream_nv
= NULL
;
2228 avl_tree_t
*stream_avl
= NULL
;
2229 char *fromsnap
= NULL
;
2231 char tofs
[ZFS_MAXNAMELEN
];
2232 char sendfs
[ZFS_MAXNAMELEN
];
2234 dmu_replay_record_t drre
;
2236 boolean_t anyerr
= B_FALSE
;
2237 boolean_t softerr
= B_FALSE
;
2238 boolean_t recursive
;
2240 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
2243 assert(drr
->drr_type
== DRR_BEGIN
);
2244 assert(drr
->drr_u
.drr_begin
.drr_magic
== DMU_BACKUP_MAGIC
);
2245 assert(DMU_GET_STREAM_HDRTYPE(drr
->drr_u
.drr_begin
.drr_versioninfo
) ==
2246 DMU_COMPOUNDSTREAM
);
2249 * Read in the nvlist from the stream.
2251 if (drr
->drr_payloadlen
!= 0) {
2252 error
= recv_read_nvlist(hdl
, fd
, drr
->drr_payloadlen
,
2253 &stream_nv
, flags
->byteswap
, zc
);
2255 error
= zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
);
2260 recursive
= (nvlist_lookup_boolean(stream_nv
, "not_recursive") ==
2263 if (recursive
&& strchr(destname
, '@')) {
2264 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2265 "cannot specify snapshot name for multi-snapshot stream"));
2266 error
= zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
);
2271 * Read in the end record and verify checksum.
2273 if (0 != (error
= recv_read(hdl
, fd
, &drre
, sizeof (drre
),
2274 flags
->byteswap
, NULL
)))
2276 if (flags
->byteswap
) {
2277 drre
.drr_type
= BSWAP_32(drre
.drr_type
);
2278 drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[0] =
2279 BSWAP_64(drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[0]);
2280 drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[1] =
2281 BSWAP_64(drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[1]);
2282 drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[2] =
2283 BSWAP_64(drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[2]);
2284 drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[3] =
2285 BSWAP_64(drre
.drr_u
.drr_end
.drr_checksum
.zc_word
[3]);
2287 if (drre
.drr_type
!= DRR_END
) {
2288 error
= zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
);
2291 if (!ZIO_CHECKSUM_EQUAL(drre
.drr_u
.drr_end
.drr_checksum
, *zc
)) {
2292 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2293 "incorrect header checksum"));
2294 error
= zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
);
2298 (void) nvlist_lookup_string(stream_nv
, "fromsnap", &fromsnap
);
2300 if (drr
->drr_payloadlen
!= 0) {
2301 nvlist_t
*stream_fss
;
2303 VERIFY(0 == nvlist_lookup_nvlist(stream_nv
, "fss",
2305 if ((stream_avl
= fsavl_create(stream_fss
)) == NULL
) {
2306 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2307 "couldn't allocate avl tree"));
2308 error
= zfs_error(hdl
, EZFS_NOMEM
, errbuf
);
2312 if (fromsnap
!= NULL
) {
2313 nvlist_t
*renamed
= NULL
;
2314 nvpair_t
*pair
= NULL
;
2316 (void) strlcpy(tofs
, destname
, ZFS_MAXNAMELEN
);
2317 if (flags
->isprefix
) {
2318 struct drr_begin
*drrb
= &drr
->drr_u
.drr_begin
;
2321 if (flags
->istail
) {
2322 cp
= strrchr(drrb
->drr_toname
, '/');
2324 (void) strlcat(tofs
, "/",
2328 i
= (cp
- drrb
->drr_toname
);
2331 i
= strcspn(drrb
->drr_toname
, "/@");
2333 /* zfs_receive_one() will create_parents() */
2334 (void) strlcat(tofs
, &drrb
->drr_toname
[i
],
2336 *strchr(tofs
, '@') = '\0';
2339 if (recursive
&& !flags
->dryrun
&& !flags
->nomount
) {
2340 VERIFY(0 == nvlist_alloc(&renamed
,
2341 NV_UNIQUE_NAME
, 0));
2344 softerr
= recv_incremental_replication(hdl
, tofs
, flags
,
2345 stream_nv
, stream_avl
, renamed
);
2347 /* Unmount renamed filesystems before receiving. */
2348 while ((pair
= nvlist_next_nvpair(renamed
,
2351 prop_changelist_t
*clp
= NULL
;
2353 zhp
= zfs_open(hdl
, nvpair_name(pair
),
2354 ZFS_TYPE_FILESYSTEM
);
2356 clp
= changelist_gather(zhp
,
2357 ZFS_PROP_MOUNTPOINT
, 0, 0);
2361 changelist_prefix(clp
);
2362 changelist_free(clp
);
2367 nvlist_free(renamed
);
2372 * Get the fs specified by the first path in the stream (the top level
2373 * specified by 'zfs send') and pass it to each invocation of
2374 * zfs_receive_one().
2376 (void) strlcpy(sendfs
, drr
->drr_u
.drr_begin
.drr_toname
,
2378 if ((cp
= strchr(sendfs
, '@')) != NULL
)
2381 /* Finally, receive each contained stream */
2384 * we should figure out if it has a recoverable
2385 * error, in which case do a recv_skip() and drive on.
2386 * Note, if we fail due to already having this guid,
2387 * zfs_receive_one() will take care of it (ie,
2388 * recv_skip() and return 0).
2390 error
= zfs_receive_impl(hdl
, destname
, flags
, fd
,
2391 sendfs
, stream_nv
, stream_avl
, top_zfs
, cleanup_fd
,
2393 if (error
== ENODATA
) {
2398 } while (error
== 0);
2400 if (drr
->drr_payloadlen
!= 0 && fromsnap
!= NULL
) {
2402 * Now that we have the fs's they sent us, try the
2405 softerr
= recv_incremental_replication(hdl
, tofs
, flags
,
2406 stream_nv
, stream_avl
, NULL
);
2410 fsavl_destroy(stream_avl
);
2412 nvlist_free(stream_nv
);
2421 trunc_prop_errs(int truncated
)
2423 ASSERT(truncated
!= 0);
2426 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
2427 "1 more property could not be set\n"));
2429 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
2430 "%d more properties could not be set\n"), truncated
);
2434 recv_skip(libzfs_handle_t
*hdl
, int fd
, boolean_t byteswap
)
2436 dmu_replay_record_t
*drr
;
2437 void *buf
= malloc(1<<20);
2440 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
2441 "cannot receive:"));
2443 /* XXX would be great to use lseek if possible... */
2446 while (recv_read(hdl
, fd
, drr
, sizeof (dmu_replay_record_t
),
2447 byteswap
, NULL
) == 0) {
2449 drr
->drr_type
= BSWAP_32(drr
->drr_type
);
2451 switch (drr
->drr_type
) {
2453 /* NB: not to be used on v2 stream packages */
2454 if (drr
->drr_payloadlen
!= 0) {
2455 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2456 "invalid substream header"));
2457 return (zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
));
2467 drr
->drr_u
.drr_object
.drr_bonuslen
=
2468 BSWAP_32(drr
->drr_u
.drr_object
.
2471 (void) recv_read(hdl
, fd
, buf
,
2472 P2ROUNDUP(drr
->drr_u
.drr_object
.drr_bonuslen
, 8),
2478 drr
->drr_u
.drr_write
.drr_length
=
2479 BSWAP_64(drr
->drr_u
.drr_write
.drr_length
);
2481 (void) recv_read(hdl
, fd
, buf
,
2482 drr
->drr_u
.drr_write
.drr_length
, B_FALSE
, NULL
);
2486 drr
->drr_u
.drr_write
.drr_length
=
2487 BSWAP_64(drr
->drr_u
.drr_spill
.drr_length
);
2489 (void) recv_read(hdl
, fd
, buf
,
2490 drr
->drr_u
.drr_spill
.drr_length
, B_FALSE
, NULL
);
2492 case DRR_WRITE_BYREF
:
2493 case DRR_FREEOBJECTS
:
2498 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2499 "invalid record type"));
2500 return (zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
));
2509 * Restores a backup of tosnap from the file descriptor specified by infd.
2512 zfs_receive_one(libzfs_handle_t
*hdl
, int infd
, const char *tosnap
,
2513 recvflags_t
*flags
, dmu_replay_record_t
*drr
,
2514 dmu_replay_record_t
*drr_noswap
, const char *sendfs
,
2515 nvlist_t
*stream_nv
, avl_tree_t
*stream_avl
, char **top_zfs
, int cleanup_fd
,
2516 uint64_t *action_handlep
)
2518 zfs_cmd_t zc
= {"\0"};
2520 int ioctl_err
, ioctl_errno
, err
;
2522 struct drr_begin
*drrb
= &drr
->drr_u
.drr_begin
;
2524 char prop_errbuf
[1024];
2525 const char *chopprefix
;
2526 boolean_t newfs
= B_FALSE
;
2527 boolean_t stream_wantsnewfs
;
2528 uint64_t parent_snapguid
= 0;
2529 prop_changelist_t
*clp
= NULL
;
2530 nvlist_t
*snapprops_nvlist
= NULL
;
2531 zprop_errflags_t prop_errflags
;
2532 boolean_t recursive
;
2534 begin_time
= time(NULL
);
2536 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
2539 recursive
= (nvlist_lookup_boolean(stream_nv
, "not_recursive") ==
2542 if (stream_avl
!= NULL
) {
2544 nvlist_t
*fs
= fsavl_find(stream_avl
, drrb
->drr_toguid
,
2549 (void) nvlist_lookup_uint64(fs
, "parentfromsnap",
2551 err
= nvlist_lookup_nvlist(fs
, "props", &props
);
2553 VERIFY(0 == nvlist_alloc(&props
, NV_UNIQUE_NAME
, 0));
2555 if (flags
->canmountoff
) {
2556 VERIFY(0 == nvlist_add_uint64(props
,
2557 zfs_prop_to_name(ZFS_PROP_CANMOUNT
), 0));
2559 ret
= zcmd_write_src_nvlist(hdl
, &zc
, props
);
2563 if (0 == nvlist_lookup_nvlist(fs
, "snapprops", &props
)) {
2564 VERIFY(0 == nvlist_lookup_nvlist(props
,
2565 snapname
, &snapprops_nvlist
));
2575 * Determine how much of the snapshot name stored in the stream
2576 * we are going to tack on to the name they specified on the
2577 * command line, and how much we are going to chop off.
2579 * If they specified a snapshot, chop the entire name stored in
2582 if (flags
->istail
) {
2584 * A filesystem was specified with -e. We want to tack on only
2585 * the tail of the sent snapshot path.
2587 if (strchr(tosnap
, '@')) {
2588 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "invalid "
2589 "argument - snapshot not allowed with -e"));
2590 return (zfs_error(hdl
, EZFS_INVALIDNAME
, errbuf
));
2593 chopprefix
= strrchr(sendfs
, '/');
2595 if (chopprefix
== NULL
) {
2597 * The tail is the poolname, so we need to
2598 * prepend a path separator.
2600 int len
= strlen(drrb
->drr_toname
);
2601 cp
= malloc(len
+ 2);
2603 (void) strcpy(&cp
[1], drrb
->drr_toname
);
2606 chopprefix
= drrb
->drr_toname
+ (chopprefix
- sendfs
);
2608 } else if (flags
->isprefix
) {
2610 * A filesystem was specified with -d. We want to tack on
2611 * everything but the first element of the sent snapshot path
2612 * (all but the pool name).
2614 if (strchr(tosnap
, '@')) {
2615 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "invalid "
2616 "argument - snapshot not allowed with -d"));
2617 return (zfs_error(hdl
, EZFS_INVALIDNAME
, errbuf
));
2620 chopprefix
= strchr(drrb
->drr_toname
, '/');
2621 if (chopprefix
== NULL
)
2622 chopprefix
= strchr(drrb
->drr_toname
, '@');
2623 } else if (strchr(tosnap
, '@') == NULL
) {
2625 * If a filesystem was specified without -d or -e, we want to
2626 * tack on everything after the fs specified by 'zfs send'.
2628 chopprefix
= drrb
->drr_toname
+ strlen(sendfs
);
2630 /* A snapshot was specified as an exact path (no -d or -e). */
2632 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2633 "cannot specify snapshot name for multi-snapshot "
2635 return (zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
));
2637 chopprefix
= drrb
->drr_toname
+ strlen(drrb
->drr_toname
);
2640 ASSERT(strstr(drrb
->drr_toname
, sendfs
) == drrb
->drr_toname
);
2641 ASSERT(chopprefix
> drrb
->drr_toname
);
2642 ASSERT(chopprefix
<= drrb
->drr_toname
+ strlen(drrb
->drr_toname
));
2643 ASSERT(chopprefix
[0] == '/' || chopprefix
[0] == '@' ||
2644 chopprefix
[0] == '\0');
2647 * Determine name of destination snapshot, store in zc_value.
2649 (void) strcpy(zc
.zc_value
, tosnap
);
2650 (void) strlcat(zc
.zc_value
, chopprefix
, sizeof (zc
.zc_value
));
2652 if (!zfs_name_valid(zc
.zc_value
, ZFS_TYPE_SNAPSHOT
)) {
2653 zcmd_free_nvlists(&zc
);
2654 return (zfs_error(hdl
, EZFS_INVALIDNAME
, errbuf
));
2658 * Determine the name of the origin snapshot, store in zc_string.
2660 if (drrb
->drr_flags
& DRR_FLAG_CLONE
) {
2661 if (guid_to_name(hdl
, zc
.zc_value
,
2662 drrb
->drr_fromguid
, zc
.zc_string
) != 0) {
2663 zcmd_free_nvlists(&zc
);
2664 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2665 "local origin for clone %s does not exist"),
2667 return (zfs_error(hdl
, EZFS_NOENT
, errbuf
));
2670 (void) printf("found clone origin %s\n", zc
.zc_string
);
2673 stream_wantsnewfs
= (drrb
->drr_fromguid
== 0 ||
2674 (drrb
->drr_flags
& DRR_FLAG_CLONE
));
2676 if (stream_wantsnewfs
) {
2678 * if the parent fs does not exist, look for it based on
2679 * the parent snap GUID
2681 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
2682 "cannot receive new filesystem stream"));
2684 (void) strcpy(zc
.zc_name
, zc
.zc_value
);
2685 cp
= strrchr(zc
.zc_name
, '/');
2689 !zfs_dataset_exists(hdl
, zc
.zc_name
, ZFS_TYPE_DATASET
)) {
2690 char suffix
[ZFS_MAXNAMELEN
];
2691 (void) strcpy(suffix
, strrchr(zc
.zc_value
, '/'));
2692 if (guid_to_name(hdl
, zc
.zc_name
, parent_snapguid
,
2693 zc
.zc_value
) == 0) {
2694 *strchr(zc
.zc_value
, '@') = '\0';
2695 (void) strcat(zc
.zc_value
, suffix
);
2700 * if the fs does not exist, look for it based on the
2703 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
2704 "cannot receive incremental stream"));
2706 (void) strcpy(zc
.zc_name
, zc
.zc_value
);
2707 *strchr(zc
.zc_name
, '@') = '\0';
2710 * If the exact receive path was specified and this is the
2711 * topmost path in the stream, then if the fs does not exist we
2712 * should look no further.
2714 if ((flags
->isprefix
|| (*(chopprefix
= drrb
->drr_toname
+
2715 strlen(sendfs
)) != '\0' && *chopprefix
!= '@')) &&
2716 !zfs_dataset_exists(hdl
, zc
.zc_name
, ZFS_TYPE_DATASET
)) {
2717 char snap
[ZFS_MAXNAMELEN
];
2718 (void) strcpy(snap
, strchr(zc
.zc_value
, '@'));
2719 if (guid_to_name(hdl
, zc
.zc_name
, drrb
->drr_fromguid
,
2720 zc
.zc_value
) == 0) {
2721 *strchr(zc
.zc_value
, '@') = '\0';
2722 (void) strcat(zc
.zc_value
, snap
);
2727 (void) strcpy(zc
.zc_name
, zc
.zc_value
);
2728 *strchr(zc
.zc_name
, '@') = '\0';
2730 if (zfs_dataset_exists(hdl
, zc
.zc_name
, ZFS_TYPE_DATASET
)) {
2734 * Destination fs exists. Therefore this should either
2735 * be an incremental, or the stream specifies a new fs
2736 * (full stream or clone) and they want us to blow it
2737 * away (and have therefore specified -F and removed any
2740 if (stream_wantsnewfs
) {
2741 if (!flags
->force
) {
2742 zcmd_free_nvlists(&zc
);
2743 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2744 "destination '%s' exists\n"
2745 "must specify -F to overwrite it"),
2747 return (zfs_error(hdl
, EZFS_EXISTS
, errbuf
));
2749 if (ioctl(hdl
->libzfs_fd
, ZFS_IOC_SNAPSHOT_LIST_NEXT
,
2751 zcmd_free_nvlists(&zc
);
2752 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2753 "destination has snapshots (eg. %s)\n"
2754 "must destroy them to overwrite it"),
2756 return (zfs_error(hdl
, EZFS_EXISTS
, errbuf
));
2760 if ((zhp
= zfs_open(hdl
, zc
.zc_name
,
2761 ZFS_TYPE_FILESYSTEM
| ZFS_TYPE_VOLUME
)) == NULL
) {
2762 zcmd_free_nvlists(&zc
);
2766 if (stream_wantsnewfs
&&
2767 zhp
->zfs_dmustats
.dds_origin
[0]) {
2768 zcmd_free_nvlists(&zc
);
2770 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2771 "destination '%s' is a clone\n"
2772 "must destroy it to overwrite it"),
2774 return (zfs_error(hdl
, EZFS_EXISTS
, errbuf
));
2777 if (!flags
->dryrun
&& zhp
->zfs_type
== ZFS_TYPE_FILESYSTEM
&&
2778 stream_wantsnewfs
) {
2779 /* We can't do online recv in this case */
2780 clp
= changelist_gather(zhp
, ZFS_PROP_NAME
, 0, 0);
2783 zcmd_free_nvlists(&zc
);
2786 if (changelist_prefix(clp
) != 0) {
2787 changelist_free(clp
);
2789 zcmd_free_nvlists(&zc
);
2793 if (!flags
->dryrun
&& zhp
->zfs_type
== ZFS_TYPE_VOLUME
&&
2794 zvol_remove_link(hdl
, zhp
->zfs_name
) != 0) {
2796 zcmd_free_nvlists(&zc
);
2802 * Destination filesystem does not exist. Therefore we better
2803 * be creating a new filesystem (either from a full backup, or
2804 * a clone). It would therefore be invalid if the user
2805 * specified only the pool name (i.e. if the destination name
2806 * contained no slash character).
2808 if (!stream_wantsnewfs
||
2809 (cp
= strrchr(zc
.zc_name
, '/')) == NULL
) {
2810 zcmd_free_nvlists(&zc
);
2811 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2812 "destination '%s' does not exist"), zc
.zc_name
);
2813 return (zfs_error(hdl
, EZFS_NOENT
, errbuf
));
2817 * Trim off the final dataset component so we perform the
2818 * recvbackup ioctl to the filesystems's parent.
2822 if (flags
->isprefix
&& !flags
->istail
&& !flags
->dryrun
&&
2823 create_parents(hdl
, zc
.zc_value
, strlen(tosnap
)) != 0) {
2824 zcmd_free_nvlists(&zc
);
2825 return (zfs_error(hdl
, EZFS_BADRESTORE
, errbuf
));
2831 zc
.zc_begin_record
= drr_noswap
->drr_u
.drr_begin
;
2832 zc
.zc_cookie
= infd
;
2833 zc
.zc_guid
= flags
->force
;
2834 if (flags
->verbose
) {
2835 (void) printf("%s %s stream of %s into %s\n",
2836 flags
->dryrun
? "would receive" : "receiving",
2837 drrb
->drr_fromguid
? "incremental" : "full",
2838 drrb
->drr_toname
, zc
.zc_value
);
2839 (void) fflush(stdout
);
2842 if (flags
->dryrun
) {
2843 zcmd_free_nvlists(&zc
);
2844 return (recv_skip(hdl
, infd
, flags
->byteswap
));
2847 zc
.zc_nvlist_dst
= (uint64_t)(uintptr_t)prop_errbuf
;
2848 zc
.zc_nvlist_dst_size
= sizeof (prop_errbuf
);
2849 zc
.zc_cleanup_fd
= cleanup_fd
;
2850 zc
.zc_action_handle
= *action_handlep
;
2852 err
= ioctl_err
= zfs_ioctl(hdl
, ZFS_IOC_RECV
, &zc
);
2853 ioctl_errno
= errno
;
2854 prop_errflags
= (zprop_errflags_t
)zc
.zc_obj
;
2857 nvlist_t
*prop_errors
;
2858 VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc
.zc_nvlist_dst
,
2859 zc
.zc_nvlist_dst_size
, &prop_errors
, 0));
2861 nvpair_t
*prop_err
= NULL
;
2863 while ((prop_err
= nvlist_next_nvpair(prop_errors
,
2864 prop_err
)) != NULL
) {
2869 prop
= zfs_name_to_prop(nvpair_name(prop_err
));
2870 (void) nvpair_value_int32(prop_err
, &intval
);
2871 if (strcmp(nvpair_name(prop_err
),
2872 ZPROP_N_MORE_ERRORS
) == 0) {
2873 trunc_prop_errs(intval
);
2876 (void) snprintf(tbuf
, sizeof (tbuf
),
2877 dgettext(TEXT_DOMAIN
,
2878 "cannot receive %s property on %s"),
2879 nvpair_name(prop_err
), zc
.zc_name
);
2880 zfs_setprop_error(hdl
, prop
, intval
, tbuf
);
2883 nvlist_free(prop_errors
);
2886 zc
.zc_nvlist_dst
= 0;
2887 zc
.zc_nvlist_dst_size
= 0;
2888 zcmd_free_nvlists(&zc
);
2890 if (err
== 0 && snapprops_nvlist
) {
2891 zfs_cmd_t zc2
= {"\0"};
2893 (void) strcpy(zc2
.zc_name
, zc
.zc_value
);
2894 zc2
.zc_cookie
= B_TRUE
; /* received */
2895 if (zcmd_write_src_nvlist(hdl
, &zc2
, snapprops_nvlist
) == 0) {
2896 (void) zfs_ioctl(hdl
, ZFS_IOC_SET_PROP
, &zc2
);
2897 zcmd_free_nvlists(&zc2
);
2901 if (err
&& (ioctl_errno
== ENOENT
|| ioctl_errno
== EEXIST
)) {
2903 * It may be that this snapshot already exists,
2904 * in which case we want to consume & ignore it
2905 * rather than failing.
2907 avl_tree_t
*local_avl
;
2908 nvlist_t
*local_nv
, *fs
;
2909 cp
= strchr(zc
.zc_value
, '@');
2912 * XXX Do this faster by just iterating over snaps in
2913 * this fs. Also if zc_value does not exist, we will
2914 * get a strange "does not exist" error message.
2917 if (gather_nvlist(hdl
, zc
.zc_value
, NULL
, NULL
, B_FALSE
,
2918 &local_nv
, &local_avl
) == 0) {
2920 fs
= fsavl_find(local_avl
, drrb
->drr_toguid
, NULL
);
2921 fsavl_destroy(local_avl
);
2922 nvlist_free(local_nv
);
2925 if (flags
->verbose
) {
2926 (void) printf("snap %s already exists; "
2927 "ignoring\n", zc
.zc_value
);
2929 err
= ioctl_err
= recv_skip(hdl
, infd
,
2936 if (ioctl_err
!= 0) {
2937 switch (ioctl_errno
) {
2939 cp
= strchr(zc
.zc_value
, '@');
2941 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2942 "most recent snapshot of %s does not\n"
2943 "match incremental source"), zc
.zc_value
);
2944 (void) zfs_error(hdl
, EZFS_BADRESTORE
, errbuf
);
2948 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2949 "destination %s has been modified\n"
2950 "since most recent snapshot"), zc
.zc_name
);
2951 (void) zfs_error(hdl
, EZFS_BADRESTORE
, errbuf
);
2954 cp
= strchr(zc
.zc_value
, '@');
2956 /* it's the containing fs that exists */
2959 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2960 "destination already exists"));
2961 (void) zfs_error_fmt(hdl
, EZFS_EXISTS
,
2962 dgettext(TEXT_DOMAIN
, "cannot restore to %s"),
2967 (void) zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
);
2970 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2971 "invalid stream (checksum mismatch)"));
2972 (void) zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
);
2975 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2976 "pool must be upgraded to receive this stream."));
2977 (void) zfs_error(hdl
, EZFS_BADVERSION
, errbuf
);
2980 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
2981 "destination %s space quota exceeded"), zc
.zc_name
);
2982 (void) zfs_error(hdl
, EZFS_NOSPC
, errbuf
);
2985 (void) zfs_standard_error(hdl
, ioctl_errno
, errbuf
);
2990 * Mount the target filesystem (if created). Also mount any
2991 * children of the target filesystem if we did a replication
2992 * receive (indicated by stream_avl being non-NULL).
2994 cp
= strchr(zc
.zc_value
, '@');
2995 if (cp
&& (ioctl_err
== 0 || !newfs
)) {
2999 h
= zfs_open(hdl
, zc
.zc_value
,
3000 ZFS_TYPE_FILESYSTEM
| ZFS_TYPE_VOLUME
);
3002 if (h
->zfs_type
== ZFS_TYPE_VOLUME
) {
3004 err
= zvol_create_link(hdl
, h
->zfs_name
);
3005 if (err
== 0 && ioctl_err
== 0)
3006 err
= zvol_create_link(hdl
,
3008 } else if (newfs
|| stream_avl
) {
3010 * Track the first/top of hierarchy fs,
3011 * for mounting and sharing later.
3013 if (top_zfs
&& *top_zfs
== NULL
)
3014 *top_zfs
= zfs_strdup(hdl
, zc
.zc_value
);
3022 err
|= changelist_postfix(clp
);
3023 changelist_free(clp
);
3026 if (prop_errflags
& ZPROP_ERR_NOCLEAR
) {
3027 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
, "Warning: "
3028 "failed to clear unreceived properties on %s"),
3030 (void) fprintf(stderr
, "\n");
3032 if (prop_errflags
& ZPROP_ERR_NORESTORE
) {
3033 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
, "Warning: "
3034 "failed to restore original properties on %s"),
3036 (void) fprintf(stderr
, "\n");
3039 if (err
|| ioctl_err
)
3042 *action_handlep
= zc
.zc_action_handle
;
3044 if (flags
->verbose
) {
3047 uint64_t bytes
= zc
.zc_cookie
;
3048 time_t delta
= time(NULL
) - begin_time
;
3051 zfs_nicenum(bytes
, buf1
, sizeof (buf1
));
3052 zfs_nicenum(bytes
/delta
, buf2
, sizeof (buf1
));
3054 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3062 zfs_receive_impl(libzfs_handle_t
*hdl
, const char *tosnap
, recvflags_t
*flags
,
3063 int infd
, const char *sendfs
, nvlist_t
*stream_nv
, avl_tree_t
*stream_avl
,
3064 char **top_zfs
, int cleanup_fd
, uint64_t *action_handlep
)
3067 dmu_replay_record_t drr
, drr_noswap
;
3068 struct drr_begin
*drrb
= &drr
.drr_u
.drr_begin
;
3070 zio_cksum_t zcksum
= { { 0 } };
3071 uint64_t featureflags
;
3074 (void) snprintf(errbuf
, sizeof (errbuf
), dgettext(TEXT_DOMAIN
,
3077 if (flags
->isprefix
&&
3078 !zfs_dataset_exists(hdl
, tosnap
, ZFS_TYPE_DATASET
)) {
3079 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "specified fs "
3080 "(%s) does not exist"), tosnap
);
3081 return (zfs_error(hdl
, EZFS_NOENT
, errbuf
));
3084 /* read in the BEGIN record */
3085 if (0 != (err
= recv_read(hdl
, infd
, &drr
, sizeof (drr
), B_FALSE
,
3089 if (drr
.drr_type
== DRR_END
|| drr
.drr_type
== BSWAP_32(DRR_END
)) {
3090 /* It's the double end record at the end of a package */
3094 /* the kernel needs the non-byteswapped begin record */
3097 flags
->byteswap
= B_FALSE
;
3098 if (drrb
->drr_magic
== BSWAP_64(DMU_BACKUP_MAGIC
)) {
3100 * We computed the checksum in the wrong byteorder in
3101 * recv_read() above; do it again correctly.
3103 bzero(&zcksum
, sizeof (zio_cksum_t
));
3104 fletcher_4_incremental_byteswap(&drr
, sizeof (drr
), &zcksum
);
3105 flags
->byteswap
= B_TRUE
;
3107 drr
.drr_type
= BSWAP_32(drr
.drr_type
);
3108 drr
.drr_payloadlen
= BSWAP_32(drr
.drr_payloadlen
);
3109 drrb
->drr_magic
= BSWAP_64(drrb
->drr_magic
);
3110 drrb
->drr_versioninfo
= BSWAP_64(drrb
->drr_versioninfo
);
3111 drrb
->drr_creation_time
= BSWAP_64(drrb
->drr_creation_time
);
3112 drrb
->drr_type
= BSWAP_32(drrb
->drr_type
);
3113 drrb
->drr_flags
= BSWAP_32(drrb
->drr_flags
);
3114 drrb
->drr_toguid
= BSWAP_64(drrb
->drr_toguid
);
3115 drrb
->drr_fromguid
= BSWAP_64(drrb
->drr_fromguid
);
3118 if (drrb
->drr_magic
!= DMU_BACKUP_MAGIC
|| drr
.drr_type
!= DRR_BEGIN
) {
3119 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "invalid "
3120 "stream (bad magic number)"));
3121 return (zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
));
3124 featureflags
= DMU_GET_FEATUREFLAGS(drrb
->drr_versioninfo
);
3125 hdrtype
= DMU_GET_STREAM_HDRTYPE(drrb
->drr_versioninfo
);
3127 if (!DMU_STREAM_SUPPORTED(featureflags
) ||
3128 (hdrtype
!= DMU_SUBSTREAM
&& hdrtype
!= DMU_COMPOUNDSTREAM
)) {
3129 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
3130 "stream has unsupported feature, feature flags = %lx"),
3132 return (zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
));
3135 if (strchr(drrb
->drr_toname
, '@') == NULL
) {
3136 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
, "invalid "
3137 "stream (bad snapshot name)"));
3138 return (zfs_error(hdl
, EZFS_BADSTREAM
, errbuf
));
3141 if (DMU_GET_STREAM_HDRTYPE(drrb
->drr_versioninfo
) == DMU_SUBSTREAM
) {
3142 char nonpackage_sendfs
[ZFS_MAXNAMELEN
];
3143 if (sendfs
== NULL
) {
3145 * We were not called from zfs_receive_package(). Get
3146 * the fs specified by 'zfs send'.
3149 (void) strlcpy(nonpackage_sendfs
,
3150 drr
.drr_u
.drr_begin
.drr_toname
, ZFS_MAXNAMELEN
);
3151 if ((cp
= strchr(nonpackage_sendfs
, '@')) != NULL
)
3153 sendfs
= nonpackage_sendfs
;
3155 return (zfs_receive_one(hdl
, infd
, tosnap
, flags
,
3156 &drr
, &drr_noswap
, sendfs
, stream_nv
, stream_avl
,
3157 top_zfs
, cleanup_fd
, action_handlep
));
3159 assert(DMU_GET_STREAM_HDRTYPE(drrb
->drr_versioninfo
) ==
3160 DMU_COMPOUNDSTREAM
);
3161 return (zfs_receive_package(hdl
, infd
, tosnap
, flags
,
3162 &drr
, &zcksum
, top_zfs
, cleanup_fd
, action_handlep
));
3167 * Restores a backup of tosnap from the file descriptor specified by infd.
3168 * Return 0 on total success, -2 if some things couldn't be
3169 * destroyed/renamed/promoted, -1 if some things couldn't be received.
3170 * (-1 will override -2).
3173 zfs_receive(libzfs_handle_t
*hdl
, const char *tosnap
, recvflags_t
*flags
,
3174 int infd
, avl_tree_t
*stream_avl
)
3176 char *top_zfs
= NULL
;
3179 uint64_t action_handle
= 0;
3181 cleanup_fd
= open(ZFS_DEV
, O_RDWR
);
3182 VERIFY(cleanup_fd
>= 0);
3184 err
= zfs_receive_impl(hdl
, tosnap
, flags
, infd
, NULL
, NULL
,
3185 stream_avl
, &top_zfs
, cleanup_fd
, &action_handle
);
3187 VERIFY(0 == close(cleanup_fd
));
3189 if (err
== 0 && !flags
->nomount
&& top_zfs
) {
3191 prop_changelist_t
*clp
;
3193 zhp
= zfs_open(hdl
, top_zfs
, ZFS_TYPE_FILESYSTEM
);
3195 clp
= changelist_gather(zhp
, ZFS_PROP_MOUNTPOINT
,
3196 CL_GATHER_MOUNT_ALWAYS
, 0);
3199 /* mount and share received datasets */
3200 err
= changelist_postfix(clp
);
3201 changelist_free(clp
);
3204 if (zhp
== NULL
|| clp
== NULL
|| err
)