7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
25 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Copyright (c) 2013 Steven Hartland. All rights reserved.
27 */
28
29 #include <assert.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <libintl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <strings.h>
36 #include <unistd.h>
37 #include <stddef.h>
38 #include <fcntl.h>
39 #include <sys/mount.h>
40 #include <pthread.h>
41 #include <umem.h>
42 #include <time.h>
43
44 #include <libzfs.h>
45 #include <libzfs_core.h>
46
47 #include "zfs_namecheck.h"
48 #include "zfs_prop.h"
49 #include "zfs_fletcher.h"
50 #include "libzfs_impl.h"
51 #include <zlib.h>
52 #include <sha2.h>
53 #include <sys/zio_checksum.h>
54 #include <sys/ddt.h>
55
56 /* in libzfs_dataset.c */
57 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
58
59 static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
60 recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
61 uint64_t *);
62 static int guid_to_name(libzfs_handle_t *, const char *,
63 uint64_t, boolean_t, char *);
64
65 static const zio_cksum_t zero_cksum = { 0 };
66
67 typedef struct dedup_arg {
68 int inputfd;
69 int outputfd;
70 libzfs_handle_t *dedup_hdl;
71 } dedup_arg_t;
72
73 typedef struct progress_arg {
74 zfs_handle_t *pa_zhp;
75 int pa_fd;
76 boolean_t pa_parsable;
77 } progress_arg_t;
78
79 typedef struct dataref {
80 uint64_t ref_guid;
81 uint64_t ref_object;
2544 nvlist_free(local_nv);
2545
2546 if (needagain && progress) {
2547 /* do another pass to fix up temporary names */
2548 if (flags->verbose)
2549 (void) printf("another pass:\n");
2550 goto again;
2551 }
2552
2553 return (needagain);
2554 }
2555
2556 static int
2557 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2558 recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2559 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2560 {
2561 nvlist_t *stream_nv = NULL;
2562 avl_tree_t *stream_avl = NULL;
2563 char *fromsnap = NULL;
2564 char *cp;
2565 char tofs[ZFS_MAXNAMELEN];
2566 char sendfs[ZFS_MAXNAMELEN];
2567 char errbuf[1024];
2568 dmu_replay_record_t drre;
2569 int error;
2570 boolean_t anyerr = B_FALSE;
2571 boolean_t softerr = B_FALSE;
2572 boolean_t recursive;
2573
2574 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2575 "cannot receive"));
2576
2577 assert(drr->drr_type == DRR_BEGIN);
2578 assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2579 assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2580 DMU_COMPOUNDSTREAM);
2581
2582 /*
2583 * Read in the nvlist from the stream.
2692 zfs_close(zhp);
2693 if (clp != NULL) {
2694 softerr |=
2695 changelist_prefix(clp);
2696 changelist_free(clp);
2697 }
2698 }
2699 }
2700
2701 nvlist_free(renamed);
2702 }
2703 }
2704
2705 /*
2706 * Get the fs specified by the first path in the stream (the top level
2707 * specified by 'zfs send') and pass it to each invocation of
2708 * zfs_receive_one().
2709 */
2710 (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2711 ZFS_MAXNAMELEN);
2712 if ((cp = strchr(sendfs, '@')) != NULL)
2713 *cp = '\0';
2714
2715 /* Finally, receive each contained stream */
2716 do {
2717 /*
2718 * we should figure out if it has a recoverable
2719 * error, in which case do a recv_skip() and drive on.
2720 * Note, if we fail due to already having this guid,
2721 * zfs_receive_one() will take care of it (ie,
2722 * recv_skip() and return 0).
2723 */
2724 error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
2725 sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2726 action_handlep);
2727 if (error == ENODATA) {
2728 error = 0;
2729 break;
2730 }
2731 anyerr |= error;
2732 } while (error == 0);
2733
2734 if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2735 /*
2736 * Now that we have the fs's they sent us, try the
2737 * renames again.
2738 */
2739 softerr = recv_incremental_replication(hdl, tofs, flags,
2740 stream_nv, stream_avl, NULL);
2741 }
2742
2743 out:
2744 fsavl_destroy(stream_avl);
2745 if (stream_nv)
2746 nvlist_free(stream_nv);
2872 if (error == 0) {
2873 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2874 "checksum mismatch or incomplete stream.\n"
2875 "Partially received snapshot is saved.\n"
2876 "A resuming stream can be generated on the sending "
2877 "system by running:\n"
2878 " zfs send -t %s"),
2879 token_buf);
2880 }
2881 zfs_close(zhp);
2882 }
2883
2884 /*
2885 * Restores a backup of tosnap from the file descriptor specified by infd.
2886 */
2887 static int
2888 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2889 const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
2890 dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
2891 avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2892 uint64_t *action_handlep)
2893 {
2894 zfs_cmd_t zc = { 0 };
2895 time_t begin_time;
2896 int ioctl_err, ioctl_errno, err;
2897 char *cp;
2898 struct drr_begin *drrb = &drr->drr_u.drr_begin;
2899 char errbuf[1024];
2900 char prop_errbuf[1024];
2901 const char *chopprefix;
2902 boolean_t newfs = B_FALSE;
2903 boolean_t stream_wantsnewfs;
2904 uint64_t parent_snapguid = 0;
2905 prop_changelist_t *clp = NULL;
2906 nvlist_t *snapprops_nvlist = NULL;
2907 zprop_errflags_t prop_errflags;
2908 boolean_t recursive;
2909
2910 begin_time = time(NULL);
2911
2912 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2913 "cannot receive"));
2914
2915 recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2916 ENOENT);
2917
2918 if (stream_avl != NULL) {
2919 char *snapname;
2920 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2921 &snapname);
2922 nvlist_t *props;
2923 int ret;
2924
2925 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2926 &parent_snapguid);
2927 err = nvlist_lookup_nvlist(fs, "props", &props);
2928 if (err)
2929 VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2930
2931 if (flags->canmountoff) {
2932 VERIFY(0 == nvlist_add_uint64(props,
2933 zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2934 }
2935 ret = zcmd_write_src_nvlist(hdl, &zc, props);
2936 if (err)
2937 nvlist_free(props);
2938
2939 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
3246
3247 if (err == 0) {
3248 nvlist_t *prop_errors;
3249 VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
3250 zc.zc_nvlist_dst_size, &prop_errors, 0));
3251
3252 nvpair_t *prop_err = NULL;
3253
3254 while ((prop_err = nvlist_next_nvpair(prop_errors,
3255 prop_err)) != NULL) {
3256 char tbuf[1024];
3257 zfs_prop_t prop;
3258 int intval;
3259
3260 prop = zfs_name_to_prop(nvpair_name(prop_err));
3261 (void) nvpair_value_int32(prop_err, &intval);
3262 if (strcmp(nvpair_name(prop_err),
3263 ZPROP_N_MORE_ERRORS) == 0) {
3264 trunc_prop_errs(intval);
3265 break;
3266 } else {
3267 (void) snprintf(tbuf, sizeof (tbuf),
3268 dgettext(TEXT_DOMAIN,
3269 "cannot receive %s property on %s"),
3270 nvpair_name(prop_err), zc.zc_name);
3271 zfs_setprop_error(hdl, prop, intval, tbuf);
3272 }
3273 }
3274 nvlist_free(prop_errors);
3275 }
3276
3277 zc.zc_nvlist_dst = 0;
3278 zc.zc_nvlist_dst_size = 0;
3279 zcmd_free_nvlists(&zc);
3280
3281 if (err == 0 && snapprops_nvlist) {
3282 zfs_cmd_t zc2 = { 0 };
3283
3284 (void) strcpy(zc2.zc_name, zc.zc_value);
3285 zc2.zc_cookie = B_TRUE; /* received */
3286 if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) {
3431 char buf1[64];
3432 char buf2[64];
3433 uint64_t bytes = zc.zc_cookie;
3434 time_t delta = time(NULL) - begin_time;
3435 if (delta == 0)
3436 delta = 1;
3437 zfs_nicenum(bytes, buf1, sizeof (buf1));
3438 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3439
3440 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3441 buf1, delta, buf2);
3442 }
3443
3444 return (0);
3445 }
3446
3447 static int
3448 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
3449 const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
3450 nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
3451 uint64_t *action_handlep)
3452 {
3453 int err;
3454 dmu_replay_record_t drr, drr_noswap;
3455 struct drr_begin *drrb = &drr.drr_u.drr_begin;
3456 char errbuf[1024];
3457 zio_cksum_t zcksum = { 0 };
3458 uint64_t featureflags;
3459 int hdrtype;
3460
3461 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3462 "cannot receive"));
3463
3464 if (flags->isprefix &&
3465 !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3466 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3467 "(%s) does not exist"), tosnap);
3468 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3469 }
3470 if (originsnap &&
3471 !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
3527
3528 if (strchr(drrb->drr_toname, '@') == NULL) {
3529 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3530 "stream (bad snapshot name)"));
3531 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3532 }
3533
3534 if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3535 char nonpackage_sendfs[ZFS_MAXNAMELEN];
3536 if (sendfs == NULL) {
3537 /*
3538 * We were not called from zfs_receive_package(). Get
3539 * the fs specified by 'zfs send'.
3540 */
3541 char *cp;
3542 (void) strlcpy(nonpackage_sendfs,
3543 drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3544 if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3545 *cp = '\0';
3546 sendfs = nonpackage_sendfs;
3547 }
3548 return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
3549 &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
3550 cleanup_fd, action_handlep));
3551 } else {
3552 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3553 DMU_COMPOUNDSTREAM);
3554 return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
3555 &zcksum, top_zfs, cleanup_fd, action_handlep));
3556 }
3557 }
3558
3559 /*
3560 * Restores a backup of tosnap from the file descriptor specified by infd.
3561 * Return 0 on total success, -2 if some things couldn't be
3562 * destroyed/renamed/promoted, -1 if some things couldn't be received.
3563 * (-1 will override -2, if -1 and the resumable flag was specified the
3564 * transfer can be resumed if the sending side supports it).
3565 */
3566 int
3567 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
3568 recvflags_t *flags, int infd, avl_tree_t *stream_avl)
3569 {
3570 char *top_zfs = NULL;
3571 int err;
3572 int cleanup_fd;
3573 uint64_t action_handle = 0;
3574 char *originsnap = NULL;
3575 if (props) {
3576 err = nvlist_lookup_string(props, "origin", &originsnap);
3577 if (err && err != ENOENT)
3578 return (err);
3579 }
3580
3581 cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3582 VERIFY(cleanup_fd >= 0);
3583
3584 err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
3585 stream_avl, &top_zfs, cleanup_fd, &action_handle);
3586
3587 VERIFY(0 == close(cleanup_fd));
3588
3589 if (err == 0 && !flags->nomount && top_zfs) {
3590 zfs_handle_t *zhp;
3591 prop_changelist_t *clp;
3592
3593 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3594 if (zhp != NULL) {
3595 clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3596 CL_GATHER_MOUNT_ALWAYS, 0);
3597 zfs_close(zhp);
3598 if (clp != NULL) {
3599 /* mount and share received datasets */
3600 err = changelist_postfix(clp);
3601 changelist_free(clp);
3602 }
3603 }
3604 if (zhp == NULL || clp == NULL || err)
3605 err = -1;
|
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
25 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Copyright (c) 2013 Steven Hartland. All rights reserved.
27 * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
28 */
29
30 #include <assert.h>
31 #include <ctype.h>
32 #include <errno.h>
33 #include <libintl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <strings.h>
37 #include <unistd.h>
38 #include <stddef.h>
39 #include <fcntl.h>
40 #include <sys/mount.h>
41 #include <pthread.h>
42 #include <umem.h>
43 #include <time.h>
44
45 #include <libzfs.h>
46 #include <libzfs_core.h>
47
48 #include "zfs_namecheck.h"
49 #include "zfs_prop.h"
50 #include "zfs_fletcher.h"
51 #include "libzfs_impl.h"
52 #include <zlib.h>
53 #include <sha2.h>
54 #include <sys/zio_checksum.h>
55 #include <sys/ddt.h>
56
57 /* in libzfs_dataset.c */
58 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
59
60 static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
61 recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
62 uint64_t *, const char *);
63 static int guid_to_name(libzfs_handle_t *, const char *,
64 uint64_t, boolean_t, char *);
65
66 static const zio_cksum_t zero_cksum = { 0 };
67
68 typedef struct dedup_arg {
69 int inputfd;
70 int outputfd;
71 libzfs_handle_t *dedup_hdl;
72 } dedup_arg_t;
73
74 typedef struct progress_arg {
75 zfs_handle_t *pa_zhp;
76 int pa_fd;
77 boolean_t pa_parsable;
78 } progress_arg_t;
79
80 typedef struct dataref {
81 uint64_t ref_guid;
82 uint64_t ref_object;
2545 nvlist_free(local_nv);
2546
2547 if (needagain && progress) {
2548 /* do another pass to fix up temporary names */
2549 if (flags->verbose)
2550 (void) printf("another pass:\n");
2551 goto again;
2552 }
2553
2554 return (needagain);
2555 }
2556
2557 static int
2558 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2559 recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2560 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2561 {
2562 nvlist_t *stream_nv = NULL;
2563 avl_tree_t *stream_avl = NULL;
2564 char *fromsnap = NULL;
2565 char *sendsnap = NULL;
2566 char *cp;
2567 char tofs[ZFS_MAXNAMELEN];
2568 char sendfs[ZFS_MAXNAMELEN];
2569 char errbuf[1024];
2570 dmu_replay_record_t drre;
2571 int error;
2572 boolean_t anyerr = B_FALSE;
2573 boolean_t softerr = B_FALSE;
2574 boolean_t recursive;
2575
2576 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2577 "cannot receive"));
2578
2579 assert(drr->drr_type == DRR_BEGIN);
2580 assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2581 assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2582 DMU_COMPOUNDSTREAM);
2583
2584 /*
2585 * Read in the nvlist from the stream.
2694 zfs_close(zhp);
2695 if (clp != NULL) {
2696 softerr |=
2697 changelist_prefix(clp);
2698 changelist_free(clp);
2699 }
2700 }
2701 }
2702
2703 nvlist_free(renamed);
2704 }
2705 }
2706
2707 /*
2708 * Get the fs specified by the first path in the stream (the top level
2709 * specified by 'zfs send') and pass it to each invocation of
2710 * zfs_receive_one().
2711 */
2712 (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2713 ZFS_MAXNAMELEN);
2714 if ((cp = strchr(sendfs, '@')) != NULL) {
2715 *cp = '\0';
2716 /*
2717 * Find the "sendsnap", the final snapshot in a replication
2718 * stream. zfs_receive_one() handles certain errors
2719 * differently, depending on if the contained stream is the
2720 * last one or not.
2721 */
2722 sendsnap = (cp + 1);
2723 }
2724
2725 /* Finally, receive each contained stream */
2726 do {
2727 /*
2728 * we should figure out if it has a recoverable
2729 * error, in which case do a recv_skip() and drive on.
2730 * Note, if we fail due to already having this guid,
2731 * zfs_receive_one() will take care of it (ie,
2732 * recv_skip() and return 0).
2733 */
2734 error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
2735 sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2736 action_handlep, sendsnap);
2737 if (error == ENODATA) {
2738 error = 0;
2739 break;
2740 }
2741 anyerr |= error;
2742 } while (error == 0);
2743
2744 if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2745 /*
2746 * Now that we have the fs's they sent us, try the
2747 * renames again.
2748 */
2749 softerr = recv_incremental_replication(hdl, tofs, flags,
2750 stream_nv, stream_avl, NULL);
2751 }
2752
2753 out:
2754 fsavl_destroy(stream_avl);
2755 if (stream_nv)
2756 nvlist_free(stream_nv);
2882 if (error == 0) {
2883 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2884 "checksum mismatch or incomplete stream.\n"
2885 "Partially received snapshot is saved.\n"
2886 "A resuming stream can be generated on the sending "
2887 "system by running:\n"
2888 " zfs send -t %s"),
2889 token_buf);
2890 }
2891 zfs_close(zhp);
2892 }
2893
2894 /*
2895 * Restores a backup of tosnap from the file descriptor specified by infd.
2896 */
2897 static int
2898 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2899 const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
2900 dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
2901 avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2902 uint64_t *action_handlep, const char *finalsnap)
2903 {
2904 zfs_cmd_t zc = { 0 };
2905 time_t begin_time;
2906 int ioctl_err, ioctl_errno, err;
2907 char *cp;
2908 struct drr_begin *drrb = &drr->drr_u.drr_begin;
2909 char errbuf[1024];
2910 char prop_errbuf[1024];
2911 const char *chopprefix;
2912 boolean_t newfs = B_FALSE;
2913 boolean_t stream_wantsnewfs;
2914 uint64_t parent_snapguid = 0;
2915 prop_changelist_t *clp = NULL;
2916 nvlist_t *snapprops_nvlist = NULL;
2917 zprop_errflags_t prop_errflags;
2918 boolean_t recursive;
2919 char *snapname = NULL;
2920
2921 begin_time = time(NULL);
2922
2923 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2924 "cannot receive"));
2925
2926 recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2927 ENOENT);
2928
2929 if (stream_avl != NULL) {
2930 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2931 &snapname);
2932 nvlist_t *props;
2933 int ret;
2934
2935 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2936 &parent_snapguid);
2937 err = nvlist_lookup_nvlist(fs, "props", &props);
2938 if (err)
2939 VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2940
2941 if (flags->canmountoff) {
2942 VERIFY(0 == nvlist_add_uint64(props,
2943 zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2944 }
2945 ret = zcmd_write_src_nvlist(hdl, &zc, props);
2946 if (err)
2947 nvlist_free(props);
2948
2949 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
3256
3257 if (err == 0) {
3258 nvlist_t *prop_errors;
3259 VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
3260 zc.zc_nvlist_dst_size, &prop_errors, 0));
3261
3262 nvpair_t *prop_err = NULL;
3263
3264 while ((prop_err = nvlist_next_nvpair(prop_errors,
3265 prop_err)) != NULL) {
3266 char tbuf[1024];
3267 zfs_prop_t prop;
3268 int intval;
3269
3270 prop = zfs_name_to_prop(nvpair_name(prop_err));
3271 (void) nvpair_value_int32(prop_err, &intval);
3272 if (strcmp(nvpair_name(prop_err),
3273 ZPROP_N_MORE_ERRORS) == 0) {
3274 trunc_prop_errs(intval);
3275 break;
3276 } else if (snapname == NULL || finalsnap == NULL ||
3277 strcmp(finalsnap, snapname) == 0 ||
3278 strcmp(nvpair_name(prop_err),
3279 zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) {
3280 /*
3281 * Skip the special case of, for example,
3282 * "refquota", errors on intermediate
3283 * snapshots leading up to a final one.
3284 * That's why we have all of the checks above.
3285 *
3286 * See zfs_ioctl.c's extract_delay_props() for
3287 * a list of props which can fail on
3288 * intermediate snapshots, but shouldn't
3289 * affect the overall receive.
3290 */
3291 (void) snprintf(tbuf, sizeof (tbuf),
3292 dgettext(TEXT_DOMAIN,
3293 "cannot receive %s property on %s"),
3294 nvpair_name(prop_err), zc.zc_name);
3295 zfs_setprop_error(hdl, prop, intval, tbuf);
3296 }
3297 }
3298 nvlist_free(prop_errors);
3299 }
3300
3301 zc.zc_nvlist_dst = 0;
3302 zc.zc_nvlist_dst_size = 0;
3303 zcmd_free_nvlists(&zc);
3304
3305 if (err == 0 && snapprops_nvlist) {
3306 zfs_cmd_t zc2 = { 0 };
3307
3308 (void) strcpy(zc2.zc_name, zc.zc_value);
3309 zc2.zc_cookie = B_TRUE; /* received */
3310 if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) {
3455 char buf1[64];
3456 char buf2[64];
3457 uint64_t bytes = zc.zc_cookie;
3458 time_t delta = time(NULL) - begin_time;
3459 if (delta == 0)
3460 delta = 1;
3461 zfs_nicenum(bytes, buf1, sizeof (buf1));
3462 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3463
3464 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3465 buf1, delta, buf2);
3466 }
3467
3468 return (0);
3469 }
3470
3471 static int
3472 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
3473 const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
3474 nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
3475 uint64_t *action_handlep, const char *finalsnap)
3476 {
3477 int err;
3478 dmu_replay_record_t drr, drr_noswap;
3479 struct drr_begin *drrb = &drr.drr_u.drr_begin;
3480 char errbuf[1024];
3481 zio_cksum_t zcksum = { 0 };
3482 uint64_t featureflags;
3483 int hdrtype;
3484
3485 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3486 "cannot receive"));
3487
3488 if (flags->isprefix &&
3489 !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3490 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3491 "(%s) does not exist"), tosnap);
3492 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3493 }
3494 if (originsnap &&
3495 !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
3551
3552 if (strchr(drrb->drr_toname, '@') == NULL) {
3553 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3554 "stream (bad snapshot name)"));
3555 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3556 }
3557
3558 if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3559 char nonpackage_sendfs[ZFS_MAXNAMELEN];
3560 if (sendfs == NULL) {
3561 /*
3562 * We were not called from zfs_receive_package(). Get
3563 * the fs specified by 'zfs send'.
3564 */
3565 char *cp;
3566 (void) strlcpy(nonpackage_sendfs,
3567 drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3568 if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3569 *cp = '\0';
3570 sendfs = nonpackage_sendfs;
3571 VERIFY(finalsnap == NULL);
3572 }
3573 return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
3574 &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
3575 cleanup_fd, action_handlep, finalsnap));
3576 } else {
3577 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3578 DMU_COMPOUNDSTREAM);
3579 return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
3580 &zcksum, top_zfs, cleanup_fd, action_handlep));
3581 }
3582 }
3583
3584 /*
3585 * Restores a backup of tosnap from the file descriptor specified by infd.
3586 * Return 0 on total success, -2 if some things couldn't be
3587 * destroyed/renamed/promoted, -1 if some things couldn't be received.
3588 * (-1 will override -2, if -1 and the resumable flag was specified the
3589 * transfer can be resumed if the sending side supports it).
3590 */
3591 int
3592 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
3593 recvflags_t *flags, int infd, avl_tree_t *stream_avl)
3594 {
3595 char *top_zfs = NULL;
3596 int err;
3597 int cleanup_fd;
3598 uint64_t action_handle = 0;
3599 char *originsnap = NULL;
3600 if (props) {
3601 err = nvlist_lookup_string(props, "origin", &originsnap);
3602 if (err && err != ENOENT)
3603 return (err);
3604 }
3605
3606 cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3607 VERIFY(cleanup_fd >= 0);
3608
3609 err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
3610 stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
3611
3612 VERIFY(0 == close(cleanup_fd));
3613
3614 if (err == 0 && !flags->nomount && top_zfs) {
3615 zfs_handle_t *zhp;
3616 prop_changelist_t *clp;
3617
3618 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3619 if (zhp != NULL) {
3620 clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3621 CL_GATHER_MOUNT_ALWAYS, 0);
3622 zfs_close(zhp);
3623 if (clp != NULL) {
3624 /* mount and share received datasets */
3625 err = changelist_postfix(clp);
3626 changelist_free(clp);
3627 }
3628 }
3629 if (zhp == NULL || clp == NULL || err)
3630 err = -1;
|