1 5367 ahrens /* 2 5367 ahrens * CDDL HEADER START 3 5367 ahrens * 4 5367 ahrens * The contents of this file are subject to the terms of the 5 5367 ahrens * Common Development and Distribution License (the "License"). 6 5367 ahrens * You may not use this file except in compliance with the License. 7 5367 ahrens * 8 5367 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 5367 ahrens * or http://www.opensolaris.org/os/licensing. 10 5367 ahrens * See the License for the specific language governing permissions 11 5367 ahrens * and limitations under the License. 12 5367 ahrens * 13 5367 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 5367 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 5367 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 5367 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 5367 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 5367 ahrens * 19 5367 ahrens * CDDL HEADER END 20 5367 ahrens */ 21 5367 ahrens 22 5367 ahrens /* 23 8584 Lori * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 5367 ahrens * Use is subject to license terms. 25 5367 ahrens */ 26 5367 ahrens 27 5367 ahrens #include <assert.h> 28 5367 ahrens #include <ctype.h> 29 5367 ahrens #include <errno.h> 30 5367 ahrens #include <libintl.h> 31 5367 ahrens #include <stdio.h> 32 5367 ahrens #include <stdlib.h> 33 5367 ahrens #include <strings.h> 34 5367 ahrens #include <unistd.h> 35 5367 ahrens #include <stddef.h> 36 5367 ahrens #include <fcntl.h> 37 5367 ahrens #include <sys/mount.h> 38 11007 Lori #include <pthread.h> 39 11007 Lori #include <umem.h> 40 5367 ahrens 41 5367 ahrens #include <libzfs.h> 42 5367 ahrens 43 5367 ahrens #include "zfs_namecheck.h" 44 5367 ahrens #include "zfs_prop.h" 45 10602 Lori #include "zfs_fletcher.h" 46 5367 ahrens #include "libzfs_impl.h" 47 11007 Lori #include <sha2.h> 48 11022 Tom 49 11022 Tom /* in libzfs_dataset.c */ 50 11022 Tom extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *); 51 7366 Tim 52 7366 Tim static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t, 53 7366 Tim int, avl_tree_t *, char **); 54 11007 Lori 55 11007 Lori static const zio_cksum_t zero_cksum = { 0 }; 56 11007 Lori 57 11007 Lori typedef struct dedup_arg { 58 11007 Lori int inputfd; 59 11007 Lori int outputfd; 60 11007 Lori libzfs_handle_t *dedup_hdl; 61 11007 Lori } dedup_arg_t; 62 11007 Lori 63 11007 Lori typedef struct dataref { 64 11007 Lori uint64_t ref_guid; 65 11007 Lori uint64_t ref_object; 66 11007 Lori uint64_t ref_offset; 67 11007 Lori } dataref_t; 68 11007 Lori 69 11007 Lori typedef struct dedup_entry { 70 11007 Lori struct dedup_entry *dde_next; 71 11007 Lori zio_cksum_t dde_chksum; 72 11007 Lori dataref_t dde_ref; 73 11007 Lori } dedup_entry_t; 74 11007 Lori 75 11007 Lori #define MAX_DDT_PHYSMEM_PERCENT 20 76 11007 Lori #define SMALLEST_POSSIBLE_MAX_DDT_MB 128 77 11007 Lori 78 11007 Lori typedef struct dedup_table { 79 11007 Lori dedup_entry_t **dedup_hash_array; 80 11007 Lori umem_cache_t *ddecache; 81 11007 Lori uint64_t max_ddt_size; /* max dedup table size in bytes */ 82 11007 Lori uint64_t cur_ddt_size; /* current dedup table size in bytes */ 83 11007 Lori uint64_t ddt_count; 84 11007 Lori int numhashbits; 85 11007 Lori boolean_t ddt_full; 86 11007 Lori } dedup_table_t; 87 11007 Lori 88 11007 Lori static int 89 11007 Lori high_order_bit(uint64_t n) 90 11007 Lori { 91 11007 Lori int count; 92 11007 Lori 93 11007 Lori for (count = 0; n != 0; count++) 94 11007 Lori n >>= 1; 95 11007 Lori return (count); 96 11007 Lori } 97 11007 Lori 98 11007 Lori static size_t 99 11007 Lori ssread(void *buf, size_t len, FILE *stream) 100 11007 Lori { 101 11007 Lori size_t outlen; 102 11007 Lori 103 11007 Lori if ((outlen = fread(buf, len, 1, stream)) == 0) 104 11007 Lori return (0); 105 11007 Lori 106 11007 Lori return (outlen); 107 11007 Lori } 108 11007 Lori 109 11007 Lori static void 110 11007 Lori ddt_hash_append(libzfs_handle_t *hdl, dedup_table_t *ddt, dedup_entry_t **ddepp, 111 11007 Lori zio_cksum_t *cs, dataref_t *dr) 112 11007 Lori { 113 11007 Lori dedup_entry_t *dde; 114 11007 Lori 115 11007 Lori if (ddt->cur_ddt_size >= ddt->max_ddt_size) { 116 11007 Lori if (ddt->ddt_full == B_FALSE) { 117 11007 Lori zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 118 11007 Lori "Dedup table full. Deduplication will continue " 119 11007 Lori "with existing table entries")); 120 11007 Lori ddt->ddt_full = B_TRUE; 121 11007 Lori } 122 11007 Lori return; 123 11007 Lori } 124 11007 Lori 125 11007 Lori if ((dde = umem_cache_alloc(ddt->ddecache, UMEM_DEFAULT)) 126 11007 Lori != NULL) { 127 11007 Lori assert(*ddepp == NULL); 128 11007 Lori dde->dde_next = NULL; 129 11007 Lori dde->dde_chksum = *cs; 130 11007 Lori dde->dde_ref = *dr; 131 11007 Lori *ddepp = dde; 132 11007 Lori ddt->cur_ddt_size += sizeof (dedup_entry_t); 133 11007 Lori ddt->ddt_count++; 134 11007 Lori } 135 11007 Lori } 136 11007 Lori 137 11007 Lori /* 138 11007 Lori * Using the specified dedup table, do a lookup for an entry with 139 11007 Lori * the checksum cs. If found, return the block's reference info 140 11007 Lori * in *dr. Otherwise, insert a new entry in the dedup table, using 141 11007 Lori * the reference information specified by *dr. 142 11007 Lori * 143 11007 Lori * return value: true - entry was found 144 11007 Lori * false - entry was not found 145 11007 Lori */ 146 11007 Lori static boolean_t 147 11007 Lori ddt_update(libzfs_handle_t *hdl, dedup_table_t *ddt, zio_cksum_t *cs, 148 11007 Lori dataref_t *dr) 149 11007 Lori { 150 11007 Lori uint32_t hashcode; 151 11007 Lori dedup_entry_t **ddepp; 152 11007 Lori 153 11007 Lori hashcode = BF64_GET(cs->zc_word[0], 0, ddt->numhashbits); 154 11007 Lori 155 11007 Lori for (ddepp = &(ddt->dedup_hash_array[hashcode]); *ddepp != NULL; 156 11007 Lori ddepp = &((*ddepp)->dde_next)) { 157 11007 Lori if (ZIO_CHECKSUM_EQUAL(((*ddepp)->dde_chksum), *cs)) { 158 11007 Lori *dr = (*ddepp)->dde_ref; 159 11007 Lori return (B_TRUE); 160 11007 Lori } 161 11007 Lori } 162 11007 Lori ddt_hash_append(hdl, ddt, ddepp, cs, dr); 163 11007 Lori return (B_FALSE); 164 11007 Lori } 165 11007 Lori 166 11007 Lori static int 167 11007 Lori cksum_and_write(const void *buf, uint64_t len, zio_cksum_t *zc, int outfd) 168 11007 Lori { 169 11007 Lori fletcher_4_incremental_native(buf, len, zc); 170 11007 Lori return (write(outfd, buf, len)); 171 11007 Lori } 172 11007 Lori 173 11007 Lori /* 174 11007 Lori * This function is started in a separate thread when the dedup option 175 11007 Lori * has been requested. The main send thread determines the list of 176 11007 Lori * snapshots to be included in the send stream and makes the ioctl calls 177 11007 Lori * for each one. But instead of having the ioctl send the output to the 178 11007 Lori * the output fd specified by the caller of zfs_send()), the 179 11007 Lori * ioctl is told to direct the output to a pipe, which is read by the 180 11007 Lori * alternate thread running THIS function. This function does the 181 11007 Lori * dedup'ing by: 182 11007 Lori * 1. building a dedup table (the DDT) 183 11007 Lori * 2. doing checksums on each data block and inserting a record in the DDT 184 11007 Lori * 3. looking for matching checksums, and 185 11007 Lori * 4. sending a DRR_WRITE_BYREF record instead of a write record whenever 186 11007 Lori * a duplicate block is found. 187 11007 Lori * The output of this function then goes to the output fd requested 188 11007 Lori * by the caller of zfs_send(). 189 11007 Lori */ 190 11007 Lori static void * 191 11007 Lori cksummer(void *arg) 192 11007 Lori { 193 11007 Lori dedup_arg_t *dda = arg; 194 11007 Lori char *buf = malloc(1<<20); 195 11007 Lori dmu_replay_record_t thedrr; 196 11007 Lori dmu_replay_record_t *drr = &thedrr; 197 11007 Lori struct drr_begin *drrb = &thedrr.drr_u.drr_begin; 198 11007 Lori struct drr_end *drre = &thedrr.drr_u.drr_end; 199 11007 Lori struct drr_object *drro = &thedrr.drr_u.drr_object; 200 11007 Lori struct drr_write *drrw = &thedrr.drr_u.drr_write; 201 11007 Lori FILE *ofp; 202 11007 Lori int outfd; 203 11007 Lori dmu_replay_record_t wbr_drr; 204 11007 Lori struct drr_write_byref *wbr_drrr = &wbr_drr.drr_u.drr_write_byref; 205 11007 Lori dedup_table_t ddt; 206 11007 Lori zio_cksum_t stream_cksum; 207 11007 Lori uint64_t physmem = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); 208 11007 Lori uint64_t numbuckets; 209 11007 Lori 210 11007 Lori ddt.max_ddt_size = 211 11007 Lori MAX((physmem * MAX_DDT_PHYSMEM_PERCENT)/100, 212 11007 Lori SMALLEST_POSSIBLE_MAX_DDT_MB<<20); 213 11007 Lori 214 11007 Lori numbuckets = ddt.max_ddt_size/(sizeof (dedup_entry_t)); 215 11007 Lori 216 11007 Lori /* 217 11007 Lori * numbuckets must be a power of 2. Increase number to 218 11007 Lori * a power of 2 if necessary. 219 11007 Lori */ 220 11007 Lori if (!ISP2(numbuckets)) 221 11007 Lori numbuckets = 1 << high_order_bit(numbuckets); 222 11007 Lori 223 11007 Lori ddt.dedup_hash_array = calloc(numbuckets, sizeof (dedup_entry_t *)); 224 11007 Lori ddt.ddecache = umem_cache_create("dde", sizeof (dedup_entry_t), 0, 225 11007 Lori NULL, NULL, NULL, NULL, NULL, 0); 226 11007 Lori ddt.cur_ddt_size = numbuckets * sizeof (dedup_entry_t *); 227 11007 Lori ddt.numhashbits = high_order_bit(numbuckets) - 1; 228 11007 Lori ddt.ddt_full = B_FALSE; 229 11007 Lori 230 11007 Lori /* Initialize the write-by-reference block. */ 231 11007 Lori wbr_drr.drr_type = DRR_WRITE_BYREF; 232 11007 Lori wbr_drr.drr_payloadlen = 0; 233 11007 Lori 234 11007 Lori outfd = dda->outputfd; 235 11007 Lori ofp = fdopen(dda->inputfd, "r"); 236 11007 Lori while (ssread(drr, sizeof (dmu_replay_record_t), ofp) != 0) { 237 11007 Lori 238 11007 Lori switch (drr->drr_type) { 239 11007 Lori case DRR_BEGIN: 240 11007 Lori { 241 11007 Lori int fflags; 242 11007 Lori ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0); 243 11007 Lori 244 11007 Lori /* set the DEDUP feature flag for this stream */ 245 11007 Lori fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); 246 11007 Lori fflags |= DMU_BACKUP_FEATURE_DEDUP; 247 11007 Lori DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags); 248 11007 Lori 249 11007 Lori if (cksum_and_write(drr, sizeof (dmu_replay_record_t), 250 11007 Lori &stream_cksum, outfd) == -1) 251 11007 Lori goto out; 252 11007 Lori if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == 253 11007 Lori DMU_COMPOUNDSTREAM && drr->drr_payloadlen != 0) { 254 11007 Lori int sz = drr->drr_payloadlen; 255 11007 Lori 256 11007 Lori if (sz > 1<<20) { 257 11007 Lori free(buf); 258 11007 Lori buf = malloc(sz); 259 11007 Lori } 260 11007 Lori (void) ssread(buf, sz, ofp); 261 11007 Lori if (ferror(stdin)) 262 11007 Lori perror("fread"); 263 11007 Lori if (cksum_and_write(buf, sz, &stream_cksum, 264 11007 Lori outfd) == -1) 265 11007 Lori goto out; 266 11007 Lori } 267 11007 Lori break; 268 11007 Lori } 269 11007 Lori 270 11007 Lori case DRR_END: 271 11007 Lori { 272 11007 Lori /* use the recalculated checksum */ 273 11007 Lori ZIO_SET_CHECKSUM(&drre->drr_checksum, 274 11007 Lori stream_cksum.zc_word[0], stream_cksum.zc_word[1], 275 11007 Lori stream_cksum.zc_word[2], stream_cksum.zc_word[3]); 276 11007 Lori if ((write(outfd, drr, 277 11007 Lori sizeof (dmu_replay_record_t))) == -1) 278 11007 Lori goto out; 279 11007 Lori break; 280 11007 Lori } 281 11007 Lori 282 11007 Lori case DRR_OBJECT: 283 11007 Lori { 284 11007 Lori if (cksum_and_write(drr, sizeof (dmu_replay_record_t), 285 11007 Lori &stream_cksum, outfd) == -1) 286 11007 Lori goto out; 287 11007 Lori if (drro->drr_bonuslen > 0) { 288 11007 Lori (void) ssread(buf, 289 11007 Lori P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8), 290 11007 Lori ofp); 291 11007 Lori if (cksum_and_write(buf, 292 11007 Lori P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8), 293 11007 Lori &stream_cksum, outfd) == -1) 294 11007 Lori goto out; 295 11007 Lori } 296 11007 Lori break; 297 11007 Lori } 298 11007 Lori 299 11007 Lori case DRR_FREEOBJECTS: 300 11007 Lori { 301 11007 Lori if (cksum_and_write(drr, sizeof (dmu_replay_record_t), 302 11007 Lori &stream_cksum, outfd) == -1) 303 11007 Lori goto out; 304 11007 Lori break; 305 11007 Lori } 306 11007 Lori 307 11007 Lori case DRR_WRITE: 308 11007 Lori { 309 11007 Lori dataref_t dataref; 310 11007 Lori 311 11007 Lori (void) ssread(buf, drrw->drr_length, ofp); 312 11007 Lori /* 313 11007 Lori * If the block doesn't already have a dedup 314 11007 Lori * checksum, calculate one. 315 11007 Lori */ 316 11007 Lori if (ZIO_CHECKSUM_EQUAL(drrw->drr_blkcksum, 317 11007 Lori zero_cksum)) { 318 11007 Lori SHA256_CTX ctx; 319 11007 Lori zio_cksum_t tmpsha256; 320 11007 Lori 321 11007 Lori SHA256Init(&ctx); 322 11007 Lori SHA256Update(&ctx, buf, drrw->drr_length); 323 11007 Lori SHA256Final(&tmpsha256, &ctx); 324 11007 Lori drrw->drr_blkcksum.zc_word[0] = 325 11007 Lori BE_64(tmpsha256.zc_word[0]); 326 11007 Lori drrw->drr_blkcksum.zc_word[1] = 327 11007 Lori BE_64(tmpsha256.zc_word[1]); 328 11007 Lori drrw->drr_blkcksum.zc_word[2] = 329 11007 Lori BE_64(tmpsha256.zc_word[2]); 330 11007 Lori drrw->drr_blkcksum.zc_word[3] = 331 11007 Lori BE_64(tmpsha256.zc_word[3]); 332 11007 Lori } 333 11007 Lori 334 11007 Lori dataref.ref_guid = drrw->drr_toguid; 335 11007 Lori dataref.ref_object = drrw->drr_object; 336 11007 Lori dataref.ref_offset = drrw->drr_offset; 337 11007 Lori 338 11007 Lori if (ddt_update(dda->dedup_hdl, &ddt, 339 11007 Lori &drrw->drr_blkcksum, &dataref)) { 340 11007 Lori /* block already present in stream */ 341 11007 Lori wbr_drrr->drr_object = drrw->drr_object; 342 11007 Lori wbr_drrr->drr_offset = drrw->drr_offset; 343 11007 Lori wbr_drrr->drr_length = drrw->drr_length; 344 11007 Lori wbr_drrr->drr_toguid = drrw->drr_toguid; 345 11007 Lori wbr_drrr->drr_refguid = dataref.ref_guid; 346 11007 Lori wbr_drrr->drr_refobject = 347 11007 Lori dataref.ref_object; 348 11007 Lori wbr_drrr->drr_refoffset = 349 11007 Lori dataref.ref_offset; 350 11007 Lori 351 11007 Lori wbr_drrr->drr_blkcksum = drrw->drr_blkcksum; 352 11007 Lori 353 11007 Lori if (cksum_and_write(&wbr_drr, 354 11007 Lori sizeof (dmu_replay_record_t), &stream_cksum, 355 11007 Lori outfd) == -1) 356 11007 Lori goto out; 357 11007 Lori } else { 358 11007 Lori /* block not previously seen */ 359 11007 Lori if (cksum_and_write(drr, 360 11007 Lori sizeof (dmu_replay_record_t), &stream_cksum, 361 11007 Lori outfd) == -1) 362 11007 Lori goto out; 363 11007 Lori if (cksum_and_write(buf, 364 11007 Lori drrw->drr_length, 365 11007 Lori &stream_cksum, outfd) == -1) 366 11007 Lori goto out; 367 11007 Lori } 368 11007 Lori break; 369 11007 Lori } 370 11007 Lori 371 11007 Lori case DRR_FREE: 372 11007 Lori { 373 11007 Lori if (cksum_and_write(drr, sizeof (dmu_replay_record_t), 374 11007 Lori &stream_cksum, outfd) == -1) 375 11007 Lori goto out; 376 11007 Lori break; 377 11007 Lori } 378 11007 Lori 379 11007 Lori default: 380 11007 Lori (void) printf("INVALID record type 0x%x\n", 381 11007 Lori drr->drr_type); 382 11007 Lori /* should never happen, so assert */ 383 11007 Lori assert(B_FALSE); 384 11007 Lori } 385 11007 Lori } 386 11007 Lori out: 387 11007 Lori umem_cache_destroy(ddt.ddecache); 388 11007 Lori free(ddt.dedup_hash_array); 389 11007 Lori free(buf); 390 11007 Lori (void) fclose(ofp); 391 11007 Lori 392 11007 Lori return (NULL); 393 11007 Lori } 394 5367 ahrens 395 5367 ahrens /* 396 5367 ahrens * Routines for dealing with the AVL tree of fs-nvlists 397 5367 ahrens */ 398 5367 ahrens typedef struct fsavl_node { 399 5367 ahrens avl_node_t fn_node; 400 5367 ahrens nvlist_t *fn_nvfs; 401 5367 ahrens char *fn_snapname; 402 5367 ahrens uint64_t fn_guid; 403 5367 ahrens } fsavl_node_t; 404 5367 ahrens 405 5367 ahrens static int 406 5367 ahrens fsavl_compare(const void *arg1, const void *arg2) 407 5367 ahrens { 408 5367 ahrens const fsavl_node_t *fn1 = arg1; 409 5367 ahrens const fsavl_node_t *fn2 = arg2; 410 5367 ahrens 411 5367 ahrens if (fn1->fn_guid > fn2->fn_guid) 412 5367 ahrens return (+1); 413 5367 ahrens else if (fn1->fn_guid < fn2->fn_guid) 414 5367 ahrens return (-1); 415 5367 ahrens else 416 5367 ahrens return (0); 417 5367 ahrens } 418 5367 ahrens 419 5367 ahrens /* 420 5367 ahrens * Given the GUID of a snapshot, find its containing filesystem and 421 5367 ahrens * (optionally) name. 422 5367 ahrens */ 423 5367 ahrens static nvlist_t * 424 5367 ahrens fsavl_find(avl_tree_t *avl, uint64_t snapguid, char **snapname) 425 5367 ahrens { 426 5367 ahrens fsavl_node_t fn_find; 427 5367 ahrens fsavl_node_t *fn; 428 5367 ahrens 429 5367 ahrens fn_find.fn_guid = snapguid; 430 5367 ahrens 431 5367 ahrens fn = avl_find(avl, &fn_find, NULL); 432 5367 ahrens if (fn) { 433 5367 ahrens if (snapname) 434 5367 ahrens *snapname = fn->fn_snapname; 435 5367 ahrens return (fn->fn_nvfs); 436 5367 ahrens } 437 5367 ahrens return (NULL); 438 5367 ahrens } 439 5367 ahrens 440 5896 ahl static void 441 5896 ahl fsavl_destroy(avl_tree_t *avl) 442 5896 ahl { 443 5896 ahl fsavl_node_t *fn; 444 5896 ahl void *cookie; 445 5896 ahl 446 5896 ahl if (avl == NULL) 447 5896 ahl return; 448 5896 ahl 449 5896 ahl cookie = NULL; 450 5896 ahl while ((fn = avl_destroy_nodes(avl, &cookie)) != NULL) 451 5896 ahl free(fn); 452 5896 ahl avl_destroy(avl); 453 5896 ahl free(avl); 454 5896 ahl } 455 5896 ahl 456 10200 Lori /* 457 10200 Lori * Given an nvlist, produce an avl tree of snapshots, ordered by guid 458 10200 Lori */ 459 5367 ahrens static avl_tree_t * 460 5367 ahrens fsavl_create(nvlist_t *fss) 461 5367 ahrens { 462 5367 ahrens avl_tree_t *fsavl; 463 5367 ahrens nvpair_t *fselem = NULL; 464 5367 ahrens 465 5896 ahl if ((fsavl = malloc(sizeof (avl_tree_t))) == NULL) 466 5896 ahl return (NULL); 467 5896 ahl 468 5367 ahrens avl_create(fsavl, fsavl_compare, sizeof (fsavl_node_t), 469 5367 ahrens offsetof(fsavl_node_t, fn_node)); 470 5367 ahrens 471 5367 ahrens while ((fselem = nvlist_next_nvpair(fss, fselem)) != NULL) { 472 5367 ahrens nvlist_t *nvfs, *snaps; 473 5367 ahrens nvpair_t *snapelem = NULL; 474 5367 ahrens 475 5367 ahrens VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs)); 476 5367 ahrens VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps)); 477 5367 ahrens 478 5367 ahrens while ((snapelem = 479 5367 ahrens nvlist_next_nvpair(snaps, snapelem)) != NULL) { 480 5367 ahrens fsavl_node_t *fn; 481 5367 ahrens uint64_t guid; 482 5367 ahrens 483 5367 ahrens VERIFY(0 == nvpair_value_uint64(snapelem, &guid)); 484 5896 ahl if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) { 485 5896 ahl fsavl_destroy(fsavl); 486 5896 ahl return (NULL); 487 5896 ahl } 488 5367 ahrens fn->fn_nvfs = nvfs; 489 5367 ahrens fn->fn_snapname = nvpair_name(snapelem); 490 5367 ahrens fn->fn_guid = guid; 491 5367 ahrens 492 5367 ahrens /* 493 5367 ahrens * Note: if there are multiple snaps with the 494 5367 ahrens * same GUID, we ignore all but one. 495 5367 ahrens */ 496 5367 ahrens if (avl_find(fsavl, fn, NULL) == NULL) 497 5367 ahrens avl_add(fsavl, fn); 498 5367 ahrens else 499 5367 ahrens free(fn); 500 5367 ahrens } 501 5367 ahrens } 502 5367 ahrens 503 5367 ahrens return (fsavl); 504 5367 ahrens } 505 5367 ahrens 506 5367 ahrens /* 507 5367 ahrens * Routines for dealing with the giant nvlist of fs-nvlists, etc. 508 5367 ahrens */ 509 5367 ahrens typedef struct send_data { 510 5367 ahrens uint64_t parent_fromsnap_guid; 511 5367 ahrens nvlist_t *parent_snaps; 512 5367 ahrens nvlist_t *fss; 513 7265 ahrens nvlist_t *snapprops; 514 5367 ahrens const char *fromsnap; 515 5367 ahrens const char *tosnap; 516 11022 Tom boolean_t recursive; 517 5367 ahrens 518 5367 ahrens /* 519 5367 ahrens * The header nvlist is of the following format: 520 5367 ahrens * { 521 5367 ahrens * "tosnap" -> string 522 5367 ahrens * "fromsnap" -> string (if incremental) 523 5367 ahrens * "fss" -> { 524 5367 ahrens * id -> { 525 5367 ahrens * 526 5367 ahrens * "name" -> string (full name; for debugging) 527 5367 ahrens * "parentfromsnap" -> number (guid of fromsnap in parent) 528 5367 ahrens * 529 5367 ahrens * "props" -> { name -> value (only if set here) } 530 5367 ahrens * "snaps" -> { name (lastname) -> number (guid) } 531 7265 ahrens * "snapprops" -> { name (lastname) -> { name -> value } } 532 5367 ahrens * 533 5367 ahrens * "origin" -> number (guid) (if clone) 534 5367 ahrens * "sent" -> boolean (not on-disk) 535 5367 ahrens * } 536 5367 ahrens * } 537 5367 ahrens * } 538 5367 ahrens * 539 5367 ahrens */ 540 5367 ahrens } send_data_t; 541 5367 ahrens 542 7265 ahrens static void send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv); 543 7265 ahrens 544 5367 ahrens static int 545 5367 ahrens send_iterate_snap(zfs_handle_t *zhp, void *arg) 546 5367 ahrens { 547 5367 ahrens send_data_t *sd = arg; 548 5367 ahrens uint64_t guid = zhp->zfs_dmustats.dds_guid; 549 5367 ahrens char *snapname; 550 7265 ahrens nvlist_t *nv; 551 5367 ahrens 552 5367 ahrens snapname = strrchr(zhp->zfs_name, '@')+1; 553 5367 ahrens 554 5367 ahrens VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid)); 555 5367 ahrens /* 556 5367 ahrens * NB: if there is no fromsnap here (it's a newly created fs in 557 5367 ahrens * an incremental replication), we will substitute the tosnap. 558 5367 ahrens */ 559 5367 ahrens if ((sd->fromsnap && strcmp(snapname, sd->fromsnap) == 0) || 560 5367 ahrens (sd->parent_fromsnap_guid == 0 && sd->tosnap && 561 5367 ahrens strcmp(snapname, sd->tosnap) == 0)) { 562 5367 ahrens sd->parent_fromsnap_guid = guid; 563 5367 ahrens } 564 7265 ahrens 565 7265 ahrens VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0)); 566 7265 ahrens send_iterate_prop(zhp, nv); 567 7265 ahrens VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv)); 568 7265 ahrens nvlist_free(nv); 569 5367 ahrens 570 5367 ahrens zfs_close(zhp); 571 5367 ahrens return (0); 572 5367 ahrens } 573 5367 ahrens 574 5367 ahrens static void 575 5367 ahrens send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv) 576 5367 ahrens { 577 5367 ahrens nvpair_t *elem = NULL; 578 5367 ahrens 579 5367 ahrens while ((elem = nvlist_next_nvpair(zhp->zfs_props, elem)) != NULL) { 580 5367 ahrens char *propname = nvpair_name(elem); 581 5367 ahrens zfs_prop_t prop = zfs_name_to_prop(propname); 582 5367 ahrens nvlist_t *propnv; 583 9396 Matthew 584 10960 Eric if (!zfs_prop_user(propname)) { 585 10960 Eric /* 586 10960 Eric * Realistically, this should never happen. However, 587 10960 Eric * we want the ability to add DSL properties without 588 10960 Eric * needing to make incompatible version changes. We 589 10960 Eric * need to ignore unknown properties to allow older 590 10960 Eric * software to still send datasets containing these 591 10960 Eric * properties, with the unknown properties elided. 592 10960 Eric */ 593 10960 Eric if (prop == ZPROP_INVAL) 594 10960 Eric continue; 595 5367 ahrens 596 10960 Eric if (zfs_prop_readonly(prop)) 597 10960 Eric continue; 598 10960 Eric } 599 5367 ahrens 600 5367 ahrens verify(nvpair_value_nvlist(elem, &propnv) == 0); 601 10195 Sanjeev if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION || 602 10195 Sanjeev prop == ZFS_PROP_REFQUOTA || 603 10195 Sanjeev prop == ZFS_PROP_REFRESERVATION) { 604 11022 Tom char *source; 605 5367 ahrens uint64_t value; 606 5367 ahrens verify(nvlist_lookup_uint64(propnv, 607 5367 ahrens ZPROP_VALUE, &value) == 0); 608 7265 ahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) 609 7265 ahrens continue; 610 11022 Tom /* 611 11022 Tom * May have no source before SPA_VERSION_RECVD_PROPS, 612 11022 Tom * but is still modifiable. 613 11022 Tom */ 614 11022 Tom if (nvlist_lookup_string(propnv, 615 11022 Tom ZPROP_SOURCE, &source) == 0) { 616 11022 Tom if ((strcmp(source, zhp->zfs_name) != 0) && 617 11022 Tom (strcmp(source, 618 11022 Tom ZPROP_SOURCE_VAL_RECVD) != 0)) 619 11022 Tom continue; 620 11022 Tom } 621 5367 ahrens } else { 622 5367 ahrens char *source; 623 5367 ahrens if (nvlist_lookup_string(propnv, 624 5367 ahrens ZPROP_SOURCE, &source) != 0) 625 5367 ahrens continue; 626 11022 Tom if ((strcmp(source, zhp->zfs_name) != 0) && 627 11022 Tom (strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0)) 628 5367 ahrens continue; 629 5367 ahrens } 630 5367 ahrens 631 5367 ahrens if (zfs_prop_user(propname) || 632 5367 ahrens zfs_prop_get_type(prop) == PROP_TYPE_STRING) { 633 5367 ahrens char *value; 634 5367 ahrens verify(nvlist_lookup_string(propnv, 635 5367 ahrens ZPROP_VALUE, &value) == 0); 636 5367 ahrens VERIFY(0 == nvlist_add_string(nv, propname, value)); 637 5367 ahrens } else { 638 5367 ahrens uint64_t value; 639 5367 ahrens verify(nvlist_lookup_uint64(propnv, 640 5367 ahrens ZPROP_VALUE, &value) == 0); 641 5367 ahrens VERIFY(0 == nvlist_add_uint64(nv, propname, value)); 642 5367 ahrens } 643 5367 ahrens } 644 5367 ahrens } 645 5367 ahrens 646 10200 Lori /* 647 10200 Lori * recursively generate nvlists describing datasets. See comment 648 10200 Lori * for the data structure send_data_t above for description of contents 649 10200 Lori * of the nvlist. 650 10200 Lori */ 651 5367 ahrens static int 652 5367 ahrens send_iterate_fs(zfs_handle_t *zhp, void *arg) 653 5367 ahrens { 654 5367 ahrens send_data_t *sd = arg; 655 5367 ahrens nvlist_t *nvfs, *nv; 656 11022 Tom int rv = 0; 657 5367 ahrens uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid; 658 5367 ahrens uint64_t guid = zhp->zfs_dmustats.dds_guid; 659 5367 ahrens char guidstring[64]; 660 5367 ahrens 661 5367 ahrens VERIFY(0 == nvlist_alloc(&nvfs, NV_UNIQUE_NAME, 0)); 662 5367 ahrens VERIFY(0 == nvlist_add_string(nvfs, "name", zhp->zfs_name)); 663 5367 ahrens VERIFY(0 == nvlist_add_uint64(nvfs, "parentfromsnap", 664 5367 ahrens sd->parent_fromsnap_guid)); 665 5367 ahrens 666 5367 ahrens if (zhp->zfs_dmustats.dds_origin[0]) { 667 5367 ahrens zfs_handle_t *origin = zfs_open(zhp->zfs_hdl, 668 5367 ahrens zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT); 669 5367 ahrens if (origin == NULL) 670 5367 ahrens return (-1); 671 5367 ahrens VERIFY(0 == nvlist_add_uint64(nvfs, "origin", 672 5367 ahrens origin->zfs_dmustats.dds_guid)); 673 5367 ahrens } 674 5367 ahrens 675 5367 ahrens /* iterate over props */ 676 5367 ahrens VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0)); 677 5367 ahrens send_iterate_prop(zhp, nv); 678 5367 ahrens VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv)); 679 5367 ahrens nvlist_free(nv); 680 5367 ahrens 681 5367 ahrens /* iterate over snaps, and set sd->parent_fromsnap_guid */ 682 5367 ahrens sd->parent_fromsnap_guid = 0; 683 5367 ahrens VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0)); 684 7265 ahrens VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0)); 685 5367 ahrens (void) zfs_iter_snapshots(zhp, send_iterate_snap, sd); 686 5367 ahrens VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps)); 687 7265 ahrens VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops)); 688 5367 ahrens nvlist_free(sd->parent_snaps); 689 7265 ahrens nvlist_free(sd->snapprops); 690 5367 ahrens 691 5367 ahrens /* add this fs to nvlist */ 692 5367 ahrens (void) snprintf(guidstring, sizeof (guidstring), 693 5367 ahrens "0x%llx", (longlong_t)guid); 694 5367 ahrens VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs)); 695 5367 ahrens nvlist_free(nvfs); 696 5367 ahrens 697 5367 ahrens /* iterate over children */ 698 11022 Tom if (sd->recursive) 699 11022 Tom rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd); 700 5367 ahrens 701 5367 ahrens sd->parent_fromsnap_guid = parent_fromsnap_guid_save; 702 5367 ahrens 703 5367 ahrens zfs_close(zhp); 704 5367 ahrens return (rv); 705 5367 ahrens } 706 5367 ahrens 707 5367 ahrens static int 708 5367 ahrens gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap, 709 11022 Tom const char *tosnap, boolean_t recursive, nvlist_t **nvlp, avl_tree_t **avlp) 710 5367 ahrens { 711 5367 ahrens zfs_handle_t *zhp; 712 5367 ahrens send_data_t sd = { 0 }; 713 5367 ahrens int error; 714 5367 ahrens 715 5367 ahrens zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 716 5367 ahrens if (zhp == NULL) 717 5367 ahrens return (EZFS_BADTYPE); 718 5367 ahrens 719 5367 ahrens VERIFY(0 == nvlist_alloc(&sd.fss, NV_UNIQUE_NAME, 0)); 720 5367 ahrens sd.fromsnap = fromsnap; 721 5367 ahrens sd.tosnap = tosnap; 722 11022 Tom sd.recursive = recursive; 723 5896 ahl 724 5896 ahl if ((error = send_iterate_fs(zhp, &sd)) != 0) { 725 5896 ahl nvlist_free(sd.fss); 726 5896 ahl if (avlp != NULL) 727 5896 ahl *avlp = NULL; 728 5896 ahl *nvlp = NULL; 729 5896 ahl return (error); 730 5896 ahl } 731 5896 ahl 732 5896 ahl if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) { 733 5896 ahl nvlist_free(sd.fss); 734 5896 ahl *nvlp = NULL; 735 5896 ahl return (EZFS_NOMEM); 736 5896 ahl } 737 5367 ahrens 738 5367 ahrens *nvlp = sd.fss; 739 5896 ahl return (0); 740 5367 ahrens } 741 5367 ahrens 742 5367 ahrens /* 743 5367 ahrens * Routines for dealing with the sorted snapshot functionality 744 5367 ahrens */ 745 5367 ahrens typedef struct zfs_node { 746 5367 ahrens zfs_handle_t *zn_handle; 747 5367 ahrens avl_node_t zn_avlnode; 748 5367 ahrens } zfs_node_t; 749 5367 ahrens 750 5367 ahrens static int 751 5367 ahrens zfs_sort_snaps(zfs_handle_t *zhp, void *data) 752 5367 ahrens { 753 5367 ahrens avl_tree_t *avl = data; 754 5367 ahrens zfs_node_t *node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t)); 755 5367 ahrens 756 5367 ahrens node->zn_handle = zhp; 757 5367 ahrens avl_add(avl, node); 758 5367 ahrens return (0); 759 5367 ahrens } 760 5367 ahrens 761 5367 ahrens /* ARGSUSED */ 762 5367 ahrens static int 763 5367 ahrens zfs_snapshot_compare(const void *larg, const void *rarg) 764 5367 ahrens { 765 5367 ahrens zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle; 766 5367 ahrens zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle; 767 5367 ahrens uint64_t lcreate, rcreate; 768 5367 ahrens 769 5367 ahrens /* 770 5367 ahrens * Sort them according to creation time. We use the hidden 771 5367 ahrens * CREATETXG property to get an absolute ordering of snapshots. 772 5367 ahrens */ 773 5367 ahrens lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG); 774 5367 ahrens rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG); 775 5367 ahrens 776 5367 ahrens if (lcreate < rcreate) 777 5367 ahrens return (-1); 778 5367 ahrens else if (lcreate > rcreate) 779 5367 ahrens return (+1); 780 5367 ahrens else 781 5367 ahrens return (0); 782 5367 ahrens } 783 5367 ahrens 784 10342 chris int 785 5367 ahrens zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data) 786 5367 ahrens { 787 5367 ahrens int ret = 0; 788 5367 ahrens zfs_node_t *node; 789 5367 ahrens avl_tree_t avl; 790 5367 ahrens void *cookie = NULL; 791 5367 ahrens 792 5367 ahrens avl_create(&avl, zfs_snapshot_compare, 793 5367 ahrens sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode)); 794 5367 ahrens 795 5367 ahrens ret = zfs_iter_snapshots(zhp, zfs_sort_snaps, &avl); 796 5367 ahrens 797 5367 ahrens for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node)) 798 5367 ahrens ret |= callback(node->zn_handle, data); 799 5367 ahrens 800 5367 ahrens while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL) 801 5367 ahrens free(node); 802 5367 ahrens 803 5367 ahrens avl_destroy(&avl); 804 5367 ahrens 805 5367 ahrens return (ret); 806 5367 ahrens } 807 5367 ahrens 808 5367 ahrens /* 809 5367 ahrens * Routines specific to "zfs send" 810 5367 ahrens */ 811 5367 ahrens typedef struct send_dump_data { 812 5367 ahrens /* these are all just the short snapname (the part after the @) */ 813 5367 ahrens const char *fromsnap; 814 5367 ahrens const char *tosnap; 815 11007 Lori char prevsnap[ZFS_MAXNAMELEN]; 816 5367 ahrens boolean_t seenfrom, seento, replicate, doall, fromorigin; 817 5367 ahrens boolean_t verbose; 818 5367 ahrens int outfd; 819 5367 ahrens boolean_t err; 820 5367 ahrens nvlist_t *fss; 821 5367 ahrens avl_tree_t *fsavl; 822 11007 Lori snapfilter_cb_t *filter_cb; 823 11007 Lori void *filter_cb_arg; 824 5367 ahrens } send_dump_data_t; 825 5367 ahrens 826 5367 ahrens /* 827 5367 ahrens * Dumps a backup of the given snapshot (incremental from fromsnap if it's not 828 5367 ahrens * NULL) to the file descriptor specified by outfd. 829 5367 ahrens */ 830 5367 ahrens static int 831 5367 ahrens dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, boolean_t fromorigin, 832 5367 ahrens int outfd) 833 5367 ahrens { 834 5367 ahrens zfs_cmd_t zc = { 0 }; 835 5367 ahrens libzfs_handle_t *hdl = zhp->zfs_hdl; 836 5367 ahrens 837 5367 ahrens assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT); 838 5367 ahrens assert(fromsnap == NULL || fromsnap[0] == '\0' || !fromorigin); 839 5367 ahrens 840 5367 ahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 841 5367 ahrens if (fromsnap) 842 5765 ek110237 (void) strlcpy(zc.zc_value, fromsnap, sizeof (zc.zc_value)); 843 5367 ahrens zc.zc_cookie = outfd; 844 5367 ahrens zc.zc_obj = fromorigin; 845 5367 ahrens 846 5367 ahrens if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SEND, &zc) != 0) { 847 5367 ahrens char errbuf[1024]; 848 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 849 5367 ahrens "warning: cannot send '%s'"), zhp->zfs_name); 850 5367 ahrens 851 5367 ahrens switch (errno) { 852 5367 ahrens 853 5367 ahrens case EXDEV: 854 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 855 5367 ahrens "not an earlier snapshot from the same fs")); 856 5367 ahrens return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf)); 857 5367 ahrens 858 5367 ahrens case ENOENT: 859 5367 ahrens if (zfs_dataset_exists(hdl, zc.zc_name, 860 5367 ahrens ZFS_TYPE_SNAPSHOT)) { 861 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 862 5367 ahrens "incremental source (@%s) does not exist"), 863 5367 ahrens zc.zc_value); 864 5367 ahrens } 865 5367 ahrens return (zfs_error(hdl, EZFS_NOENT, errbuf)); 866 5367 ahrens 867 5367 ahrens case EDQUOT: 868 5367 ahrens case EFBIG: 869 5367 ahrens case EIO: 870 5367 ahrens case ENOLINK: 871 5367 ahrens case ENOSPC: 872 5367 ahrens case ENOSTR: 873 5367 ahrens case ENXIO: 874 5367 ahrens case EPIPE: 875 5367 ahrens case ERANGE: 876 5367 ahrens case EFAULT: 877 5367 ahrens case EROFS: 878 5367 ahrens zfs_error_aux(hdl, strerror(errno)); 879 5367 ahrens return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); 880 5367 ahrens 881 5367 ahrens default: 882 5367 ahrens return (zfs_standard_error(hdl, errno, errbuf)); 883 5367 ahrens } 884 5367 ahrens } 885 5367 ahrens 886 5367 ahrens return (0); 887 5367 ahrens } 888 5367 ahrens 889 5367 ahrens static int 890 5367 ahrens dump_snapshot(zfs_handle_t *zhp, void *arg) 891 5367 ahrens { 892 5367 ahrens send_dump_data_t *sdd = arg; 893 5367 ahrens const char *thissnap; 894 5367 ahrens int err; 895 5367 ahrens 896 5367 ahrens thissnap = strchr(zhp->zfs_name, '@') + 1; 897 5367 ahrens 898 5367 ahrens if (sdd->fromsnap && !sdd->seenfrom && 899 5367 ahrens strcmp(sdd->fromsnap, thissnap) == 0) { 900 5367 ahrens sdd->seenfrom = B_TRUE; 901 11007 Lori (void) strcpy(sdd->prevsnap, thissnap); 902 5367 ahrens zfs_close(zhp); 903 5367 ahrens return (0); 904 5367 ahrens } 905 5367 ahrens 906 5367 ahrens if (sdd->seento || !sdd->seenfrom) { 907 5367 ahrens zfs_close(zhp); 908 5367 ahrens return (0); 909 5367 ahrens } 910 5367 ahrens 911 11007 Lori if (strcmp(sdd->tosnap, thissnap) == 0) 912 11007 Lori sdd->seento = B_TRUE; 913 11007 Lori 914 11007 Lori /* 915 11007 Lori * If a filter function exists, call it to determine whether 916 11007 Lori * this snapshot will be sent. 917 11007 Lori */ 918 11007 Lori if (sdd->filter_cb != NULL && 919 11007 Lori sdd->filter_cb(zhp, sdd->filter_cb_arg) == B_FALSE) { 920 11007 Lori /* 921 11007 Lori * This snapshot is filtered out. Don't send it, and don't 922 11007 Lori * set prevsnap, so it will be as if this snapshot didn't 923 11007 Lori * exist, and the next accepted snapshot will be sent as 924 11007 Lori * an incremental from the last accepted one, or as the 925 11007 Lori * first (and full) snapshot in the case of a replication, 926 11007 Lori * non-incremental send. 927 11007 Lori */ 928 11007 Lori zfs_close(zhp); 929 11007 Lori return (0); 930 11007 Lori } 931 11007 Lori 932 5367 ahrens /* send it */ 933 5367 ahrens if (sdd->verbose) { 934 5367 ahrens (void) fprintf(stderr, "sending from @%s to %s\n", 935 11007 Lori sdd->prevsnap, zhp->zfs_name); 936 5367 ahrens } 937 5367 ahrens 938 11007 Lori err = dump_ioctl(zhp, sdd->prevsnap, 939 11007 Lori sdd->prevsnap[0] == '\0' && (sdd->fromorigin || sdd->replicate), 940 5367 ahrens sdd->outfd); 941 5367 ahrens 942 11007 Lori (void) strcpy(sdd->prevsnap, thissnap); 943 5367 ahrens zfs_close(zhp); 944 5367 ahrens return (err); 945 5367 ahrens } 946 5367 ahrens 947 5367 ahrens static int 948 5367 ahrens dump_filesystem(zfs_handle_t *zhp, void *arg) 949 5367 ahrens { 950 5367 ahrens int rv = 0; 951 5367 ahrens send_dump_data_t *sdd = arg; 952 5367 ahrens boolean_t missingfrom = B_FALSE; 953 5367 ahrens zfs_cmd_t zc = { 0 }; 954 5367 ahrens 955 5367 ahrens (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s", 956 5367 ahrens zhp->zfs_name, sdd->tosnap); 957 5367 ahrens if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) { 958 5367 ahrens (void) fprintf(stderr, "WARNING: " 959 5367 ahrens "could not send %s@%s: does not exist\n", 960 5367 ahrens zhp->zfs_name, sdd->tosnap); 961 5367 ahrens sdd->err = B_TRUE; 962 5367 ahrens return (0); 963 5367 ahrens } 964 5367 ahrens 965 5367 ahrens if (sdd->replicate && sdd->fromsnap) { 966 5367 ahrens /* 967 5367 ahrens * If this fs does not have fromsnap, and we're doing 968 5367 ahrens * recursive, we need to send a full stream from the 969 5367 ahrens * beginning (or an incremental from the origin if this 970 5367 ahrens * is a clone). If we're doing non-recursive, then let 971 5367 ahrens * them get the error. 972 5367 ahrens */ 973 5367 ahrens (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s", 974 5367 ahrens zhp->zfs_name, sdd->fromsnap); 975 5367 ahrens if (ioctl(zhp->zfs_hdl->libzfs_fd, 976 5367 ahrens ZFS_IOC_OBJSET_STATS, &zc) != 0) { 977 5367 ahrens missingfrom = B_TRUE; 978 5367 ahrens } 979 5367 ahrens } 980 5367 ahrens 981 5367 ahrens if (sdd->doall) { 982 11007 Lori sdd->seenfrom = sdd->seento = sdd->prevsnap[0] = 0; 983 5367 ahrens if (sdd->fromsnap == NULL || missingfrom) 984 5367 ahrens sdd->seenfrom = B_TRUE; 985 5367 ahrens 986 5367 ahrens rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg); 987 5367 ahrens if (!sdd->seenfrom) { 988 5367 ahrens (void) fprintf(stderr, 989 5367 ahrens "WARNING: could not send %s@%s:\n" 990 5367 ahrens "incremental source (%s@%s) does not exist\n", 991 5367 ahrens zhp->zfs_name, sdd->tosnap, 992 5367 ahrens zhp->zfs_name, sdd->fromsnap); 993 5367 ahrens sdd->err = B_TRUE; 994 5367 ahrens } else if (!sdd->seento) { 995 9396 Matthew if (sdd->fromsnap) { 996 9396 Matthew (void) fprintf(stderr, 997 9396 Matthew "WARNING: could not send %s@%s:\n" 998 9396 Matthew "incremental source (%s@%s) " 999 9396 Matthew "is not earlier than it\n", 1000 9396 Matthew zhp->zfs_name, sdd->tosnap, 1001 9396 Matthew zhp->zfs_name, sdd->fromsnap); 1002 9396 Matthew } else { 1003 9396 Matthew (void) fprintf(stderr, "WARNING: " 1004 9396 Matthew "could not send %s@%s: does not exist\n", 1005 9396 Matthew zhp->zfs_name, sdd->tosnap); 1006 9396 Matthew } 1007 5367 ahrens sdd->err = B_TRUE; 1008 5367 ahrens } 1009 5367 ahrens } else { 1010 5367 ahrens zfs_handle_t *snapzhp; 1011 5367 ahrens char snapname[ZFS_MAXNAMELEN]; 1012 5367 ahrens 1013 5367 ahrens (void) snprintf(snapname, sizeof (snapname), "%s@%s", 1014 5367 ahrens zfs_get_name(zhp), sdd->tosnap); 1015 5367 ahrens snapzhp = zfs_open(zhp->zfs_hdl, snapname, ZFS_TYPE_SNAPSHOT); 1016 6476 ahl if (snapzhp == NULL) { 1017 6476 ahl rv = -1; 1018 6476 ahl } else { 1019 11007 Lori if (sdd->filter_cb == NULL || 1020 11007 Lori sdd->filter_cb(snapzhp, sdd->filter_cb_arg) == 1021 11007 Lori B_TRUE) { 1022 11007 Lori rv = dump_ioctl(snapzhp, 1023 11007 Lori missingfrom ? NULL : sdd->fromsnap, 1024 11007 Lori sdd->fromorigin || missingfrom, 1025 11007 Lori sdd->outfd); 1026 11007 Lori } 1027 6476 ahl sdd->seento = B_TRUE; 1028 6476 ahl zfs_close(snapzhp); 1029 6476 ahl } 1030 5367 ahrens } 1031 5367 ahrens 1032 5367 ahrens return (rv); 1033 5367 ahrens } 1034 5367 ahrens 1035 5367 ahrens static int 1036 5367 ahrens dump_filesystems(zfs_handle_t *rzhp, void *arg) 1037 5367 ahrens { 1038 5367 ahrens send_dump_data_t *sdd = arg; 1039 5367 ahrens nvpair_t *fspair; 1040 5367 ahrens boolean_t needagain, progress; 1041 5367 ahrens 1042 5367 ahrens if (!sdd->replicate) 1043 5367 ahrens return (dump_filesystem(rzhp, sdd)); 1044 5367 ahrens 1045 5367 ahrens again: 1046 5367 ahrens needagain = progress = B_FALSE; 1047 5367 ahrens for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair; 1048 5367 ahrens fspair = nvlist_next_nvpair(sdd->fss, fspair)) { 1049 5367 ahrens nvlist_t *fslist; 1050 5367 ahrens char *fsname; 1051 5367 ahrens zfs_handle_t *zhp; 1052 5367 ahrens int err; 1053 5367 ahrens uint64_t origin_guid = 0; 1054 5367 ahrens nvlist_t *origin_nv; 1055 5367 ahrens 1056 5367 ahrens VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0); 1057 5367 ahrens if (nvlist_lookup_boolean(fslist, "sent") == 0) 1058 5367 ahrens continue; 1059 5367 ahrens 1060 5367 ahrens VERIFY(nvlist_lookup_string(fslist, "name", &fsname) == 0); 1061 5367 ahrens (void) nvlist_lookup_uint64(fslist, "origin", &origin_guid); 1062 5367 ahrens 1063 5367 ahrens origin_nv = fsavl_find(sdd->fsavl, origin_guid, NULL); 1064 5367 ahrens if (origin_nv && 1065 5367 ahrens nvlist_lookup_boolean(origin_nv, "sent") == ENOENT) { 1066 11022 Tom /* 1067 11022 Tom * origin has not been sent yet; 1068 11022 Tom * skip this clone. 1069 11022 Tom */ 1070 11022 Tom needagain = B_TRUE; 1071 11022 Tom continue; 1072 5367 ahrens } 1073 5367 ahrens 1074 5367 ahrens zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET); 1075 6476 ahl if (zhp == NULL) 1076 6476 ahl return (-1); 1077 5367 ahrens err = dump_filesystem(zhp, sdd); 1078 5367 ahrens VERIFY(nvlist_add_boolean(fslist, "sent") == 0); 1079 5367 ahrens progress = B_TRUE; 1080 5367 ahrens zfs_close(zhp); 1081 5367 ahrens if (err) 1082 5367 ahrens return (err); 1083 5367 ahrens } 1084 5367 ahrens if (needagain) { 1085 5367 ahrens assert(progress); 1086 5367 ahrens goto again; 1087 5367 ahrens } 1088 5367 ahrens return (0); 1089 5367 ahrens } 1090 5367 ahrens 1091 5367 ahrens /* 1092 10200 Lori * Generate a send stream for the dataset identified by the argument zhp. 1093 10200 Lori * 1094 10200 Lori * The content of the send stream is the snapshot identified by 1095 10200 Lori * 'tosnap'. Incremental streams are requested in two ways: 1096 10200 Lori * - from the snapshot identified by "fromsnap" (if non-null) or 1097 10200 Lori * - from the origin of the dataset identified by zhp, which must 1098 10200 Lori * be a clone. In this case, "fromsnap" is null and "fromorigin" 1099 10200 Lori * is TRUE. 1100 10200 Lori * 1101 10200 Lori * The send stream is recursive (i.e. dumps a hierarchy of snapshots) and 1102 11007 Lori * uses a special header (with a hdrtype field of DMU_COMPOUNDSTREAM) 1103 10200 Lori * if "replicate" is set. If "doall" is set, dump all the intermediate 1104 11007 Lori * snapshots. The DMU_COMPOUNDSTREAM header is used in the "doall" 1105 11022 Tom * case too. If "props" is set, send properties. 1106 5367 ahrens */ 1107 5367 ahrens int 1108 5367 ahrens zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, 1109 11007 Lori sendflags_t flags, int outfd, snapfilter_cb_t filter_func, 1110 11007 Lori void *cb_arg) 1111 5367 ahrens { 1112 5367 ahrens char errbuf[1024]; 1113 5367 ahrens send_dump_data_t sdd = { 0 }; 1114 5367 ahrens int err; 1115 5367 ahrens nvlist_t *fss = NULL; 1116 5367 ahrens avl_tree_t *fsavl = NULL; 1117 10342 chris char holdtag[128]; 1118 10342 chris static uint64_t holdseq; 1119 10735 chris int spa_version; 1120 10735 chris boolean_t holdsnaps = B_FALSE; 1121 11007 Lori pthread_t tid; 1122 11007 Lori int pipefd[2]; 1123 11007 Lori dedup_arg_t dda = { 0 }; 1124 11007 Lori int featureflags = 0; 1125 5367 ahrens 1126 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1127 5367 ahrens "cannot send '%s'"), zhp->zfs_name); 1128 5367 ahrens 1129 5367 ahrens if (fromsnap && fromsnap[0] == '\0') { 1130 5367 ahrens zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1131 5367 ahrens "zero-length incremental source")); 1132 5367 ahrens return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf)); 1133 5367 ahrens } 1134 5367 ahrens 1135 10735 chris if (zfs_spa_version(zhp, &spa_version) == 0 && 1136 10735 chris spa_version >= SPA_VERSION_USERREFS) 1137 10735 chris holdsnaps = B_TRUE; 1138 10735 chris 1139 11007 Lori if (flags.dedup) { 1140 11007 Lori featureflags |= DMU_BACKUP_FEATURE_DEDUP; 1141 11007 Lori if (err = pipe(pipefd)) { 1142 11007 Lori zfs_error_aux(zhp->zfs_hdl, strerror(errno)); 1143 11007 Lori return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED, 1144 11007 Lori errbuf)); 1145 11007 Lori } 1146 11007 Lori dda.outputfd = outfd; 1147 11007 Lori dda.inputfd = pipefd[1]; 1148 11007 Lori dda.dedup_hdl = zhp->zfs_hdl; 1149 11007 Lori if (err = pthread_create(&tid, NULL, cksummer, &dda)) { 1150 11007 Lori (void) close(pipefd[0]); 1151 11007 Lori (void) close(pipefd[1]); 1152 11007 Lori zfs_error_aux(zhp->zfs_hdl, strerror(errno)); 1153 11007 Lori return (zfs_error(zhp->zfs_hdl, 1154 11007 Lori EZFS_THREADCREATEFAILED, errbuf)); 1155 11007 Lori } 1156 11007 Lori } 1157 11007 Lori 1158 11022 Tom if (flags.replicate || flags.doall || flags.props) { 1159 5367 ahrens dmu_replay_record_t drr = { 0 }; 1160 5367 ahrens char *packbuf = NULL; 1161 5367 ahrens size_t buflen = 0; 1162 5367 ahrens zio_cksum_t zc = { 0 }; 1163 5367 ahrens 1164 10735 chris if (holdsnaps) { 1165 10735 chris (void) snprintf(holdtag, sizeof (holdtag), 1166 10735 chris ".send-%d-%llu", getpid(), (u_longlong_t)holdseq); 1167 10735 chris ++holdseq; 1168 10735 chris err = zfs_hold_range(zhp, fromsnap, tosnap, 1169 10735 chris holdtag, B_TRUE); 1170 10735 chris if (err) 1171 11007 Lori goto err_out; 1172 10735 chris } 1173 11007 Lori 1174 11022 Tom if (flags.replicate || flags.props) { 1175 5367 ahrens nvlist_t *hdrnv; 1176 5367 ahrens 1177 5367 ahrens VERIFY(0 == nvlist_alloc(&hdrnv, NV_UNIQUE_NAME, 0)); 1178 5367 ahrens if (fromsnap) { 1179 5367 ahrens VERIFY(0 == nvlist_add_string(hdrnv, 1180 5367 ahrens "fromsnap", fromsnap)); 1181 5367 ahrens } 1182 5367 ahrens VERIFY(0 == nvlist_add_string(hdrnv, "tosnap", tosnap)); 1183 11022 Tom if (!flags.replicate) { 1184 11022 Tom VERIFY(0 == nvlist_add_boolean(hdrnv, 1185 11022 Tom "not_recursive")); 1186 11022 Tom } 1187 5367 ahrens 1188 5367 ahrens err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name, 1189 11022 Tom fromsnap, tosnap, flags.replicate, &fss, &fsavl); 1190 10342 chris if (err) { 1191 10735 chris if (holdsnaps) { 1192 10735 chris (void) zfs_release_range(zhp, fromsnap, 1193 10735 chris tosnap, holdtag); 1194 10735 chris } 1195 11007 Lori goto err_out; 1196 10342 chris } 1197 5367 ahrens VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss)); 1198 5367 ahrens err = nvlist_pack(hdrnv, &packbuf, &buflen, 1199 5367 ahrens NV_ENCODE_XDR, 0); 1200 5367 ahrens nvlist_free(hdrnv); 1201 5367 ahrens if (err) { 1202 5367 ahrens fsavl_destroy(fsavl); 1203 5367 ahrens nvlist_free(fss); 1204 10735 chris if (holdsnaps) { 1205 10735 chris (void) zfs_release_range(zhp, fromsnap, 1206 10735 chris tosnap, holdtag); 1207 10735 chris } 1208 11007 Lori goto stderr_out; 1209 5367 ahrens } 1210 5367 ahrens } 1211 5367 ahrens 1212 5367 ahrens /* write first begin record */ 1213 5367 ahrens drr.drr_type = DRR_BEGIN; 1214 5367 ahrens drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC; 1215 11007 Lori DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.drr_versioninfo, 1216 11007 Lori DMU_COMPOUNDSTREAM); 1217 11007 Lori DMU_SET_FEATUREFLAGS(drr.drr_u.drr_begin.drr_versioninfo, 1218 11007 Lori featureflags); 1219 5367 ahrens (void) snprintf(drr.drr_u.drr_begin.drr_toname, 1220 5367 ahrens sizeof (drr.drr_u.drr_begin.drr_toname), 1221 5367 ahrens "%s@%s", zhp->zfs_name, tosnap); 1222 5367 ahrens drr.drr_payloadlen = buflen; 1223 11007 Lori err = cksum_and_write(&drr, sizeof (drr), &zc, outfd); 1224 5367 ahrens 1225 5367 ahrens /* write header nvlist */ 1226 11022 Tom if (err != -1 && packbuf != NULL) { 1227 11007 Lori err = cksum_and_write(packbuf, buflen, &zc, outfd); 1228 5367 ahrens } 1229 5367 ahrens free(packbuf); 1230 5367 ahrens if (err == -1) { 1231 5367 ahrens fsavl_destroy(fsavl); 1232 5367 ahrens nvlist_free(fss); 1233 10735 chris if (holdsnaps) { 1234 10735 chris (void) zfs_release_range(zhp, fromsnap, tosnap, 1235 10735 chris holdtag); 1236 10735 chris } 1237 11007 Lori err = errno; 1238 11007 Lori goto stderr_out; 1239 5367 ahrens } 1240 5367 ahrens 1241 5367 ahrens /* write end record */ 1242 5367 ahrens if (err != -1) { 1243 5367 ahrens bzero(&drr, sizeof (drr)); 1244 5367 ahrens drr.drr_type = DRR_END; 1245 5367 ahrens drr.drr_u.drr_end.drr_checksum = zc; 1246 5367 ahrens err = write(outfd, &drr, sizeof (drr)); 1247 5367 ahrens if (err == -1) { 1248 5367 ahrens fsavl_destroy(fsavl); 1249 5367 ahrens nvlist_free(fss); 1250 10735 chris if (holdsnaps) { 1251 10735 chris (void) zfs_release_range(zhp, fromsnap, 1252 10735 chris tosnap, holdtag); 1253 10735 chris } 1254 11007 Lori err = errno; 1255 11007 Lori goto stderr_out; 1256 5367 ahrens } 1257 5367 ahrens } 1258 5367 ahrens } 1259 5367 ahrens 1260 5367 ahrens /* dump each stream */ 1261 5367 ahrens sdd.fromsnap = fromsnap; 1262 5367 ahrens sdd.tosnap = tosnap; 1263 11007 Lori if (flags.dedup) 1264 11007 Lori sdd.outfd = pipefd[0]; 1265 11007 Lori else 1266 11007 Lori sdd.outfd = outfd; 1267 11007 Lori sdd.replicate = flags.replicate; 1268 11007 Lori sdd.doall = flags.doall; 1269 11007 Lori sdd.fromorigin = flags.fromorigin; 1270 5367 ahrens sdd.fss = fss; 1271 5367 ahrens sdd.fsavl = fsavl; 1272 11007 Lori sdd.verbose = flags.verbose; 1273 11007 Lori sdd.filter_cb = filter_func; 1274 11007 Lori sdd.filter_cb_arg = cb_arg; 1275 5367 ahrens err = dump_filesystems(zhp, &sdd); 1276 5367 ahrens fsavl_destroy(fsavl); 1277 5367 ahrens nvlist_free(fss); 1278 5367 ahrens 1279 11007 Lori if (flags.dedup) { 1280 11007 Lori (void) close(pipefd[0]); 1281 11007 Lori (void) pthread_join(tid, NULL); 1282 11007 Lori } 1283 11022 Tom 1284 11022 Tom if (flags.replicate || flags.doall || flags.props) { 1285 5367 ahrens /* 1286 5367 ahrens * write final end record. NB: want to do this even if 1287 5367 ahrens * there was some error, because it might not be totally 1288 5367 ahrens * failed. 1289 5367 ahrens */ 1290 5367 ahrens dmu_replay_record_t drr = { 0 }; 1291 5367 ahrens drr.drr_type = DRR_END; 1292 10735 chris if (holdsnaps) { 1293 10735 chris (void) zfs_release_range(zhp, fromsnap, tosnap, 1294 10735 chris holdtag); 1295 10735 chris } 1296 5367 ahrens if (write(outfd, &drr, sizeof (drr)) == -1) { 1297 5367 ahrens return (zfs_standard_error(zhp->zfs_hdl, 1298 5367 ahrens errno, errbuf)); 1299 5367 ahrens } 1300 5367 ahrens } 1301 5367 ahrens 1302 5367 ahrens return (err || sdd.err); 1303 11007 Lori 1304 11007 Lori stderr_out: 1305 11007 Lori err = zfs_standard_error(zhp->zfs_hdl, err, errbuf); 1306 11007 Lori err_out: 1307 11007 Lori if (flags.dedup) { 1308 11007 Lori (void) pthread_cancel(tid); 1309 11007 Lori (void) pthread_join(tid, NULL); 1310 11007 Lori (void) close(pipefd[0]); 1311 11007 Lori } 1312 11007 Lori return (err); 1313 5367 ahrens } 1314 5367 ahrens 1315 5367 ahrens /* 1316 5367 ahrens * Routines specific to "zfs recv" 1317 5367 ahrens */ 1318 5367 ahrens 1319 5367 ahrens static int 1320 5367 ahrens recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen, 1321 5367 ahrens boolean_t byteswap, zio_cksum_t *zc) 1322 5367 ahrens { 1323 5367 ahrens char *cp = buf; 1324 5367 ahrens int rv; 1325 5367 ahrens int len = ilen; 1326 5367 ahrens 1327 5367 ahrens do { 1328 5367 ahrens rv = read(fd, cp, len); 1329 5367 ahrens cp += rv; 1330 5367 ahrens len -= rv; 1331 5367 ahrens } while (rv > 0); 1332 5367 ahrens 1333 5367 ahrens if (rv < 0 || len != 0) { 1334 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1335 5367 ahrens "failed to read from stream")); 1336 5367 ahrens return (zfs_error(hdl, EZFS_BADSTREAM, dgettext(TEXT_DOMAIN, 1337 5367 ahrens "cannot receive"))); 1338 5367 ahrens } 1339 5367 ahrens 1340 5367 ahrens if (zc) { 1341 5367 ahrens if (byteswap) 1342 5367 ahrens fletcher_4_incremental_byteswap(buf, ilen, zc); 1343 5367 ahrens else 1344 5367 ahrens fletcher_4_incremental_native(buf, ilen, zc); 1345 5367 ahrens } 1346 5367 ahrens return (0); 1347 5367 ahrens } 1348 5367 ahrens 1349 5367 ahrens static int 1350 5367 ahrens recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp, 1351 5367 ahrens boolean_t byteswap, zio_cksum_t *zc) 1352 5367 ahrens { 1353 5367 ahrens char *buf; 1354 5367 ahrens int err; 1355 5367 ahrens 1356 5367 ahrens buf = zfs_alloc(hdl, len); 1357 5367 ahrens if (buf == NULL) 1358 5367 ahrens return (ENOMEM); 1359 5367 ahrens 1360 5367 ahrens err = recv_read(hdl, fd, buf, len, byteswap, zc); 1361 5367 ahrens if (err != 0) { 1362 5367 ahrens free(buf); 1363 5367 ahrens return (err); 1364 5367 ahrens } 1365 5367 ahrens 1366 5367 ahrens err = nvlist_unpack(buf, len, nvp, 0); 1367 5367 ahrens free(buf); 1368 5367 ahrens if (err != 0) { 1369 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 1370 5367 ahrens "stream (malformed nvlist)")); 1371 5367 ahrens return (EINVAL); 1372 5367 ahrens } 1373 5367 ahrens return (0); 1374 5367 ahrens } 1375 5367 ahrens 1376 5367 ahrens static int 1377 5367 ahrens recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname, 1378 5367 ahrens int baselen, char *newname, recvflags_t flags) 1379 5367 ahrens { 1380 5367 ahrens static int seq; 1381 5367 ahrens zfs_cmd_t zc = { 0 }; 1382 5367 ahrens int err; 1383 6047 ahrens prop_changelist_t *clp; 1384 6047 ahrens zfs_handle_t *zhp; 1385 5367 ahrens 1386 6047 ahrens zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); 1387 6047 ahrens if (zhp == NULL) 1388 6047 ahrens return (-1); 1389 7366 Tim clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 1390 7366 Tim flags.force ? MS_FORCE : 0); 1391 6047 ahrens zfs_close(zhp); 1392 6047 ahrens if (clp == NULL) 1393 6047 ahrens return (-1); 1394 6047 ahrens err = changelist_prefix(clp); 1395 6047 ahrens if (err) 1396 6047 ahrens return (err); 1397 5367 ahrens 1398 10242 chris zc.zc_objset_type = DMU_OST_ZFS; 1399 10242 chris (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 1400 10242 chris 1401 5367 ahrens if (tryname) { 1402 5367 ahrens (void) strcpy(newname, tryname); 1403 5367 ahrens 1404 5367 ahrens (void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value)); 1405 5367 ahrens 1406 5367 ahrens if (flags.verbose) { 1407 5367 ahrens (void) printf("attempting rename %s to %s\n", 1408 5367 ahrens zc.zc_name, zc.zc_value); 1409 5367 ahrens } 1410 5367 ahrens err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc); 1411 6047 ahrens if (err == 0) 1412 5367 ahrens changelist_rename(clp, name, tryname); 1413 5367 ahrens } else { 1414 5367 ahrens err = ENOENT; 1415 5367 ahrens } 1416 5367 ahrens 1417 5367 ahrens if (err != 0 && strncmp(name+baselen, "recv-", 5) != 0) { 1418 5367 ahrens seq++; 1419 5367 ahrens 1420 5367 ahrens (void) strncpy(newname, name, baselen); 1421 5367 ahrens (void) snprintf(newname+baselen, ZFS_MAXNAMELEN-baselen, 1422 5367 ahrens "recv-%u-%u", getpid(), seq); 1423 5367 ahrens (void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value)); 1424 5367 ahrens 1425 5367 ahrens if (flags.verbose) { 1426 5367 ahrens (void) printf("failed - trying rename %s to %s\n", 1427 5367 ahrens zc.zc_name, zc.zc_value); 1428 5367 ahrens } 1429 5367 ahrens err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc); 1430 6047 ahrens if (err == 0) 1431 5367 ahrens changelist_rename(clp, name, newname); 1432 5367 ahrens if (err && flags.verbose) { 1433 5367 ahrens (void) printf("failed (%u) - " 1434 5367 ahrens "will try again on next pass\n", errno); 1435 5367 ahrens } 1436 5367 ahrens err = EAGAIN; 1437 5367 ahrens } else if (flags.verbose) { 1438 5367 ahrens if (err == 0) 1439 5367 ahrens (void) printf("success\n"); 1440 5367 ahrens else 1441 5367 ahrens (void) printf("failed (%u)\n", errno); 1442 5367 ahrens } 1443 5367 ahrens 1444 6047 ahrens (void) changelist_postfix(clp); 1445 6047 ahrens changelist_free(clp); 1446 5367 ahrens 1447 5367 ahrens return (err); 1448 5367 ahrens } 1449 5367 ahrens 1450 5367 ahrens static int 1451 5367 ahrens recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen, 1452 5367 ahrens char *newname, recvflags_t flags) 1453 5367 ahrens { 1454 5367 ahrens zfs_cmd_t zc = { 0 }; 1455 6047 ahrens int err = 0; 1456 6047 ahrens prop_changelist_t *clp; 1457 6047 ahrens zfs_handle_t *zhp; 1458 10242 chris boolean_t defer = B_FALSE; 1459 10242 chris int spa_version; 1460 6047 ahrens 1461 6047 ahrens zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); 1462 6047 ahrens if (zhp == NULL) 1463 6047 ahrens return (-1); 1464 7366 Tim clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 1465 7366 Tim flags.force ? MS_FORCE : 0); 1466 10242 chris if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 1467 10242 chris zfs_spa_version(zhp, &spa_version) == 0 && 1468 10242 chris spa_version >= SPA_VERSION_USERREFS) 1469 10242 chris defer = B_TRUE; 1470 6047 ahrens zfs_close(zhp); 1471 6047 ahrens if (clp == NULL) 1472 6047 ahrens return (-1); 1473 6047 ahrens err = changelist_prefix(clp); 1474 6047 ahrens if (err) 1475 6047 ahrens return (err); 1476 5367 ahrens 1477 5367 ahrens zc.zc_objset_type = DMU_OST_ZFS; 1478 10242 chris zc.zc_defer_destroy = defer; 1479 5367 ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 1480 5367 ahrens 1481 5367 ahrens if (flags.verbose) 1482 5367 ahrens (void) printf("attempting destroy %s\n", zc.zc_name); 1483 5367 ahrens err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc); 1484 6047 ahrens if (err == 0) { 1485 6047 ahrens if (flags.verbose) 1486 6047 ahrens (void) printf("success\n"); 1487 6047 ahrens changelist_remove(clp, zc.zc_name); 1488 6047 ahrens } 1489 6047 ahrens 1490 6047 ahrens (void) changelist_postfix(clp); 1491 6047 ahrens changelist_free(clp); 1492 6047 ahrens 1493 10242 chris /* 1494 11022 Tom * Deferred destroy might destroy the snapshot or only mark it to be 1495 11022 Tom * destroyed later, and it returns success in either case. 1496 10242 chris */ 1497 11022 Tom if (err != 0 || (defer && zfs_dataset_exists(hdl, name, 1498 11022 Tom ZFS_TYPE_SNAPSHOT))) { 1499 5367 ahrens err = recv_rename(hdl, name, NULL, baselen, newname, flags); 1500 11022 Tom } 1501 5367 ahrens 1502 5367 ahrens return (err); 1503 5367 ahrens } 1504 5367 ahrens 1505 5367 ahrens typedef struct guid_to_name_data { 1506 5367 ahrens uint64_t guid; 1507 5367 ahrens char *name; 1508 5367 ahrens } guid_to_name_data_t; 1509 5367 ahrens 1510 5367 ahrens static int 1511 5367 ahrens guid_to_name_cb(zfs_handle_t *zhp, void *arg) 1512 5367 ahrens { 1513 5367 ahrens guid_to_name_data_t *gtnd = arg; 1514 5367 ahrens int err; 1515 5367 ahrens 1516 5367 ahrens if (zhp->zfs_dmustats.dds_guid == gtnd->guid) { 1517 5367 ahrens (void) strcpy(gtnd->name, zhp->zfs_name); 1518 5367 ahrens return (EEXIST); 1519 5367 ahrens } 1520 5367 ahrens err = zfs_iter_children(zhp, guid_to_name_cb, gtnd); 1521 5367 ahrens zfs_close(zhp); 1522 5367 ahrens return (err); 1523 5367 ahrens } 1524 5367 ahrens 1525 5367 ahrens static int 1526 5367 ahrens guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid, 1527 5367 ahrens char *name) 1528 5367 ahrens { 1529 5367 ahrens /* exhaustive search all local snapshots */ 1530 5367 ahrens guid_to_name_data_t gtnd; 1531 5367 ahrens int err = 0; 1532 5367 ahrens zfs_handle_t *zhp; 1533 5367 ahrens char *cp; 1534 5367 ahrens 1535 5367 ahrens gtnd.guid = guid; 1536 5367 ahrens gtnd.name = name; 1537 5367 ahrens 1538 5367 ahrens if (strchr(parent, '@') == NULL) { 1539 5367 ahrens zhp = make_dataset_handle(hdl, parent); 1540 5367 ahrens if (zhp != NULL) { 1541 5367 ahrens err = zfs_iter_children(zhp, guid_to_name_cb, >nd); 1542 5367 ahrens zfs_close(zhp); 1543 5367 ahrens if (err == EEXIST) 1544 5367 ahrens return (0); 1545 5367 ahrens } 1546 5367 ahrens } 1547 5367 ahrens 1548 5367 ahrens cp = strchr(parent, '/'); 1549 5367 ahrens if (cp) 1550 5367 ahrens *cp = '\0'; 1551 5367 ahrens zhp = make_dataset_handle(hdl, parent); 1552 5367 ahrens if (cp) 1553 5367 ahrens *cp = '/'; 1554 5367 ahrens 1555 5367 ahrens if (zhp) { 1556 5367 ahrens err = zfs_iter_children(zhp, guid_to_name_cb, >nd); 1557 5367 ahrens zfs_close(zhp); 1558 5367 ahrens } 1559 5367 ahrens 1560 5367 ahrens return (err == EEXIST ? 0 : ENOENT); 1561 5367 ahrens 1562 5367 ahrens } 1563 5367 ahrens 1564 5367 ahrens /* 1565 5367 ahrens * Return true if dataset guid1 is created before guid2. 1566 5367 ahrens */ 1567 6476 ahl static int 1568 5367 ahrens created_before(libzfs_handle_t *hdl, avl_tree_t *avl, 1569 5367 ahrens uint64_t guid1, uint64_t guid2) 1570 5367 ahrens { 1571 5367 ahrens nvlist_t *nvfs; 1572 5367 ahrens char *fsname, *snapname; 1573 5367 ahrens char buf[ZFS_MAXNAMELEN]; 1574 6476 ahl int rv; 1575 5367 ahrens zfs_node_t zn1, zn2; 1576 5367 ahrens 1577 5367 ahrens if (guid2 == 0) 1578 6476 ahl return (0); 1579 5367 ahrens if (guid1 == 0) 1580 6476 ahl return (1); 1581 5367 ahrens 1582 5367 ahrens nvfs = fsavl_find(avl, guid1, &snapname); 1583 5367 ahrens VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); 1584 5367 ahrens (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); 1585 5367 ahrens zn1.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); 1586 6476 ahl if (zn1.zn_handle == NULL) 1587 6476 ahl return (-1); 1588 5367 ahrens 1589 5367 ahrens nvfs = fsavl_find(avl, guid2, &snapname); 1590 5367 ahrens VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); 1591 5367 ahrens (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); 1592 5367 ahrens zn2.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); 1593 6476 ahl if (zn2.zn_handle == NULL) { 1594 6476 ahl zfs_close(zn2.zn_handle); 1595 6476 ahl return (-1); 1596 6476 ahl } 1597 5367 ahrens 1598 5367 ahrens rv = (zfs_snapshot_compare(&zn1, &zn2) == -1); 1599 5367 ahrens 1600 5367 ahrens zfs_close(zn1.zn_handle); 1601 5367 ahrens zfs_close(zn2.zn_handle); 1602 5367 ahrens 1603 5367 ahrens return (rv); 1604 5367 ahrens } 1605 5367 ahrens 1606 5367 ahrens static int 1607 5367 ahrens recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs, 1608 5367 ahrens recvflags_t flags, nvlist_t *stream_nv, avl_tree_t *stream_avl) 1609 5367 ahrens { 1610 5367 ahrens nvlist_t *local_nv; 1611 5367 ahrens avl_tree_t *local_avl; 1612 5367 ahrens nvpair_t *fselem, *nextfselem; 1613 5367 ahrens char *tosnap, *fromsnap; 1614 5367 ahrens char newname[ZFS_MAXNAMELEN]; 1615 5367 ahrens int error; 1616 11022 Tom boolean_t needagain, progress, recursive; 1617 10299 Prabahar char *s1, *s2; 1618 5367 ahrens 1619 5367 ahrens VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap)); 1620 5367 ahrens VERIFY(0 == nvlist_lookup_string(stream_nv, "tosnap", &tosnap)); 1621 11022 Tom 1622 11022 Tom recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") == 1623 11022 Tom ENOENT); 1624 5367 ahrens 1625 5367 ahrens if (flags.dryrun) 1626 5367 ahrens return (0); 1627 5367 ahrens 1628 5367 ahrens again: 1629 5367 ahrens needagain = progress = B_FALSE; 1630 5367 ahrens 1631 5367 ahrens if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL, 1632 11022 Tom recursive, &local_nv, &local_avl)) != 0) 1633 5367 ahrens return (error); 1634 5367 ahrens 1635 5367 ahrens /* 1636 5367 ahrens * Process deletes and renames 1637 5367 ahrens */ 1638 5367 ahrens for (fselem = nvlist_next_nvpair(local_nv, NULL); 1639 5367 ahrens fselem; fselem = nextfselem) { 1640 5367 ahrens nvlist_t *nvfs, *snaps; 1641 5367 ahrens nvlist_t *stream_nvfs = NULL; 1642 5367 ahrens nvpair_t *snapelem, *nextsnapelem; 1643 5367 ahrens uint64_t fromguid = 0; 1644 5367 ahrens uint64_t originguid = 0; 1645 5367 ahrens uint64_t stream_originguid = 0; 1646 5367 ahrens uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid; 1647 5367 ahrens char *fsname, *stream_fsname; 1648 5367 ahrens 1649 5367 ahrens nextfselem = nvlist_next_nvpair(local_nv, fselem); 1650 5367 ahrens 1651 5367 ahrens VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs)); 1652 5367 ahrens VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps)); 1653 5367 ahrens VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); 1654 5367 ahrens VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap", 1655 5367 ahrens &parent_fromsnap_guid)); 1656 5367 ahrens (void) nvlist_lookup_uint64(nvfs, "origin", &originguid); 1657 5367 ahrens 1658 5367 ahrens /* 1659 5367 ahrens * First find the stream's fs, so we can check for 1660 5367 ahrens * a different origin (due to "zfs promote") 1661 5367 ahrens */ 1662 5367 ahrens for (snapelem = nvlist_next_nvpair(snaps, NULL); 1663 5367 ahrens snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) { 1664 5367 ahrens uint64_t thisguid; 1665 5367 ahrens 1666 5367 ahrens VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid)); 1667 5367 ahrens stream_nvfs = fsavl_find(stream_avl, thisguid, NULL); 1668 5367 ahrens 1669 5367 ahrens if (stream_nvfs != NULL) 1670 5367 ahrens break; 1671 5367 ahrens } 1672 5367 ahrens 1673 5367 ahrens /* check for promote */ 1674 5367 ahrens (void) nvlist_lookup_uint64(stream_nvfs, "origin", 1675 5367 ahrens &stream_originguid); 1676 5367 ahrens if (stream_nvfs && originguid != stream_originguid) { 1677 6476 ahl switch (created_before(hdl, local_avl, 1678 6476 ahl stream_originguid, originguid)) { 1679 6476 ahl case 1: { 1680 5367 ahrens /* promote it! */ 1681 5367 ahrens zfs_cmd_t zc = { 0 }; 1682 5367 ahrens nvlist_t *origin_nvfs; 1683 5367 ahrens char *origin_fsname; 1684 5367 ahrens 1685 5367 ahrens if (flags.verbose) 1686 5367 ahrens (void) printf("promoting %s\n", fsname); 1687 5367 ahrens 1688 5367 ahrens origin_nvfs = fsavl_find(local_avl, originguid, 1689 5367 ahrens NULL); 1690 5367 ahrens VERIFY(0 == nvlist_lookup_string(origin_nvfs, 1691 5367 ahrens "name", &origin_fsname)); 1692 5367 ahrens (void) strlcpy(zc.zc_value, origin_fsname, 1693 5367 ahrens sizeof (zc.zc_value)); 1694 5367 ahrens (void) strlcpy(zc.zc_name, fsname, 1695 5367 ahrens sizeof (zc.zc_name)); 1696 5367 ahrens error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc); 1697 5367 ahrens if (error == 0) 1698 5367 ahrens progress = B_TRUE; 1699 6476 ahl break; 1700 6476 ahl } 1701 6476 ahl default: 1702 6476 ahl break; 1703 6476 ahl case -1: 1704 6476 ahl fsavl_destroy(local_avl); 1705 6476 ahl nvlist_free(local_nv); 1706 6476 ahl return (-1); 1707 5367 ahrens } 1708 5367 ahrens /* 1709 5367 ahrens * We had/have the wrong origin, therefore our 1710 5367 ahrens * list of snapshots is wrong. Need to handle 1711 5367 ahrens * them on the next pass. 1712 5367 ahrens */ 1713 5367 ahrens needagain = B_TRUE; 1714 5367 ahrens continue; 1715 5367 ahrens } 1716 5367 ahrens 1717 5367 ahrens for (snapelem = nvlist_next_nvpair(snaps, NULL); 1718 5367 ahrens snapelem; snapelem = nextsnapelem) { 1719 5367 ahrens uint64_t thisguid; 1720 5367 ahrens char *stream_snapname; 1721 7265 ahrens nvlist_t *found, *props; 1722 5367 ahrens 1723 5367 ahrens nextsnapelem = nvlist_next_nvpair(snaps, snapelem); 1724 5367 ahrens 1725 5367 ahrens VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid)); 1726 5367 ahrens found = fsavl_find(stream_avl, thisguid, 1727 5367 ahrens &stream_snapname); 1728 5367 ahrens 1729 5367 ahrens /* check for delete */ 1730 5367 ahrens if (found == NULL) { 1731 5367 ahrens char name[ZFS_MAXNAMELEN]; 1732 5367 ahrens 1733 5367 ahrens if (!flags.force) 1734 5367 ahrens continue; 1735 5367 ahrens 1736 5367 ahrens (void) snprintf(name, sizeof (name), "%s@%s", 1737 5367 ahrens fsname, nvpair_name(snapelem)); 1738 5367 ahrens 1739 5367 ahrens error = recv_destroy(hdl, name, 1740 5367 ahrens strlen(fsname)+1, newname, flags); 1741 5367 ahrens if (error) 1742 5367 ahrens needagain = B_TRUE; 1743 5367 ahrens else 1744 5367 ahrens progress = B_TRUE; 1745 5367 ahrens continue; 1746 5367 ahrens } 1747 5367 ahrens 1748 5367 ahrens stream_nvfs = found; 1749 7265 ahrens 1750 7265 ahrens if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops", 1751 7265 ahrens &props) && 0 == nvlist_lookup_nvlist(props, 1752 7265 ahrens stream_snapname, &props)) { 1753 7265 ahrens zfs_cmd_t zc = { 0 }; 1754 7265 ahrens 1755 11022 Tom zc.zc_cookie = B_TRUE; /* received */ 1756 7273 ahrens (void) snprintf(zc.zc_name, sizeof (zc.zc_name), 1757 7265 ahrens "%s@%s", fsname, nvpair_name(snapelem)); 1758 7265 ahrens if (zcmd_write_src_nvlist(hdl, &zc, 1759 7265 ahrens props) == 0) { 1760 7265 ahrens (void) zfs_ioctl(hdl, 1761 7265 ahrens ZFS_IOC_SET_PROP, &zc); 1762 7265 ahrens zcmd_free_nvlists(&zc); 1763 7265 ahrens } 1764 7265 ahrens } 1765 5367 ahrens 1766 5367 ahrens /* check for different snapname */ 1767 5367 ahrens if (strcmp(nvpair_name(snapelem), 1768 5367 ahrens stream_snapname) != 0) { 1769 5367 ahrens char name[ZFS_MAXNAMELEN]; 1770 5367 ahrens char tryname[ZFS_MAXNAMELEN]; 1771 5367 ahrens 1772 5367 ahrens (void) snprintf(name, sizeof (name), "%s@%s", 1773 5367 ahrens fsname, nvpair_name(snapelem)); 1774 5367 ahrens (void) snprintf(tryname, sizeof (name), "%s@%s", 1775 5367 ahrens fsname, stream_snapname); 1776 5367 ahrens 1777 5367 ahrens error = recv_rename(hdl, name, tryname, 1778 5367 ahrens strlen(fsname)+1, newname, flags); 1779 5367 ahrens if (error) 1780 5367 ahrens needagain = B_TRUE; 1781 5367 ahrens else 1782 5367 ahrens progress = B_TRUE; 1783 5367 ahrens } 1784 5367 ahrens 1785 5367 ahrens if (strcmp(stream_snapname, fromsnap) == 0) 1786 5367 ahrens fromguid = thisguid; 1787 5367 ahrens } 1788 5367 ahrens 1789 5367 ahrens /* check for delete */ 1790 5367 ahrens if (stream_nvfs == NULL) { 1791 5367 ahrens if (!flags.force) 1792 5367 ahrens continue; 1793 5367 ahrens 1794 5367 ahrens error = recv_destroy(hdl, fsname, strlen(tofs)+1, 1795 5367 ahrens newname, flags); 1796 5367 ahrens if (error) 1797 5367 ahrens needagain = B_TRUE; 1798 5367 ahrens else 1799 5367 ahrens progress = B_TRUE; 1800 5367 ahrens continue; 1801 5367 ahrens } 1802 5367 ahrens 1803 5367 ahrens if (fromguid == 0 && flags.verbose) { 1804 5367 ahrens (void) printf("local fs %s does not have fromsnap " 1805 5367 ahrens "(%s in stream); must have been deleted locally; " 1806 5367 ahrens "ignoring\n", fsname, fromsnap); 1807 5367 ahrens continue; 1808 5367 ahrens } 1809 5367 ahrens 1810 5367 ahrens VERIFY(0 == nvlist_lookup_string(stream_nvfs, 1811 5367 ahrens "name", &stream_fsname)); 1812 5367 ahrens VERIFY(0 == nvlist_lookup_uint64(stream_nvfs, 1813 5367 ahrens "parentfromsnap", &stream_parent_fromsnap_guid)); 1814 5367 ahrens 1815 10302 Prabahar s1 = strrchr(fsname, '/'); 1816 10302 Prabahar s2 = strrchr(stream_fsname, '/'); 1817 10302 Prabahar 1818 5367 ahrens /* check for rename */ 1819 5367 ahrens if ((stream_parent_fromsnap_guid != 0 && 1820 5367 ahrens stream_parent_fromsnap_guid != parent_fromsnap_guid) || 1821 10302 Prabahar ((s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) { 1822 5367 ahrens nvlist_t *parent; 1823 5367 ahrens char tryname[ZFS_MAXNAMELEN]; 1824 5367 ahrens 1825 5367 ahrens parent = fsavl_find(local_avl, 1826 5367 ahrens stream_parent_fromsnap_guid, NULL); 1827 5367 ahrens /* 1828 5367 ahrens * NB: parent might not be found if we used the 1829 5367 ahrens * tosnap for stream_parent_fromsnap_guid, 1830 5367 ahrens * because the parent is a newly-created fs; 1831 5367 ahrens * we'll be able to rename it after we recv the 1832 5367 ahrens * new fs. 1833 5367 ahrens */ 1834 5367 ahrens if (parent != NULL) { 1835 5367 ahrens char *pname; 1836 5367 ahrens 1837 5367 ahrens VERIFY(0 == nvlist_lookup_string(parent, "name", 1838 5367 ahrens &pname)); 1839 5367 ahrens (void) snprintf(tryname, sizeof (tryname), 1840 5367 ahrens "%s%s", pname, strrchr(stream_fsname, '/')); 1841 5367 ahrens } else { 1842 5367 ahrens tryname[0] = '\0'; 1843 5367 ahrens if (flags.verbose) { 1844 5367 ahrens (void) printf("local fs %s new parent " 1845 5367 ahrens "not found\n", fsname); 1846 5367 ahrens } 1847 5367 ahrens } 1848 5367 ahrens 1849 5367 ahrens error = recv_rename(hdl, fsname, tryname, 1850 5367 ahrens strlen(tofs)+1, newname, flags); 1851 5367 ahrens if (error) 1852 5367 ahrens needagain = B_TRUE; 1853 5367 ahrens else 1854 5367 ahrens progress = B_TRUE; 1855 5367 ahrens } 1856 5367 ahrens } 1857 5367 ahrens 1858 5367 ahrens fsavl_destroy(local_avl); 1859 5367 ahrens nvlist_free(local_nv); 1860 5367 ahrens 1861 5367 ahrens if (needagain && progress) { 1862 5367 ahrens /* do another pass to fix up temporary names */ 1863 5367 ahrens if (flags.verbose) 1864 5367 ahrens (void) printf("another pass:\n"); 1865 5367 ahrens goto again; 1866 5367 ahrens } 1867 5367 ahrens 1868 5367 ahrens return (needagain); 1869 5367 ahrens } 1870 5367 ahrens 1871 5367 ahrens static int 1872 5367 ahrens zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname, 1873 7366 Tim recvflags_t flags, dmu_replay_record_t *drr, zio_cksum_t *zc, 1874 7366 Tim char **top_zfs) 1875 5367 ahrens { 1876 5367 ahrens nvlist_t *stream_nv = NULL; 1877 5367 ahrens avl_tree_t *stream_avl = NULL; 1878 5367 ahrens char *fromsnap = NULL; 1879 5367 ahrens char tofs[ZFS_MAXNAMELEN]; 1880 5367 ahrens char errbuf[1024]; 1881 5367 ahrens dmu_replay_record_t drre; 1882 5367 ahrens int error; 1883 5367 ahrens boolean_t anyerr = B_FALSE; 1884 6479 ahrens boolean_t softerr = B_FALSE; 1885 5367 ahrens 1886 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1887 5367 ahrens "cannot receive")); 1888 5367 ahrens 1889 5367 ahrens if (strchr(destname, '@')) { 1890 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1891 5367 ahrens "can not specify snapshot name for multi-snapshot stream")); 1892 5367 ahrens return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 1893 5367 ahrens } 1894 5367 ahrens 1895 5367 ahrens assert(drr->drr_type == DRR_BEGIN); 1896 5367 ahrens assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC); 1897 11007 Lori assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) == 1898 11007 Lori DMU_COMPOUNDSTREAM); 1899 5367 ahrens 1900 5367 ahrens /* 1901 5367 ahrens * Read in the nvlist from the stream. 1902 5367 ahrens */ 1903 5367 ahrens if (drr->drr_payloadlen != 0) { 1904 11022 Tom boolean_t recursive; 1905 5367 ahrens 1906 5367 ahrens error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen, 1907 5367 ahrens &stream_nv, flags.byteswap, zc); 1908 5367 ahrens if (error) { 1909 5367 ahrens error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); 1910 5367 ahrens goto out; 1911 11022 Tom } 1912 11022 Tom 1913 11022 Tom recursive = (nvlist_lookup_boolean(stream_nv, 1914 11022 Tom "not_recursive") == ENOENT); 1915 11022 Tom 1916 11022 Tom if (recursive && !flags.isprefix) { 1917 11022 Tom zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1918 11022 Tom "must use -d to receive replication " 1919 11022 Tom "(send -R) stream")); 1920 11022 Tom return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 1921 5367 ahrens } 1922 5367 ahrens } 1923 5367 ahrens 1924 5367 ahrens /* 1925 5367 ahrens * Read in the end record and verify checksum. 1926 5367 ahrens */ 1927 5367 ahrens if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre), 1928 5367 ahrens flags.byteswap, NULL))) 1929 5367 ahrens goto out; 1930 5367 ahrens if (flags.byteswap) { 1931 5367 ahrens drre.drr_type = BSWAP_32(drre.drr_type); 1932 5367 ahrens drre.drr_u.drr_end.drr_checksum.zc_word[0] = 1933 5367 ahrens BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]); 1934 5367 ahrens drre.drr_u.drr_end.drr_checksum.zc_word[1] = 1935 5367 ahrens BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[1]); 1936 5367 ahrens drre.drr_u.drr_end.drr_checksum.zc_word[2] = 1937 5367 ahrens BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[2]); 1938 5367 ahrens drre.drr_u.drr_end.drr_checksum.zc_word[3] = 1939 5367 ahrens BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[3]); 1940 5367 ahrens } 1941 5367 ahrens if (drre.drr_type != DRR_END) { 1942 5367 ahrens error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); 1943 5367 ahrens goto out; 1944 5367 ahrens } 1945 5367 ahrens if (!ZIO_CHECKSUM_EQUAL(drre.drr_u.drr_end.drr_checksum, *zc)) { 1946 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1947 5367 ahrens "incorrect header checksum")); 1948 5367 ahrens error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); 1949 5367 ahrens goto out; 1950 5367 ahrens } 1951 5367 ahrens 1952 5367 ahrens (void) nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap); 1953 5367 ahrens 1954 5367 ahrens if (drr->drr_payloadlen != 0) { 1955 5367 ahrens nvlist_t *stream_fss; 1956 5367 ahrens 1957 5367 ahrens VERIFY(0 == nvlist_lookup_nvlist(stream_nv, "fss", 1958 5367 ahrens &stream_fss)); 1959 5896 ahl if ((stream_avl = fsavl_create(stream_fss)) == NULL) { 1960 5896 ahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1961 5896 ahl "couldn't allocate avl tree")); 1962 5896 ahl error = zfs_error(hdl, EZFS_NOMEM, errbuf); 1963 5896 ahl goto out; 1964 5896 ahl } 1965 5367 ahrens 1966 5367 ahrens if (fromsnap != NULL) { 1967 5367 ahrens (void) strlcpy(tofs, destname, ZFS_MAXNAMELEN); 1968 5367 ahrens if (flags.isprefix) { 1969 5367 ahrens int i = strcspn(drr->drr_u.drr_begin.drr_toname, 1970 5367 ahrens "/@"); 1971 5367 ahrens /* zfs_receive_one() will create_parents() */ 1972 5367 ahrens (void) strlcat(tofs, 1973 5367 ahrens &drr->drr_u.drr_begin.drr_toname[i], 1974 5367 ahrens ZFS_MAXNAMELEN); 1975 5367 ahrens *strchr(tofs, '@') = '\0'; 1976 5367 ahrens } 1977 6479 ahrens softerr = recv_incremental_replication(hdl, tofs, 1978 5367 ahrens flags, stream_nv, stream_avl); 1979 5367 ahrens } 1980 5367 ahrens } 1981 5367 ahrens 1982 5367 ahrens 1983 5367 ahrens /* Finally, receive each contained stream */ 1984 5367 ahrens do { 1985 5367 ahrens /* 1986 5367 ahrens * we should figure out if it has a recoverable 1987 5367 ahrens * error, in which case do a recv_skip() and drive on. 1988 5367 ahrens * Note, if we fail due to already having this guid, 1989 5367 ahrens * zfs_receive_one() will take care of it (ie, 1990 5367 ahrens * recv_skip() and return 0). 1991 5367 ahrens */ 1992 7366 Tim error = zfs_receive_impl(hdl, destname, flags, fd, 1993 7366 Tim stream_avl, top_zfs); 1994 5367 ahrens if (error == ENODATA) { 1995 5367 ahrens error = 0; 1996 5367 ahrens break; 1997 5367 ahrens } 1998 5367 ahrens anyerr |= error; 1999 5367 ahrens } while (error == 0); 2000 5367 ahrens 2001 5367 ahrens if (drr->drr_payloadlen != 0 && fromsnap != NULL) { 2002 5367 ahrens /* 2003 5367 ahrens * Now that we have the fs's they sent us, try the 2004 5367 ahrens * renames again. 2005 5367 ahrens */ 2006 6479 ahrens softerr = recv_incremental_replication(hdl, tofs, flags, 2007 5367 ahrens stream_nv, stream_avl); 2008 5367 ahrens } 2009 5367 ahrens 2010 5367 ahrens out: 2011 5367 ahrens fsavl_destroy(stream_avl); 2012 5367 ahrens if (stream_nv) 2013 5367 ahrens nvlist_free(stream_nv); 2014 6479 ahrens if (softerr) 2015 6479 ahrens error = -2; 2016 5367 ahrens if (anyerr) 2017 5367 ahrens error = -1; 2018 5367 ahrens return (error); 2019 11022 Tom } 2020 11022 Tom 2021 11022 Tom static void 2022 11022 Tom trunc_prop_errs(int truncated) 2023 11022 Tom { 2024 11022 Tom ASSERT(truncated != 0); 2025 11022 Tom 2026 11022 Tom if (truncated == 1) 2027 11022 Tom (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 2028 11022 Tom "1 more property could not be set\n")); 2029 11022 Tom else 2030 11022 Tom (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 2031 11022 Tom "%d more properties could not be set\n"), truncated); 2032 5367 ahrens } 2033 5367 ahrens 2034 5367 ahrens static int 2035 5367 ahrens recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap) 2036 5367 ahrens { 2037 5367 ahrens dmu_replay_record_t *drr; 2038 5367 ahrens void *buf = malloc(1<<20); 2039 11007 Lori char errbuf[1024]; 2040 11007 Lori 2041 11007 Lori (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2042 11007 Lori "cannot receive:")); 2043 5367 ahrens 2044 5367 ahrens /* XXX would be great to use lseek if possible... */ 2045 5367 ahrens drr = buf; 2046 5367 ahrens 2047 5367 ahrens while (recv_read(hdl, fd, drr, sizeof (dmu_replay_record_t), 2048 5367 ahrens byteswap, NULL) == 0) { 2049 5367 ahrens if (byteswap) 2050 5367 ahrens drr->drr_type = BSWAP_32(drr->drr_type); 2051 5367 ahrens 2052 5367 ahrens switch (drr->drr_type) { 2053 5367 ahrens case DRR_BEGIN: 2054 5367 ahrens /* NB: not to be used on v2 stream packages */ 2055 11007 Lori if (drr->drr_payloadlen != 0) { 2056 11007 Lori zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2057 11007 Lori "invalid substream header")); 2058 11007 Lori return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2059 11007 Lori } 2060 5367 ahrens break; 2061 5367 ahrens 2062 5367 ahrens case DRR_END: 2063 5367 ahrens free(buf); 2064 5367 ahrens return (0); 2065 5367 ahrens 2066 5367 ahrens case DRR_OBJECT: 2067 5367 ahrens if (byteswap) { 2068 5367 ahrens drr->drr_u.drr_object.drr_bonuslen = 2069 5367 ahrens BSWAP_32(drr->drr_u.drr_object. 2070 5367 ahrens drr_bonuslen); 2071 5367 ahrens } 2072 5367 ahrens (void) recv_read(hdl, fd, buf, 2073 5367 ahrens P2ROUNDUP(drr->drr_u.drr_object.drr_bonuslen, 8), 2074 5367 ahrens B_FALSE, NULL); 2075 5367 ahrens break; 2076 5367 ahrens 2077 5367 ahrens case DRR_WRITE: 2078 5367 ahrens if (byteswap) { 2079 5367 ahrens drr->drr_u.drr_write.drr_length = 2080 7366 Tim BSWAP_64(drr->drr_u.drr_write.drr_length); 2081 5367 ahrens } 2082 5367 ahrens (void) recv_read(hdl, fd, buf, 2083 5367 ahrens drr->drr_u.drr_write.drr_length, B_FALSE, NULL); 2084 5367 ahrens break; 2085 5367 ahrens 2086 11007 Lori case DRR_WRITE_BYREF: 2087 5367 ahrens case DRR_FREEOBJECTS: 2088 5367 ahrens case DRR_FREE: 2089 5367 ahrens break; 2090 5367 ahrens 2091 5367 ahrens default: 2092 11007 Lori zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2093 11007 Lori "invalid record type")); 2094 11007 Lori return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2095 5367 ahrens } 2096 5367 ahrens } 2097 5367 ahrens 2098 5367 ahrens free(buf); 2099 5367 ahrens return (-1); 2100 5367 ahrens } 2101 5367 ahrens 2102 5367 ahrens /* 2103 5367 ahrens * Restores a backup of tosnap from the file descriptor specified by infd. 2104 5367 ahrens */ 2105 5367 ahrens static int 2106 5367 ahrens zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, 2107 5367 ahrens recvflags_t flags, dmu_replay_record_t *drr, 2108 7366 Tim dmu_replay_record_t *drr_noswap, avl_tree_t *stream_avl, 2109 7366 Tim char **top_zfs) 2110 5367 ahrens { 2111 5367 ahrens zfs_cmd_t zc = { 0 }; 2112 5367 ahrens time_t begin_time; 2113 5367 ahrens int ioctl_err, ioctl_errno, err, choplen; 2114 5367 ahrens char *cp; 2115 5367 ahrens struct drr_begin *drrb = &drr->drr_u.drr_begin; 2116 5367 ahrens char errbuf[1024]; 2117 11022 Tom char prop_errbuf[1024]; 2118 5367 ahrens char chopprefix[ZFS_MAXNAMELEN]; 2119 5367 ahrens boolean_t newfs = B_FALSE; 2120 5367 ahrens boolean_t stream_wantsnewfs; 2121 5367 ahrens uint64_t parent_snapguid = 0; 2122 5367 ahrens prop_changelist_t *clp = NULL; 2123 7265 ahrens nvlist_t *snapprops_nvlist = NULL; 2124 11022 Tom zprop_errflags_t prop_errflags; 2125 5367 ahrens 2126 5367 ahrens begin_time = time(NULL); 2127 5367 ahrens 2128 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2129 5367 ahrens "cannot receive")); 2130 5367 ahrens 2131 5367 ahrens if (stream_avl != NULL) { 2132 7265 ahrens char *snapname; 2133 7265 ahrens nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid, 2134 7265 ahrens &snapname); 2135 5367 ahrens nvlist_t *props; 2136 5896 ahl int ret; 2137 5367 ahrens 2138 5367 ahrens (void) nvlist_lookup_uint64(fs, "parentfromsnap", 2139 5367 ahrens &parent_snapguid); 2140 5367 ahrens err = nvlist_lookup_nvlist(fs, "props", &props); 2141 5367 ahrens if (err) 2142 5367 ahrens VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0)); 2143 5896 ahl 2144 5367 ahrens if (flags.canmountoff) { 2145 5367 ahrens VERIFY(0 == nvlist_add_uint64(props, 2146 5367 ahrens zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0)); 2147 5367 ahrens } 2148 5896 ahl ret = zcmd_write_src_nvlist(hdl, &zc, props); 2149 5367 ahrens if (err) 2150 5367 ahrens nvlist_free(props); 2151 7265 ahrens 2152 7265 ahrens if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) { 2153 7265 ahrens VERIFY(0 == nvlist_lookup_nvlist(props, 2154 7265 ahrens snapname, &snapprops_nvlist)); 2155 7265 ahrens } 2156 5896 ahl 2157 5896 ahl if (ret != 0) 2158 5896 ahl return (-1); 2159 5367 ahrens } 2160 5367 ahrens 2161 5367 ahrens /* 2162 5367 ahrens * Determine how much of the snapshot name stored in the stream 2163 5367 ahrens * we are going to tack on to the name they specified on the 2164 5367 ahrens * command line, and how much we are going to chop off. 2165 5367 ahrens * 2166 5367 ahrens * If they specified a snapshot, chop the entire name stored in 2167 5367 ahrens * the stream. 2168 5367 ahrens */ 2169 5367 ahrens (void) strcpy(chopprefix, drrb->drr_toname); 2170 5367 ahrens if (flags.isprefix) { 2171 5367 ahrens /* 2172 5367 ahrens * They specified a fs with -d, we want to tack on 2173 5367 ahrens * everything but the pool name stored in the stream 2174 5367 ahrens */ 2175 5367 ahrens if (strchr(tosnap, '@')) { 2176 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 2177 5367 ahrens "argument - snapshot not allowed with -d")); 2178 5367 ahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2179 5367 ahrens } 2180 5367 ahrens cp = strchr(chopprefix, '/'); 2181 5367 ahrens if (cp == NULL) 2182 5367 ahrens cp = strchr(chopprefix, '@'); 2183 5367 ahrens *cp = '\0'; 2184 5367 ahrens } else if (strchr(tosnap, '@') == NULL) { 2185 5367 ahrens /* 2186 5367 ahrens * If they specified a filesystem without -d, we want to 2187 5367 ahrens * tack on everything after the fs specified in the 2188 5367 ahrens * first name from the stream. 2189 5367 ahrens */ 2190 5367 ahrens cp = strchr(chopprefix, '@'); 2191 5367 ahrens *cp = '\0'; 2192 5367 ahrens } 2193 5367 ahrens choplen = strlen(chopprefix); 2194 5367 ahrens 2195 5367 ahrens /* 2196 5367 ahrens * Determine name of destination snapshot, store in zc_value. 2197 5367 ahrens */ 2198 11007 Lori (void) strcpy(zc.zc_top_ds, tosnap); 2199 5367 ahrens (void) strcpy(zc.zc_value, tosnap); 2200 5367 ahrens (void) strncat(zc.zc_value, drrb->drr_toname+choplen, 2201 5367 ahrens sizeof (zc.zc_value)); 2202 5896 ahl if (!zfs_name_valid(zc.zc_value, ZFS_TYPE_SNAPSHOT)) { 2203 5896 ahl zcmd_free_nvlists(&zc); 2204 5367 ahrens return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2205 5896 ahl } 2206 5367 ahrens 2207 5367 ahrens /* 2208 5367 ahrens * Determine the name of the origin snapshot, store in zc_string. 2209 5367 ahrens */ 2210 5367 ahrens if (drrb->drr_flags & DRR_FLAG_CLONE) { 2211 5367 ahrens if (guid_to_name(hdl, tosnap, 2212 5367 ahrens drrb->drr_fromguid, zc.zc_string) != 0) { 2213 5896 ahl zcmd_free_nvlists(&zc); 2214 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2215 5367 ahrens "local origin for clone %s does not exist"), 2216 5367 ahrens zc.zc_value); 2217 5367 ahrens return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2218 5367 ahrens } 2219 5367 ahrens if (flags.verbose) 2220 5367 ahrens (void) printf("found clone origin %s\n", zc.zc_string); 2221 5367 ahrens } 2222 5367 ahrens 2223 5367 ahrens stream_wantsnewfs = (drrb->drr_fromguid == NULL || 2224 5367 ahrens (drrb->drr_flags & DRR_FLAG_CLONE)); 2225 5367 ahrens 2226 5367 ahrens if (stream_wantsnewfs) { 2227 5367 ahrens /* 2228 5367 ahrens * if the parent fs does not exist, look for it based on 2229 5367 ahrens * the parent snap GUID 2230 5367 ahrens */ 2231 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2232 5367 ahrens "cannot receive new filesystem stream")); 2233 5367 ahrens 2234 5367 ahrens (void) strcpy(zc.zc_name, zc.zc_value); 2235 5367 ahrens cp = strrchr(zc.zc_name, '/'); 2236 5367 ahrens if (cp) 2237 5367 ahrens *cp = '\0'; 2238 5367 ahrens if (cp && 2239 5367 ahrens !zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) { 2240 5367 ahrens char suffix[ZFS_MAXNAMELEN]; 2241 5367 ahrens (void) strcpy(suffix, strrchr(zc.zc_value, '/')); 2242 5367 ahrens if (guid_to_name(hdl, tosnap, parent_snapguid, 2243 5367 ahrens zc.zc_value) == 0) { 2244 5367 ahrens *strchr(zc.zc_value, '@') = '\0'; 2245 5367 ahrens (void) strcat(zc.zc_value, suffix); 2246 5367 ahrens } 2247 5367 ahrens } 2248 5367 ahrens } else { 2249 5367 ahrens /* 2250 5367 ahrens * if the fs does not exist, look for it based on the 2251 5367 ahrens * fromsnap GUID 2252 5367 ahrens */ 2253 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2254 5367 ahrens "cannot receive incremental stream")); 2255 5367 ahrens 2256 5367 ahrens (void) strcpy(zc.zc_name, zc.zc_value); 2257 5367 ahrens *strchr(zc.zc_name, '@') = '\0'; 2258 5367 ahrens 2259 5367 ahrens if (!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) { 2260 5367 ahrens char snap[ZFS_MAXNAMELEN]; 2261 5367 ahrens (void) strcpy(snap, strchr(zc.zc_value, '@')); 2262 5367 ahrens if (guid_to_name(hdl, tosnap, drrb->drr_fromguid, 2263 5367 ahrens zc.zc_value) == 0) { 2264 5367 ahrens *strchr(zc.zc_value, '@') = '\0'; 2265 5367 ahrens (void) strcat(zc.zc_value, snap); 2266 5367 ahrens } 2267 5367 ahrens } 2268 5367 ahrens } 2269 5367 ahrens 2270 5367 ahrens (void) strcpy(zc.zc_name, zc.zc_value); 2271 5367 ahrens *strchr(zc.zc_name, '@') = '\0'; 2272 5367 ahrens 2273 5367 ahrens if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) { 2274 5367 ahrens zfs_handle_t *zhp; 2275 5367 ahrens /* 2276 5367 ahrens * Destination fs exists. Therefore this should either 2277 5367 ahrens * be an incremental, or the stream specifies a new fs 2278 5367 ahrens * (full stream or clone) and they want us to blow it 2279 5367 ahrens * away (and have therefore specified -F and removed any 2280 5367 ahrens * snapshots). 2281 5367 ahrens */ 2282 5367 ahrens 2283 5367 ahrens if (stream_wantsnewfs) { 2284 5367 ahrens if (!flags.force) { 2285 5896 ahl zcmd_free_nvlists(&zc); 2286 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2287 5367 ahrens "destination '%s' exists\n" 2288 5367 ahrens "must specify -F to overwrite it"), 2289 5367 ahrens zc.zc_name); 2290 5367 ahrens return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2291 5367 ahrens } 2292 5367 ahrens if (ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, 2293 5367 ahrens &zc) == 0) { 2294 5896 ahl zcmd_free_nvlists(&zc); 2295 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2296 5367 ahrens "destination has snapshots (eg. %s)\n" 2297 5367 ahrens "must destroy them to overwrite it"), 2298 5367 ahrens zc.zc_name); 2299 5367 ahrens return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2300 5367 ahrens } 2301 5367 ahrens } 2302 5367 ahrens 2303 5896 ahl if ((zhp = zfs_open(hdl, zc.zc_name, 2304 5896 ahl ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) { 2305 5896 ahl zcmd_free_nvlists(&zc); 2306 5367 ahrens return (-1); 2307 5896 ahl } 2308 5896 ahl 2309 5367 ahrens if (stream_wantsnewfs && 2310 5367 ahrens zhp->zfs_dmustats.dds_origin[0]) { 2311 5896 ahl zcmd_free_nvlists(&zc); 2312 5367 ahrens zfs_close(zhp); 2313 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2314 5367 ahrens "destination '%s' is a clone\n" 2315 5367 ahrens "must destroy it to overwrite it"), 2316 5367 ahrens zc.zc_name); 2317 5367 ahrens return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2318 5367 ahrens } 2319 5367 ahrens 2320 5367 ahrens if (!flags.dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM && 2321 5367 ahrens stream_wantsnewfs) { 2322 5367 ahrens /* We can't do online recv in this case */ 2323 7366 Tim clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0); 2324 5896 ahl if (clp == NULL) { 2325 10200 Lori zfs_close(zhp); 2326 5896 ahl zcmd_free_nvlists(&zc); 2327 5367 ahrens return (-1); 2328 5896 ahl } 2329 5367 ahrens if (changelist_prefix(clp) != 0) { 2330 5367 ahrens changelist_free(clp); 2331 10200 Lori zfs_close(zhp); 2332 5896 ahl zcmd_free_nvlists(&zc); 2333 5367 ahrens return (-1); 2334 5367 ahrens } 2335 5367 ahrens } 2336 5367 ahrens zfs_close(zhp); 2337 5367 ahrens } else { 2338 5367 ahrens /* 2339 5896 ahl * Destination filesystem does not exist. Therefore we better 2340 5896 ahl * be creating a new filesystem (either from a full backup, or 2341 5896 ahl * a clone). It would therefore be invalid if the user 2342 5896 ahl * specified only the pool name (i.e. if the destination name 2343 5896 ahl * contained no slash character). 2344 5367 ahrens */ 2345 5896 ahl if (!stream_wantsnewfs || 2346 5896 ahl (cp = strrchr(zc.zc_name, '/')) == NULL) { 2347 5896 ahl zcmd_free_nvlists(&zc); 2348 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2349 5367 ahrens "destination '%s' does not exist"), zc.zc_name); 2350 5367 ahrens return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2351 5367 ahrens } 2352 5367 ahrens 2353 5896 ahl /* 2354 5896 ahl * Trim off the final dataset component so we perform the 2355 5896 ahl * recvbackup ioctl to the filesystems's parent. 2356 5896 ahl */ 2357 5896 ahl *cp = '\0'; 2358 5367 ahrens 2359 5896 ahl if (flags.isprefix && !flags.dryrun && 2360 5896 ahl create_parents(hdl, zc.zc_value, strlen(tosnap)) != 0) { 2361 5896 ahl zcmd_free_nvlists(&zc); 2362 5896 ahl return (zfs_error(hdl, EZFS_BADRESTORE, errbuf)); 2363 5367 ahrens } 2364 5367 ahrens 2365 5367 ahrens newfs = B_TRUE; 2366 5367 ahrens } 2367 5367 ahrens 2368 5367 ahrens zc.zc_begin_record = drr_noswap->drr_u.drr_begin; 2369 5367 ahrens zc.zc_cookie = infd; 2370 5367 ahrens zc.zc_guid = flags.force; 2371 5367 ahrens if (flags.verbose) { 2372 5367 ahrens (void) printf("%s %s stream of %s into %s\n", 2373 5367 ahrens flags.dryrun ? "would receive" : "receiving", 2374 5367 ahrens drrb->drr_fromguid ? "incremental" : "full", 2375 5367 ahrens drrb->drr_toname, zc.zc_value); 2376 5367 ahrens (void) fflush(stdout); 2377 5367 ahrens } 2378 5367 ahrens 2379 5896 ahl if (flags.dryrun) { 2380 5896 ahl zcmd_free_nvlists(&zc); 2381 5367 ahrens return (recv_skip(hdl, infd, flags.byteswap)); 2382 5896 ahl } 2383 5367 ahrens 2384 11022 Tom zc.zc_nvlist_dst = (uint64_t)(uintptr_t)prop_errbuf; 2385 11022 Tom zc.zc_nvlist_dst_size = sizeof (prop_errbuf); 2386 11022 Tom 2387 5367 ahrens err = ioctl_err = zfs_ioctl(hdl, ZFS_IOC_RECV, &zc); 2388 5367 ahrens ioctl_errno = errno; 2389 11022 Tom prop_errflags = (zprop_errflags_t)zc.zc_obj; 2390 11022 Tom 2391 11022 Tom if (err == 0) { 2392 11022 Tom nvlist_t *prop_errors; 2393 11022 Tom VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst, 2394 11022 Tom zc.zc_nvlist_dst_size, &prop_errors, 0)); 2395 11022 Tom 2396 11022 Tom nvpair_t *prop_err = NULL; 2397 11022 Tom 2398 11022 Tom while ((prop_err = nvlist_next_nvpair(prop_errors, 2399 11022 Tom prop_err)) != NULL) { 2400 11022 Tom char tbuf[1024]; 2401 11022 Tom zfs_prop_t prop; 2402 11022 Tom int intval; 2403 11022 Tom 2404 11022 Tom prop = zfs_name_to_prop(nvpair_name(prop_err)); 2405 11022 Tom (void) nvpair_value_int32(prop_err, &intval); 2406 11022 Tom if (strcmp(nvpair_name(prop_err), 2407 11022 Tom ZPROP_N_MORE_ERRORS) == 0) { 2408 11022 Tom trunc_prop_errs(intval); 2409 11022 Tom break; 2410 11022 Tom } else { 2411 11022 Tom (void) snprintf(tbuf, sizeof (tbuf), 2412 11022 Tom dgettext(TEXT_DOMAIN, 2413 11022 Tom "cannot receive %s property on %s"), 2414 11022 Tom nvpair_name(prop_err), zc.zc_name); 2415 11022 Tom zfs_setprop_error(hdl, prop, intval, tbuf); 2416 11022 Tom } 2417 11022 Tom } 2418 11022 Tom nvlist_free(prop_errors); 2419 11022 Tom } 2420 11022 Tom 2421 11022 Tom zc.zc_nvlist_dst = 0; 2422 11022 Tom zc.zc_nvlist_dst_size = 0; 2423 7265 ahrens zcmd_free_nvlists(&zc); 2424 7265 ahrens 2425 7265 ahrens if (err == 0 && snapprops_nvlist) { 2426 7265 ahrens zfs_cmd_t zc2 = { 0 }; 2427 7265 ahrens 2428 7273 ahrens (void) strcpy(zc2.zc_name, zc.zc_value); 2429 11022 Tom zc2.zc_cookie = B_TRUE; /* received */ 2430 7265 ahrens if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) { 2431 7265 ahrens (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc2); 2432 7265 ahrens zcmd_free_nvlists(&zc2); 2433 7265 ahrens } 2434 7265 ahrens } 2435 7265 ahrens 2436 5367 ahrens if (err && (ioctl_errno == ENOENT || ioctl_errno == ENODEV)) { 2437 5367 ahrens /* 2438 5367 ahrens * It may be that this snapshot already exists, 2439 5367 ahrens * in which case we want to consume & ignore it 2440 5367 ahrens * rather than failing. 2441 5367 ahrens */ 2442 5367 ahrens avl_tree_t *local_avl; 2443 5367 ahrens nvlist_t *local_nv, *fs; 2444 5367 ahrens char *cp = strchr(zc.zc_value, '@'); 2445 5367 ahrens 2446 5367 ahrens /* 2447 5367 ahrens * XXX Do this faster by just iterating over snaps in 2448 5367 ahrens * this fs. Also if zc_value does not exist, we will 2449 5367 ahrens * get a strange "does not exist" error message. 2450 5367 ahrens */ 2451 5367 ahrens *cp = '\0'; 2452 11022 Tom if (gather_nvlist(hdl, zc.zc_value, NULL, NULL, B_FALSE, 2453 5367 ahrens &local_nv, &local_avl) == 0) { 2454 5367 ahrens *cp = '@'; 2455 5367 ahrens fs = fsavl_find(local_avl, drrb->drr_toguid, NULL); 2456 5367 ahrens fsavl_destroy(local_avl); 2457 5367 ahrens nvlist_free(local_nv); 2458 5367 ahrens 2459 5367 ahrens if (fs != NULL) { 2460 5367 ahrens if (flags.verbose) { 2461 5367 ahrens (void) printf("snap %s already exists; " 2462 5367 ahrens "ignoring\n", zc.zc_value); 2463 5367 ahrens } 2464 11022 Tom err = ioctl_err = recv_skip(hdl, infd, 2465 5367 ahrens flags.byteswap); 2466 5367 ahrens } 2467 5367 ahrens } 2468 5367 ahrens *cp = '@'; 2469 5367 ahrens } 2470 5367 ahrens 2471 5367 ahrens if (ioctl_err != 0) { 2472 5367 ahrens switch (ioctl_errno) { 2473 5367 ahrens case ENODEV: 2474 5367 ahrens cp = strchr(zc.zc_value, '@'); 2475 5367 ahrens *cp = '\0'; 2476 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2477 5367 ahrens "most recent snapshot of %s does not\n" 2478 5367 ahrens "match incremental source"), zc.zc_value); 2479 5367 ahrens (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 2480 5367 ahrens *cp = '@'; 2481 5367 ahrens break; 2482 5367 ahrens case ETXTBSY: 2483 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2484 5367 ahrens "destination %s has been modified\n" 2485 5367 ahrens "since most recent snapshot"), zc.zc_name); 2486 5367 ahrens (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf); 2487 5367 ahrens break; 2488 5367 ahrens case EEXIST: 2489 5367 ahrens cp = strchr(zc.zc_value, '@'); 2490 5367 ahrens if (newfs) { 2491 5367 ahrens /* it's the containing fs that exists */ 2492 5367 ahrens *cp = '\0'; 2493 5367 ahrens } 2494 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2495 5367 ahrens "destination already exists")); 2496 5367 ahrens (void) zfs_error_fmt(hdl, EZFS_EXISTS, 2497 5367 ahrens dgettext(TEXT_DOMAIN, "cannot restore to %s"), 2498 5367 ahrens zc.zc_value); 2499 5367 ahrens *cp = '@'; 2500 5367 ahrens break; 2501 5367 ahrens case EINVAL: 2502 5367 ahrens (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 2503 5367 ahrens break; 2504 5367 ahrens case ECKSUM: 2505 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2506 5367 ahrens "invalid stream (checksum mismatch)")); 2507 5367 ahrens (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf); 2508 5367 ahrens break; 2509 5367 ahrens default: 2510 5367 ahrens (void) zfs_standard_error(hdl, ioctl_errno, errbuf); 2511 5367 ahrens } 2512 5367 ahrens } 2513 5367 ahrens 2514 5367 ahrens /* 2515 10588 Eric * Mount the target filesystem (if created). Also mount any 2516 10588 Eric * children of the target filesystem if we did a replication 2517 10588 Eric * receive (indicated by stream_avl being non-NULL). 2518 5367 ahrens */ 2519 5367 ahrens cp = strchr(zc.zc_value, '@'); 2520 5367 ahrens if (cp && (ioctl_err == 0 || !newfs)) { 2521 5367 ahrens zfs_handle_t *h; 2522 5367 ahrens 2523 5367 ahrens *cp = '\0'; 2524 5367 ahrens h = zfs_open(hdl, zc.zc_value, 2525 5367 ahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2526 6476 ahl if (h != NULL) { 2527 5367 ahrens if (h->zfs_type == ZFS_TYPE_VOLUME) { 2528 7366 Tim *cp = '@'; 2529 10200 Lori } else if (newfs || stream_avl) { 2530 7366 Tim /* 2531 7366 Tim * Track the first/top of hierarchy fs, 2532 7366 Tim * for mounting and sharing later. 2533 7366 Tim */ 2534 7366 Tim if (top_zfs && *top_zfs == NULL) 2535 7366 Tim *top_zfs = zfs_strdup(hdl, zc.zc_value); 2536 5367 ahrens } 2537 6476 ahl zfs_close(h); 2538 5367 ahrens } 2539 7366 Tim *cp = '@'; 2540 5367 ahrens } 2541 5367 ahrens 2542 5367 ahrens if (clp) { 2543 5367 ahrens err |= changelist_postfix(clp); 2544 5367 ahrens changelist_free(clp); 2545 11022 Tom } 2546 11022 Tom 2547 11022 Tom if (prop_errflags & ZPROP_ERR_NOCLEAR) { 2548 11022 Tom (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: " 2549 11022 Tom "failed to clear unreceived properties on %s"), 2550 11022 Tom zc.zc_name); 2551 11022 Tom (void) fprintf(stderr, "\n"); 2552 11022 Tom } 2553 11022 Tom if (prop_errflags & ZPROP_ERR_NORESTORE) { 2554 11022 Tom (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: " 2555 11022 Tom "failed to restore original properties on %s"), 2556 11022 Tom zc.zc_name); 2557 11022 Tom (void) fprintf(stderr, "\n"); 2558 5367 ahrens } 2559 5367 ahrens 2560 5367 ahrens if (err || ioctl_err) 2561 5367 ahrens return (-1); 2562 5367 ahrens 2563 5367 ahrens if (flags.verbose) { 2564 5367 ahrens char buf1[64]; 2565 5367 ahrens char buf2[64]; 2566 5367 ahrens uint64_t bytes = zc.zc_cookie; 2567 5367 ahrens time_t delta = time(NULL) - begin_time; 2568 5367 ahrens if (delta == 0) 2569 5367 ahrens delta = 1; 2570 5367 ahrens zfs_nicenum(bytes, buf1, sizeof (buf1)); 2571 5367 ahrens zfs_nicenum(bytes/delta, buf2, sizeof (buf1)); 2572 5367 ahrens 2573 5367 ahrens (void) printf("received %sB stream in %lu seconds (%sB/sec)\n", 2574 5367 ahrens buf1, delta, buf2); 2575 5367 ahrens } 2576 5367 ahrens 2577 5367 ahrens return (0); 2578 5367 ahrens } 2579 5367 ahrens 2580 7366 Tim static int 2581 7366 Tim zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags, 2582 7366 Tim int infd, avl_tree_t *stream_avl, char **top_zfs) 2583 5367 ahrens { 2584 5367 ahrens int err; 2585 5367 ahrens dmu_replay_record_t drr, drr_noswap; 2586 5367 ahrens struct drr_begin *drrb = &drr.drr_u.drr_begin; 2587 5367 ahrens char errbuf[1024]; 2588 5367 ahrens zio_cksum_t zcksum = { 0 }; 2589 11007 Lori uint64_t featureflags; 2590 11007 Lori int hdrtype; 2591 5367 ahrens 2592 5367 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2593 5367 ahrens "cannot receive")); 2594 5367 ahrens 2595 5367 ahrens if (flags.isprefix && 2596 5367 ahrens !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) { 2597 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs " 2598 5367 ahrens "(%s) does not exist"), tosnap); 2599 5367 ahrens return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2600 5367 ahrens } 2601 5367 ahrens 2602 5367 ahrens /* read in the BEGIN record */ 2603 5367 ahrens if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE, 2604 5367 ahrens &zcksum))) 2605 5367 ahrens return (err); 2606 5367 ahrens 2607 5367 ahrens if (drr.drr_type == DRR_END || drr.drr_type == BSWAP_32(DRR_END)) { 2608 5367 ahrens /* It's the double end record at the end of a package */ 2609 5367 ahrens return (ENODATA); 2610 5367 ahrens } 2611 5367 ahrens 2612 5367 ahrens /* the kernel needs the non-byteswapped begin record */ 2613 5367 ahrens drr_noswap = drr; 2614 5367 ahrens 2615 5446 ahrens flags.byteswap = B_FALSE; 2616 5367 ahrens if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) { 2617 5367 ahrens /* 2618 5367 ahrens * We computed the checksum in the wrong byteorder in 2619 5367 ahrens * recv_read() above; do it again correctly. 2620 5367 ahrens */ 2621 5367 ahrens bzero(&zcksum, sizeof (zio_cksum_t)); 2622 5367 ahrens fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum); 2623 5367 ahrens flags.byteswap = B_TRUE; 2624 5367 ahrens 2625 5367 ahrens drr.drr_type = BSWAP_32(drr.drr_type); 2626 5367 ahrens drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen); 2627 5367 ahrens drrb->drr_magic = BSWAP_64(drrb->drr_magic); 2628 11007 Lori drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo); 2629 5367 ahrens drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time); 2630 5367 ahrens drrb->drr_type = BSWAP_32(drrb->drr_type); 2631 5367 ahrens drrb->drr_flags = BSWAP_32(drrb->drr_flags); 2632 5367 ahrens drrb->drr_toguid = BSWAP_64(drrb->drr_toguid); 2633 5367 ahrens drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid); 2634 5367 ahrens } 2635 5367 ahrens 2636 5367 ahrens if (drrb->drr_magic != DMU_BACKUP_MAGIC || drr.drr_type != DRR_BEGIN) { 2637 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 2638 5367 ahrens "stream (bad magic number)")); 2639 5367 ahrens return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2640 5367 ahrens } 2641 5367 ahrens 2642 11007 Lori featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); 2643 11007 Lori hdrtype = DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo); 2644 11007 Lori 2645 11007 Lori if (!DMU_STREAM_SUPPORTED(featureflags) || 2646 11007 Lori (hdrtype != DMU_SUBSTREAM && hdrtype != DMU_COMPOUNDSTREAM)) { 2647 11007 Lori zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2648 11007 Lori "stream has unsupported feature, feature flags = %lx"), 2649 11007 Lori featureflags); 2650 11007 Lori return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2651 11007 Lori } 2652 11007 Lori 2653 5367 ahrens if (strchr(drrb->drr_toname, '@') == NULL) { 2654 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " 2655 5367 ahrens "stream (bad snapshot name)")); 2656 5367 ahrens return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); 2657 5367 ahrens } 2658 5367 ahrens 2659 11007 Lori if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) { 2660 5367 ahrens return (zfs_receive_one(hdl, infd, tosnap, flags, 2661 7366 Tim &drr, &drr_noswap, stream_avl, top_zfs)); 2662 11007 Lori } else { /* must be DMU_COMPOUNDSTREAM */ 2663 11007 Lori assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == 2664 11007 Lori DMU_COMPOUNDSTREAM); 2665 5367 ahrens return (zfs_receive_package(hdl, infd, tosnap, flags, 2666 7366 Tim &drr, &zcksum, top_zfs)); 2667 5367 ahrens } 2668 5367 ahrens } 2669 7366 Tim 2670 7366 Tim /* 2671 7366 Tim * Restores a backup of tosnap from the file descriptor specified by infd. 2672 7366 Tim * Return 0 on total success, -2 if some things couldn't be 2673 7366 Tim * destroyed/renamed/promoted, -1 if some things couldn't be received. 2674 7366 Tim * (-1 will override -2). 2675 7366 Tim */ 2676 7366 Tim int 2677 7366 Tim zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags, 2678 7366 Tim int infd, avl_tree_t *stream_avl) 2679 7366 Tim { 2680 7366 Tim char *top_zfs = NULL; 2681 7366 Tim int err; 2682 7366 Tim 2683 7366 Tim err = zfs_receive_impl(hdl, tosnap, flags, infd, stream_avl, &top_zfs); 2684 7366 Tim 2685 8584 Lori if (err == 0 && !flags.nomount && top_zfs) { 2686 7366 Tim zfs_handle_t *zhp; 2687 7366 Tim prop_changelist_t *clp; 2688 7366 Tim 2689 7366 Tim zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM); 2690 7366 Tim if (zhp != NULL) { 2691 7366 Tim clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, 2692 7366 Tim CL_GATHER_MOUNT_ALWAYS, 0); 2693 7366 Tim zfs_close(zhp); 2694 7366 Tim if (clp != NULL) { 2695 7366 Tim /* mount and share received datasets */ 2696 7366 Tim err = changelist_postfix(clp); 2697 7366 Tim changelist_free(clp); 2698 7366 Tim } 2699 7366 Tim } 2700 7366 Tim if (zhp == NULL || clp == NULL || err) 2701 7366 Tim err = -1; 2702 7366 Tim } 2703 7366 Tim if (top_zfs) 2704 7366 Tim free(top_zfs); 2705 7366 Tim 2706 7366 Tim return (err); 2707 7366 Tim } 2708