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, 2014 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 <sha2.h>
52 #include <sys/zio_checksum.h>
53 #include <sys/ddt.h>
54
55 /* in libzfs_dataset.c */
56 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
57
58 static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t *,
59 int, const char *, nvlist_t *, avl_tree_t *, char **, int, uint64_t *);
60
61 static const zio_cksum_t zero_cksum = { 0 };
62
63 typedef struct dedup_arg {
64 int inputfd;
65 int outputfd;
66 libzfs_handle_t *dedup_hdl;
67 } dedup_arg_t;
68
69 typedef struct progress_arg {
70 zfs_handle_t *pa_zhp;
71 int pa_fd;
72 boolean_t pa_parsable;
73 } progress_arg_t;
74
75 typedef struct dataref {
76 uint64_t ref_guid;
77 uint64_t ref_object;
78 uint64_t ref_offset;
79 } dataref_t;
2288 nvlist_free(local_nv);
2289
2290 if (needagain && progress) {
2291 /* do another pass to fix up temporary names */
2292 if (flags->verbose)
2293 (void) printf("another pass:\n");
2294 goto again;
2295 }
2296
2297 return (needagain);
2298 }
2299
2300 static int
2301 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2302 recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2303 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2304 {
2305 nvlist_t *stream_nv = NULL;
2306 avl_tree_t *stream_avl = NULL;
2307 char *fromsnap = NULL;
2308 char *cp;
2309 char tofs[ZFS_MAXNAMELEN];
2310 char sendfs[ZFS_MAXNAMELEN];
2311 char errbuf[1024];
2312 dmu_replay_record_t drre;
2313 int error;
2314 boolean_t anyerr = B_FALSE;
2315 boolean_t softerr = B_FALSE;
2316 boolean_t recursive;
2317
2318 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2319 "cannot receive"));
2320
2321 assert(drr->drr_type == DRR_BEGIN);
2322 assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2323 assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2324 DMU_COMPOUNDSTREAM);
2325
2326 /*
2327 * Read in the nvlist from the stream.
2436 zfs_close(zhp);
2437 if (clp != NULL) {
2438 softerr |=
2439 changelist_prefix(clp);
2440 changelist_free(clp);
2441 }
2442 }
2443 }
2444
2445 nvlist_free(renamed);
2446 }
2447 }
2448
2449 /*
2450 * Get the fs specified by the first path in the stream (the top level
2451 * specified by 'zfs send') and pass it to each invocation of
2452 * zfs_receive_one().
2453 */
2454 (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2455 ZFS_MAXNAMELEN);
2456 if ((cp = strchr(sendfs, '@')) != NULL)
2457 *cp = '\0';
2458
2459 /* Finally, receive each contained stream */
2460 do {
2461 /*
2462 * we should figure out if it has a recoverable
2463 * error, in which case do a recv_skip() and drive on.
2464 * Note, if we fail due to already having this guid,
2465 * zfs_receive_one() will take care of it (ie,
2466 * recv_skip() and return 0).
2467 */
2468 error = zfs_receive_impl(hdl, destname, flags, fd,
2469 sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2470 action_handlep);
2471 if (error == ENODATA) {
2472 error = 0;
2473 break;
2474 }
2475 anyerr |= error;
2476 } while (error == 0);
2477
2478 if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2479 /*
2480 * Now that we have the fs's they sent us, try the
2481 * renames again.
2482 */
2483 softerr = recv_incremental_replication(hdl, tofs, flags,
2484 stream_nv, stream_avl, NULL);
2485 }
2486
2487 out:
2488 fsavl_destroy(stream_avl);
2489 if (stream_nv)
2490 nvlist_free(stream_nv);
2584
2585 default:
2586 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2587 "invalid record type"));
2588 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2589 }
2590 }
2591
2592 free(buf);
2593 return (-1);
2594 }
2595
2596 /*
2597 * Restores a backup of tosnap from the file descriptor specified by infd.
2598 */
2599 static int
2600 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2601 recvflags_t *flags, dmu_replay_record_t *drr,
2602 dmu_replay_record_t *drr_noswap, const char *sendfs,
2603 nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2604 uint64_t *action_handlep)
2605 {
2606 zfs_cmd_t zc = { 0 };
2607 time_t begin_time;
2608 int ioctl_err, ioctl_errno, err;
2609 char *cp;
2610 struct drr_begin *drrb = &drr->drr_u.drr_begin;
2611 char errbuf[1024];
2612 char prop_errbuf[1024];
2613 const char *chopprefix;
2614 boolean_t newfs = B_FALSE;
2615 boolean_t stream_wantsnewfs;
2616 uint64_t parent_snapguid = 0;
2617 prop_changelist_t *clp = NULL;
2618 nvlist_t *snapprops_nvlist = NULL;
2619 zprop_errflags_t prop_errflags;
2620 boolean_t recursive;
2621
2622 begin_time = time(NULL);
2623
2624 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2625 "cannot receive"));
2626
2627 recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2628 ENOENT);
2629
2630 if (stream_avl != NULL) {
2631 char *snapname;
2632 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2633 &snapname);
2634 nvlist_t *props;
2635 int ret;
2636
2637 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2638 &parent_snapguid);
2639 err = nvlist_lookup_nvlist(fs, "props", &props);
2640 if (err)
2641 VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2642
2643 if (flags->canmountoff) {
2644 VERIFY(0 == nvlist_add_uint64(props,
2645 zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2646 }
2647 ret = zcmd_write_src_nvlist(hdl, &zc, props);
2648 if (err)
2649 nvlist_free(props);
2650
2651 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
2937
2938 if (err == 0) {
2939 nvlist_t *prop_errors;
2940 VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
2941 zc.zc_nvlist_dst_size, &prop_errors, 0));
2942
2943 nvpair_t *prop_err = NULL;
2944
2945 while ((prop_err = nvlist_next_nvpair(prop_errors,
2946 prop_err)) != NULL) {
2947 char tbuf[1024];
2948 zfs_prop_t prop;
2949 int intval;
2950
2951 prop = zfs_name_to_prop(nvpair_name(prop_err));
2952 (void) nvpair_value_int32(prop_err, &intval);
2953 if (strcmp(nvpair_name(prop_err),
2954 ZPROP_N_MORE_ERRORS) == 0) {
2955 trunc_prop_errs(intval);
2956 break;
2957 } else {
2958 (void) snprintf(tbuf, sizeof (tbuf),
2959 dgettext(TEXT_DOMAIN,
2960 "cannot receive %s property on %s"),
2961 nvpair_name(prop_err), zc.zc_name);
2962 zfs_setprop_error(hdl, prop, intval, tbuf);
2963 }
2964 }
2965 nvlist_free(prop_errors);
2966 }
2967
2968 zc.zc_nvlist_dst = 0;
2969 zc.zc_nvlist_dst_size = 0;
2970 zcmd_free_nvlists(&zc);
2971
2972 if (err == 0 && snapprops_nvlist) {
2973 zfs_cmd_t zc2 = { 0 };
2974
2975 (void) strcpy(zc2.zc_name, zc.zc_value);
2976 zc2.zc_cookie = B_TRUE; /* received */
2977 if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) {
3122 if (flags->verbose) {
3123 char buf1[64];
3124 char buf2[64];
3125 uint64_t bytes = zc.zc_cookie;
3126 time_t delta = time(NULL) - begin_time;
3127 if (delta == 0)
3128 delta = 1;
3129 zfs_nicenum(bytes, buf1, sizeof (buf1));
3130 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3131
3132 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3133 buf1, delta, buf2);
3134 }
3135
3136 return (0);
3137 }
3138
3139 static int
3140 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
3141 int infd, const char *sendfs, nvlist_t *stream_nv, avl_tree_t *stream_avl,
3142 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
3143 {
3144 int err;
3145 dmu_replay_record_t drr, drr_noswap;
3146 struct drr_begin *drrb = &drr.drr_u.drr_begin;
3147 char errbuf[1024];
3148 zio_cksum_t zcksum = { 0 };
3149 uint64_t featureflags;
3150 int hdrtype;
3151
3152 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3153 "cannot receive"));
3154
3155 if (flags->isprefix &&
3156 !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3157 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3158 "(%s) does not exist"), tosnap);
3159 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3160 }
3161
3162 /* read in the BEGIN record */
3212
3213 if (strchr(drrb->drr_toname, '@') == NULL) {
3214 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3215 "stream (bad snapshot name)"));
3216 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3217 }
3218
3219 if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3220 char nonpackage_sendfs[ZFS_MAXNAMELEN];
3221 if (sendfs == NULL) {
3222 /*
3223 * We were not called from zfs_receive_package(). Get
3224 * the fs specified by 'zfs send'.
3225 */
3226 char *cp;
3227 (void) strlcpy(nonpackage_sendfs,
3228 drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3229 if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3230 *cp = '\0';
3231 sendfs = nonpackage_sendfs;
3232 }
3233 return (zfs_receive_one(hdl, infd, tosnap, flags,
3234 &drr, &drr_noswap, sendfs, stream_nv, stream_avl,
3235 top_zfs, cleanup_fd, action_handlep));
3236 } else {
3237 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3238 DMU_COMPOUNDSTREAM);
3239 return (zfs_receive_package(hdl, infd, tosnap, flags,
3240 &drr, &zcksum, top_zfs, cleanup_fd, action_handlep));
3241 }
3242 }
3243
3244 /*
3245 * Restores a backup of tosnap from the file descriptor specified by infd.
3246 * Return 0 on total success, -2 if some things couldn't be
3247 * destroyed/renamed/promoted, -1 if some things couldn't be received.
3248 * (-1 will override -2).
3249 */
3250 int
3251 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
3252 int infd, avl_tree_t *stream_avl)
3253 {
3254 char *top_zfs = NULL;
3255 int err;
3256 int cleanup_fd;
3257 uint64_t action_handle = 0;
3258
3259 cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3260 VERIFY(cleanup_fd >= 0);
3261
3262 err = zfs_receive_impl(hdl, tosnap, flags, infd, NULL, NULL,
3263 stream_avl, &top_zfs, cleanup_fd, &action_handle);
3264
3265 VERIFY(0 == close(cleanup_fd));
3266
3267 if (err == 0 && !flags->nomount && top_zfs) {
3268 zfs_handle_t *zhp;
3269 prop_changelist_t *clp;
3270
3271 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3272 if (zhp != NULL) {
3273 clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3274 CL_GATHER_MOUNT_ALWAYS, 0);
3275 zfs_close(zhp);
3276 if (clp != NULL) {
3277 /* mount and share received datasets */
3278 err = changelist_postfix(clp);
3279 changelist_free(clp);
3280 }
3281 }
3282 if (zhp == NULL || clp == NULL || err)
3283 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, 2014 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 <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 *, recvflags_t *,
60 int, const char *, nvlist_t *, avl_tree_t *, char **, int, uint64_t *,
61 const char *);
62
63 static const zio_cksum_t zero_cksum = { 0 };
64
65 typedef struct dedup_arg {
66 int inputfd;
67 int outputfd;
68 libzfs_handle_t *dedup_hdl;
69 } dedup_arg_t;
70
71 typedef struct progress_arg {
72 zfs_handle_t *pa_zhp;
73 int pa_fd;
74 boolean_t pa_parsable;
75 } progress_arg_t;
76
77 typedef struct dataref {
78 uint64_t ref_guid;
79 uint64_t ref_object;
80 uint64_t ref_offset;
81 } dataref_t;
2290 nvlist_free(local_nv);
2291
2292 if (needagain && progress) {
2293 /* do another pass to fix up temporary names */
2294 if (flags->verbose)
2295 (void) printf("another pass:\n");
2296 goto again;
2297 }
2298
2299 return (needagain);
2300 }
2301
2302 static int
2303 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2304 recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2305 char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2306 {
2307 nvlist_t *stream_nv = NULL;
2308 avl_tree_t *stream_avl = NULL;
2309 char *fromsnap = NULL;
2310 char *sendsnap = NULL;
2311 char *cp;
2312 char tofs[ZFS_MAXNAMELEN];
2313 char sendfs[ZFS_MAXNAMELEN];
2314 char errbuf[1024];
2315 dmu_replay_record_t drre;
2316 int error;
2317 boolean_t anyerr = B_FALSE;
2318 boolean_t softerr = B_FALSE;
2319 boolean_t recursive;
2320
2321 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2322 "cannot receive"));
2323
2324 assert(drr->drr_type == DRR_BEGIN);
2325 assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2326 assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2327 DMU_COMPOUNDSTREAM);
2328
2329 /*
2330 * Read in the nvlist from the stream.
2439 zfs_close(zhp);
2440 if (clp != NULL) {
2441 softerr |=
2442 changelist_prefix(clp);
2443 changelist_free(clp);
2444 }
2445 }
2446 }
2447
2448 nvlist_free(renamed);
2449 }
2450 }
2451
2452 /*
2453 * Get the fs specified by the first path in the stream (the top level
2454 * specified by 'zfs send') and pass it to each invocation of
2455 * zfs_receive_one().
2456 */
2457 (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2458 ZFS_MAXNAMELEN);
2459 if ((cp = strchr(sendfs, '@')) != NULL) {
2460 *cp = '\0';
2461 /*
2462 * Find the "sendsnap", the final snapshot in a replication
2463 * stream. zfs_receive_one() handles certain errors
2464 * differently, depending on if the contained stream is the
2465 * last one or not.
2466 */
2467 sendsnap = (cp + 1);
2468 }
2469
2470 /* Finally, receive each contained stream */
2471 do {
2472 /*
2473 * we should figure out if it has a recoverable
2474 * error, in which case do a recv_skip() and drive on.
2475 * Note, if we fail due to already having this guid,
2476 * zfs_receive_one() will take care of it (ie,
2477 * recv_skip() and return 0).
2478 */
2479 error = zfs_receive_impl(hdl, destname, flags, fd,
2480 sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2481 action_handlep, sendsnap);
2482 if (error == ENODATA) {
2483 error = 0;
2484 break;
2485 }
2486 anyerr |= error;
2487 } while (error == 0);
2488
2489 if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2490 /*
2491 * Now that we have the fs's they sent us, try the
2492 * renames again.
2493 */
2494 softerr = recv_incremental_replication(hdl, tofs, flags,
2495 stream_nv, stream_avl, NULL);
2496 }
2497
2498 out:
2499 fsavl_destroy(stream_avl);
2500 if (stream_nv)
2501 nvlist_free(stream_nv);
2595
2596 default:
2597 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2598 "invalid record type"));
2599 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2600 }
2601 }
2602
2603 free(buf);
2604 return (-1);
2605 }
2606
2607 /*
2608 * Restores a backup of tosnap from the file descriptor specified by infd.
2609 */
2610 static int
2611 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2612 recvflags_t *flags, dmu_replay_record_t *drr,
2613 dmu_replay_record_t *drr_noswap, const char *sendfs,
2614 nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2615 uint64_t *action_handlep, const char *finalsnap)
2616 {
2617 zfs_cmd_t zc = { 0 };
2618 time_t begin_time;
2619 int ioctl_err, ioctl_errno, err;
2620 char *cp;
2621 struct drr_begin *drrb = &drr->drr_u.drr_begin;
2622 char errbuf[1024];
2623 char prop_errbuf[1024];
2624 const char *chopprefix;
2625 boolean_t newfs = B_FALSE;
2626 boolean_t stream_wantsnewfs;
2627 uint64_t parent_snapguid = 0;
2628 prop_changelist_t *clp = NULL;
2629 nvlist_t *snapprops_nvlist = NULL;
2630 zprop_errflags_t prop_errflags;
2631 boolean_t recursive;
2632 char *snapname = NULL;
2633
2634 begin_time = time(NULL);
2635
2636 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2637 "cannot receive"));
2638
2639 recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2640 ENOENT);
2641
2642 if (stream_avl != NULL) {
2643 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2644 &snapname);
2645 nvlist_t *props;
2646 int ret;
2647
2648 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2649 &parent_snapguid);
2650 err = nvlist_lookup_nvlist(fs, "props", &props);
2651 if (err)
2652 VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2653
2654 if (flags->canmountoff) {
2655 VERIFY(0 == nvlist_add_uint64(props,
2656 zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2657 }
2658 ret = zcmd_write_src_nvlist(hdl, &zc, props);
2659 if (err)
2660 nvlist_free(props);
2661
2662 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
2948
2949 if (err == 0) {
2950 nvlist_t *prop_errors;
2951 VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
2952 zc.zc_nvlist_dst_size, &prop_errors, 0));
2953
2954 nvpair_t *prop_err = NULL;
2955
2956 while ((prop_err = nvlist_next_nvpair(prop_errors,
2957 prop_err)) != NULL) {
2958 char tbuf[1024];
2959 zfs_prop_t prop;
2960 int intval;
2961
2962 prop = zfs_name_to_prop(nvpair_name(prop_err));
2963 (void) nvpair_value_int32(prop_err, &intval);
2964 if (strcmp(nvpair_name(prop_err),
2965 ZPROP_N_MORE_ERRORS) == 0) {
2966 trunc_prop_errs(intval);
2967 break;
2968 } else if (snapname == NULL || finalsnap == NULL ||
2969 strcmp(finalsnap, snapname) == 0 ||
2970 strcmp(nvpair_name(prop_err),
2971 zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) {
2972 /*
2973 * Skip the special case of, for example,
2974 * "refquota", errors on intermediate
2975 * snapshots leading up to a final one.
2976 * That's why we have all of the checks above.
2977 *
2978 * See zfs_ioctl.c's extract_delay_props() for
2979 * a list of props which can fail on
2980 * intermediate snapshots, but shouldn't
2981 * affect the overall receive.
2982 */
2983 (void) snprintf(tbuf, sizeof (tbuf),
2984 dgettext(TEXT_DOMAIN,
2985 "cannot receive %s property on %s"),
2986 nvpair_name(prop_err), zc.zc_name);
2987 zfs_setprop_error(hdl, prop, intval, tbuf);
2988 }
2989 }
2990 nvlist_free(prop_errors);
2991 }
2992
2993 zc.zc_nvlist_dst = 0;
2994 zc.zc_nvlist_dst_size = 0;
2995 zcmd_free_nvlists(&zc);
2996
2997 if (err == 0 && snapprops_nvlist) {
2998 zfs_cmd_t zc2 = { 0 };
2999
3000 (void) strcpy(zc2.zc_name, zc.zc_value);
3001 zc2.zc_cookie = B_TRUE; /* received */
3002 if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) {
3147 if (flags->verbose) {
3148 char buf1[64];
3149 char buf2[64];
3150 uint64_t bytes = zc.zc_cookie;
3151 time_t delta = time(NULL) - begin_time;
3152 if (delta == 0)
3153 delta = 1;
3154 zfs_nicenum(bytes, buf1, sizeof (buf1));
3155 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3156
3157 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3158 buf1, delta, buf2);
3159 }
3160
3161 return (0);
3162 }
3163
3164 static int
3165 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
3166 int infd, const char *sendfs, nvlist_t *stream_nv, avl_tree_t *stream_avl,
3167 char **top_zfs, int cleanup_fd, uint64_t *action_handlep,
3168 const char *finalsnap)
3169 {
3170 int err;
3171 dmu_replay_record_t drr, drr_noswap;
3172 struct drr_begin *drrb = &drr.drr_u.drr_begin;
3173 char errbuf[1024];
3174 zio_cksum_t zcksum = { 0 };
3175 uint64_t featureflags;
3176 int hdrtype;
3177
3178 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3179 "cannot receive"));
3180
3181 if (flags->isprefix &&
3182 !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3183 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3184 "(%s) does not exist"), tosnap);
3185 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3186 }
3187
3188 /* read in the BEGIN record */
3238
3239 if (strchr(drrb->drr_toname, '@') == NULL) {
3240 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3241 "stream (bad snapshot name)"));
3242 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3243 }
3244
3245 if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3246 char nonpackage_sendfs[ZFS_MAXNAMELEN];
3247 if (sendfs == NULL) {
3248 /*
3249 * We were not called from zfs_receive_package(). Get
3250 * the fs specified by 'zfs send'.
3251 */
3252 char *cp;
3253 (void) strlcpy(nonpackage_sendfs,
3254 drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3255 if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3256 *cp = '\0';
3257 sendfs = nonpackage_sendfs;
3258 VERIFY(finalsnap == NULL);
3259 }
3260 return (zfs_receive_one(hdl, infd, tosnap, flags,
3261 &drr, &drr_noswap, sendfs, stream_nv, stream_avl,
3262 top_zfs, cleanup_fd, action_handlep, finalsnap));
3263 } else {
3264 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3265 DMU_COMPOUNDSTREAM);
3266 return (zfs_receive_package(hdl, infd, tosnap, flags,
3267 &drr, &zcksum, top_zfs, cleanup_fd, action_handlep));
3268 }
3269 }
3270
3271 /*
3272 * Restores a backup of tosnap from the file descriptor specified by infd.
3273 * Return 0 on total success, -2 if some things couldn't be
3274 * destroyed/renamed/promoted, -1 if some things couldn't be received.
3275 * (-1 will override -2).
3276 */
3277 int
3278 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
3279 int infd, avl_tree_t *stream_avl)
3280 {
3281 char *top_zfs = NULL;
3282 int err;
3283 int cleanup_fd;
3284 uint64_t action_handle = 0;
3285
3286 cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3287 VERIFY(cleanup_fd >= 0);
3288
3289 err = zfs_receive_impl(hdl, tosnap, flags, infd, NULL, NULL,
3290 stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
3291
3292 VERIFY(0 == close(cleanup_fd));
3293
3294 if (err == 0 && !flags->nomount && top_zfs) {
3295 zfs_handle_t *zhp;
3296 prop_changelist_t *clp;
3297
3298 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3299 if (zhp != NULL) {
3300 clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3301 CL_GATHER_MOUNT_ALWAYS, 0);
3302 zfs_close(zhp);
3303 if (clp != NULL) {
3304 /* mount and share received datasets */
3305 err = changelist_postfix(clp);
3306 changelist_free(clp);
3307 }
3308 }
3309 if (zhp == NULL || clp == NULL || err)
3310 err = -1;
|