Print this page
    
4986 receiving replication stream fails if any snapshot exceeds refquota
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libzfs/common/libzfs_sendrecv.c
          +++ new/usr/src/lib/libzfs/common/libzfs_sendrecv.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  25   25   * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  26   26   * Copyright (c) 2013 Steven Hartland. All rights reserved.
       27 + * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
  27   28   */
  28   29  
  29   30  #include <assert.h>
  30   31  #include <ctype.h>
  31   32  #include <errno.h>
  32   33  #include <libintl.h>
  33   34  #include <stdio.h>
  34   35  #include <stdlib.h>
  35   36  #include <strings.h>
  36   37  #include <unistd.h>
  37   38  #include <stddef.h>
  38   39  #include <fcntl.h>
  39   40  #include <sys/mount.h>
  40   41  #include <pthread.h>
  41   42  #include <umem.h>
  42   43  #include <time.h>
  43   44  
  44   45  #include <libzfs.h>
  45   46  #include <libzfs_core.h>
  46   47  
  47   48  #include "zfs_namecheck.h"
  48   49  #include "zfs_prop.h"
  49   50  #include "zfs_fletcher.h"
  50   51  #include "libzfs_impl.h"
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
  51   52  #include <zlib.h>
  52   53  #include <sha2.h>
  53   54  #include <sys/zio_checksum.h>
  54   55  #include <sys/ddt.h>
  55   56  
  56   57  /* in libzfs_dataset.c */
  57   58  extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
  58   59  
  59   60  static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
  60   61      recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
  61      -    uint64_t *);
       62 +    uint64_t *, const char *);
  62   63  static int guid_to_name(libzfs_handle_t *, const char *,
  63   64      uint64_t, boolean_t, char *);
  64   65  
  65   66  static const zio_cksum_t zero_cksum = { 0 };
  66   67  
  67   68  typedef struct dedup_arg {
  68   69          int     inputfd;
  69   70          int     outputfd;
  70   71          libzfs_handle_t  *dedup_hdl;
  71   72  } dedup_arg_t;
  72   73  
  73   74  typedef struct progress_arg {
  74   75          zfs_handle_t *pa_zhp;
  75   76          int pa_fd;
  76   77          boolean_t pa_parsable;
  77   78  } progress_arg_t;
  78   79  
  79   80  typedef struct dataref {
  80   81          uint64_t ref_guid;
  81   82          uint64_t ref_object;
  82   83          uint64_t ref_offset;
  83   84  } dataref_t;
  84   85  
  85   86  typedef struct dedup_entry {
  86   87          struct dedup_entry      *dde_next;
  87   88          zio_cksum_t dde_chksum;
  88   89          uint64_t dde_prop;
  89   90          dataref_t dde_ref;
  90   91  } dedup_entry_t;
  91   92  
  92   93  #define MAX_DDT_PHYSMEM_PERCENT         20
  93   94  #define SMALLEST_POSSIBLE_MAX_DDT_MB            128
  94   95  
  95   96  typedef struct dedup_table {
  96   97          dedup_entry_t   **dedup_hash_array;
  97   98          umem_cache_t    *ddecache;
  98   99          uint64_t        max_ddt_size;  /* max dedup table size in bytes */
  99  100          uint64_t        cur_ddt_size;  /* current dedup table size in bytes */
 100  101          uint64_t        ddt_count;
 101  102          int             numhashbits;
 102  103          boolean_t       ddt_full;
 103  104  } dedup_table_t;
 104  105  
 105  106  static int
 106  107  high_order_bit(uint64_t n)
 107  108  {
 108  109          int count;
 109  110  
 110  111          for (count = 0; n != 0; count++)
 111  112                  n >>= 1;
 112  113          return (count);
 113  114  }
 114  115  
 115  116  static size_t
 116  117  ssread(void *buf, size_t len, FILE *stream)
 117  118  {
 118  119          size_t outlen;
 119  120  
 120  121          if ((outlen = fread(buf, len, 1, stream)) == 0)
 121  122                  return (0);
 122  123  
 123  124          return (outlen);
 124  125  }
 125  126  
 126  127  static void
 127  128  ddt_hash_append(libzfs_handle_t *hdl, dedup_table_t *ddt, dedup_entry_t **ddepp,
 128  129      zio_cksum_t *cs, uint64_t prop, dataref_t *dr)
 129  130  {
 130  131          dedup_entry_t   *dde;
 131  132  
 132  133          if (ddt->cur_ddt_size >= ddt->max_ddt_size) {
 133  134                  if (ddt->ddt_full == B_FALSE) {
 134  135                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 135  136                              "Dedup table full.  Deduplication will continue "
 136  137                              "with existing table entries"));
 137  138                          ddt->ddt_full = B_TRUE;
 138  139                  }
 139  140                  return;
 140  141          }
 141  142  
 142  143          if ((dde = umem_cache_alloc(ddt->ddecache, UMEM_DEFAULT))
 143  144              != NULL) {
 144  145                  assert(*ddepp == NULL);
 145  146                  dde->dde_next = NULL;
 146  147                  dde->dde_chksum = *cs;
 147  148                  dde->dde_prop = prop;
 148  149                  dde->dde_ref = *dr;
 149  150                  *ddepp = dde;
 150  151                  ddt->cur_ddt_size += sizeof (dedup_entry_t);
 151  152                  ddt->ddt_count++;
 152  153          }
 153  154  }
 154  155  
 155  156  /*
 156  157   * Using the specified dedup table, do a lookup for an entry with
 157  158   * the checksum cs.  If found, return the block's reference info
 158  159   * in *dr. Otherwise, insert a new entry in the dedup table, using
 159  160   * the reference information specified by *dr.
 160  161   *
 161  162   * return value:  true - entry was found
 162  163   *                false - entry was not found
 163  164   */
 164  165  static boolean_t
 165  166  ddt_update(libzfs_handle_t *hdl, dedup_table_t *ddt, zio_cksum_t *cs,
 166  167      uint64_t prop, dataref_t *dr)
 167  168  {
 168  169          uint32_t hashcode;
 169  170          dedup_entry_t **ddepp;
 170  171  
 171  172          hashcode = BF64_GET(cs->zc_word[0], 0, ddt->numhashbits);
 172  173  
 173  174          for (ddepp = &(ddt->dedup_hash_array[hashcode]); *ddepp != NULL;
 174  175              ddepp = &((*ddepp)->dde_next)) {
 175  176                  if (ZIO_CHECKSUM_EQUAL(((*ddepp)->dde_chksum), *cs) &&
 176  177                      (*ddepp)->dde_prop == prop) {
 177  178                          *dr = (*ddepp)->dde_ref;
 178  179                          return (B_TRUE);
 179  180                  }
 180  181          }
 181  182          ddt_hash_append(hdl, ddt, ddepp, cs, prop, dr);
 182  183          return (B_FALSE);
 183  184  }
 184  185  
 185  186  static int
 186  187  dump_record(dmu_replay_record_t *drr, void *payload, int payload_len,
 187  188      zio_cksum_t *zc, int outfd)
 188  189  {
 189  190          ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
 190  191              ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
 191  192          fletcher_4_incremental_native(drr,
 192  193              offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc);
 193  194          if (drr->drr_type != DRR_BEGIN) {
 194  195                  ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.
 195  196                      drr_checksum.drr_checksum));
 196  197                  drr->drr_u.drr_checksum.drr_checksum = *zc;
 197  198          }
 198  199          fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum,
 199  200              sizeof (zio_cksum_t), zc);
 200  201          if (write(outfd, drr, sizeof (*drr)) == -1)
 201  202                  return (errno);
 202  203          if (payload_len != 0) {
 203  204                  fletcher_4_incremental_native(payload, payload_len, zc);
 204  205                  if (write(outfd, payload, payload_len) == -1)
 205  206                          return (errno);
 206  207          }
 207  208          return (0);
 208  209  }
 209  210  
 210  211  /*
 211  212   * This function is started in a separate thread when the dedup option
 212  213   * has been requested.  The main send thread determines the list of
 213  214   * snapshots to be included in the send stream and makes the ioctl calls
 214  215   * for each one.  But instead of having the ioctl send the output to the
 215  216   * the output fd specified by the caller of zfs_send()), the
 216  217   * ioctl is told to direct the output to a pipe, which is read by the
 217  218   * alternate thread running THIS function.  This function does the
 218  219   * dedup'ing by:
 219  220   *  1. building a dedup table (the DDT)
 220  221   *  2. doing checksums on each data block and inserting a record in the DDT
 221  222   *  3. looking for matching checksums, and
 222  223   *  4.  sending a DRR_WRITE_BYREF record instead of a write record whenever
 223  224   *      a duplicate block is found.
 224  225   * The output of this function then goes to the output fd requested
 225  226   * by the caller of zfs_send().
 226  227   */
 227  228  static void *
 228  229  cksummer(void *arg)
 229  230  {
 230  231          dedup_arg_t *dda = arg;
 231  232          char *buf = zfs_alloc(dda->dedup_hdl, SPA_MAXBLOCKSIZE);
 232  233          dmu_replay_record_t thedrr;
 233  234          dmu_replay_record_t *drr = &thedrr;
 234  235          FILE *ofp;
 235  236          int outfd;
 236  237          dedup_table_t ddt;
 237  238          zio_cksum_t stream_cksum;
 238  239          uint64_t physmem = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE);
 239  240          uint64_t numbuckets;
 240  241  
 241  242          ddt.max_ddt_size =
 242  243              MAX((physmem * MAX_DDT_PHYSMEM_PERCENT) / 100,
 243  244              SMALLEST_POSSIBLE_MAX_DDT_MB << 20);
 244  245  
 245  246          numbuckets = ddt.max_ddt_size / (sizeof (dedup_entry_t));
 246  247  
 247  248          /*
 248  249           * numbuckets must be a power of 2.  Increase number to
 249  250           * a power of 2 if necessary.
 250  251           */
 251  252          if (!ISP2(numbuckets))
 252  253                  numbuckets = 1 << high_order_bit(numbuckets);
 253  254  
 254  255          ddt.dedup_hash_array = calloc(numbuckets, sizeof (dedup_entry_t *));
 255  256          ddt.ddecache = umem_cache_create("dde", sizeof (dedup_entry_t), 0,
 256  257              NULL, NULL, NULL, NULL, NULL, 0);
 257  258          ddt.cur_ddt_size = numbuckets * sizeof (dedup_entry_t *);
 258  259          ddt.numhashbits = high_order_bit(numbuckets) - 1;
 259  260          ddt.ddt_full = B_FALSE;
 260  261  
 261  262          outfd = dda->outputfd;
 262  263          ofp = fdopen(dda->inputfd, "r");
 263  264          while (ssread(drr, sizeof (*drr), ofp) != 0) {
 264  265  
 265  266                  switch (drr->drr_type) {
 266  267                  case DRR_BEGIN:
 267  268                  {
 268  269                          struct drr_begin *drrb = &drr->drr_u.drr_begin;
 269  270                          int fflags;
 270  271                          int sz = 0;
 271  272                          ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
 272  273  
 273  274                          ASSERT3U(drrb->drr_magic, ==, DMU_BACKUP_MAGIC);
 274  275  
 275  276                          /* set the DEDUP feature flag for this stream */
 276  277                          fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
 277  278                          fflags |= (DMU_BACKUP_FEATURE_DEDUP |
 278  279                              DMU_BACKUP_FEATURE_DEDUPPROPS);
 279  280                          DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
 280  281  
 281  282                          if (drr->drr_payloadlen != 0) {
 282  283                                  sz = drr->drr_payloadlen;
 283  284  
 284  285                                  if (sz > SPA_MAXBLOCKSIZE) {
 285  286                                          buf = zfs_realloc(dda->dedup_hdl, buf,
 286  287                                              SPA_MAXBLOCKSIZE, sz);
 287  288                                  }
 288  289                                  (void) ssread(buf, sz, ofp);
 289  290                                  if (ferror(stdin))
 290  291                                          perror("fread");
 291  292                          }
 292  293                          if (dump_record(drr, buf, sz, &stream_cksum,
 293  294                              outfd) != 0)
 294  295                                  goto out;
 295  296                          break;
 296  297                  }
 297  298  
 298  299                  case DRR_END:
 299  300                  {
 300  301                          struct drr_end *drre = &drr->drr_u.drr_end;
 301  302                          /* use the recalculated checksum */
 302  303                          drre->drr_checksum = stream_cksum;
 303  304                          if (dump_record(drr, NULL, 0, &stream_cksum,
 304  305                              outfd) != 0)
 305  306                                  goto out;
 306  307                          break;
 307  308                  }
 308  309  
 309  310                  case DRR_OBJECT:
 310  311                  {
 311  312                          struct drr_object *drro = &drr->drr_u.drr_object;
 312  313                          if (drro->drr_bonuslen > 0) {
 313  314                                  (void) ssread(buf,
 314  315                                      P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
 315  316                                      ofp);
 316  317                          }
 317  318                          if (dump_record(drr, buf,
 318  319                              P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
 319  320                              &stream_cksum, outfd) != 0)
 320  321                                  goto out;
 321  322                          break;
 322  323                  }
 323  324  
 324  325                  case DRR_SPILL:
 325  326                  {
 326  327                          struct drr_spill *drrs = &drr->drr_u.drr_spill;
 327  328                          (void) ssread(buf, drrs->drr_length, ofp);
 328  329                          if (dump_record(drr, buf, drrs->drr_length,
 329  330                              &stream_cksum, outfd) != 0)
 330  331                                  goto out;
 331  332                          break;
 332  333                  }
 333  334  
 334  335                  case DRR_FREEOBJECTS:
 335  336                  {
 336  337                          if (dump_record(drr, NULL, 0, &stream_cksum,
 337  338                              outfd) != 0)
 338  339                                  goto out;
 339  340                          break;
 340  341                  }
 341  342  
 342  343                  case DRR_WRITE:
 343  344                  {
 344  345                          struct drr_write *drrw = &drr->drr_u.drr_write;
 345  346                          dataref_t       dataref;
 346  347  
 347  348                          (void) ssread(buf, drrw->drr_length, ofp);
 348  349  
 349  350                          /*
 350  351                           * Use the existing checksum if it's dedup-capable,
 351  352                           * else calculate a SHA256 checksum for it.
 352  353                           */
 353  354  
 354  355                          if (ZIO_CHECKSUM_EQUAL(drrw->drr_key.ddk_cksum,
 355  356                              zero_cksum) ||
 356  357                              !DRR_IS_DEDUP_CAPABLE(drrw->drr_checksumflags)) {
 357  358                                  SHA256_CTX      ctx;
 358  359                                  zio_cksum_t     tmpsha256;
 359  360  
 360  361                                  SHA256Init(&ctx);
 361  362                                  SHA256Update(&ctx, buf, drrw->drr_length);
 362  363                                  SHA256Final(&tmpsha256, &ctx);
 363  364                                  drrw->drr_key.ddk_cksum.zc_word[0] =
 364  365                                      BE_64(tmpsha256.zc_word[0]);
 365  366                                  drrw->drr_key.ddk_cksum.zc_word[1] =
 366  367                                      BE_64(tmpsha256.zc_word[1]);
 367  368                                  drrw->drr_key.ddk_cksum.zc_word[2] =
 368  369                                      BE_64(tmpsha256.zc_word[2]);
 369  370                                  drrw->drr_key.ddk_cksum.zc_word[3] =
 370  371                                      BE_64(tmpsha256.zc_word[3]);
 371  372                                  drrw->drr_checksumtype = ZIO_CHECKSUM_SHA256;
 372  373                                  drrw->drr_checksumflags = DRR_CHECKSUM_DEDUP;
 373  374                          }
 374  375  
 375  376                          dataref.ref_guid = drrw->drr_toguid;
 376  377                          dataref.ref_object = drrw->drr_object;
 377  378                          dataref.ref_offset = drrw->drr_offset;
 378  379  
 379  380                          if (ddt_update(dda->dedup_hdl, &ddt,
 380  381                              &drrw->drr_key.ddk_cksum, drrw->drr_key.ddk_prop,
 381  382                              &dataref)) {
 382  383                                  dmu_replay_record_t wbr_drr = {0};
 383  384                                  struct drr_write_byref *wbr_drrr =
 384  385                                      &wbr_drr.drr_u.drr_write_byref;
 385  386  
 386  387                                  /* block already present in stream */
 387  388                                  wbr_drr.drr_type = DRR_WRITE_BYREF;
 388  389  
 389  390                                  wbr_drrr->drr_object = drrw->drr_object;
 390  391                                  wbr_drrr->drr_offset = drrw->drr_offset;
 391  392                                  wbr_drrr->drr_length = drrw->drr_length;
 392  393                                  wbr_drrr->drr_toguid = drrw->drr_toguid;
 393  394                                  wbr_drrr->drr_refguid = dataref.ref_guid;
 394  395                                  wbr_drrr->drr_refobject =
 395  396                                      dataref.ref_object;
 396  397                                  wbr_drrr->drr_refoffset =
 397  398                                      dataref.ref_offset;
 398  399  
 399  400                                  wbr_drrr->drr_checksumtype =
 400  401                                      drrw->drr_checksumtype;
 401  402                                  wbr_drrr->drr_checksumflags =
 402  403                                      drrw->drr_checksumtype;
 403  404                                  wbr_drrr->drr_key.ddk_cksum =
 404  405                                      drrw->drr_key.ddk_cksum;
 405  406                                  wbr_drrr->drr_key.ddk_prop =
 406  407                                      drrw->drr_key.ddk_prop;
 407  408  
 408  409                                  if (dump_record(&wbr_drr, NULL, 0,
 409  410                                      &stream_cksum, outfd) != 0)
 410  411                                          goto out;
 411  412                          } else {
 412  413                                  /* block not previously seen */
 413  414                                  if (dump_record(drr, buf, drrw->drr_length,
 414  415                                      &stream_cksum, outfd) != 0)
 415  416                                          goto out;
 416  417                          }
 417  418                          break;
 418  419                  }
 419  420  
 420  421                  case DRR_WRITE_EMBEDDED:
 421  422                  {
 422  423                          struct drr_write_embedded *drrwe =
 423  424                              &drr->drr_u.drr_write_embedded;
 424  425                          (void) ssread(buf,
 425  426                              P2ROUNDUP((uint64_t)drrwe->drr_psize, 8), ofp);
 426  427                          if (dump_record(drr, buf,
 427  428                              P2ROUNDUP((uint64_t)drrwe->drr_psize, 8),
 428  429                              &stream_cksum, outfd) != 0)
 429  430                                  goto out;
 430  431                          break;
 431  432                  }
 432  433  
 433  434                  case DRR_FREE:
 434  435                  {
 435  436                          if (dump_record(drr, NULL, 0, &stream_cksum,
 436  437                              outfd) != 0)
 437  438                                  goto out;
 438  439                          break;
 439  440                  }
 440  441  
 441  442                  default:
 442  443                          (void) fprintf(stderr, "INVALID record type 0x%x\n",
 443  444                              drr->drr_type);
 444  445                          /* should never happen, so assert */
 445  446                          assert(B_FALSE);
 446  447                  }
 447  448          }
 448  449  out:
 449  450          umem_cache_destroy(ddt.ddecache);
 450  451          free(ddt.dedup_hash_array);
 451  452          free(buf);
 452  453          (void) fclose(ofp);
 453  454  
 454  455          return (NULL);
 455  456  }
 456  457  
 457  458  /*
 458  459   * Routines for dealing with the AVL tree of fs-nvlists
 459  460   */
 460  461  typedef struct fsavl_node {
 461  462          avl_node_t fn_node;
 462  463          nvlist_t *fn_nvfs;
 463  464          char *fn_snapname;
 464  465          uint64_t fn_guid;
 465  466  } fsavl_node_t;
 466  467  
 467  468  static int
 468  469  fsavl_compare(const void *arg1, const void *arg2)
 469  470  {
 470  471          const fsavl_node_t *fn1 = arg1;
 471  472          const fsavl_node_t *fn2 = arg2;
 472  473  
 473  474          if (fn1->fn_guid > fn2->fn_guid)
 474  475                  return (+1);
 475  476          else if (fn1->fn_guid < fn2->fn_guid)
 476  477                  return (-1);
 477  478          else
 478  479                  return (0);
 479  480  }
 480  481  
 481  482  /*
 482  483   * Given the GUID of a snapshot, find its containing filesystem and
 483  484   * (optionally) name.
 484  485   */
 485  486  static nvlist_t *
 486  487  fsavl_find(avl_tree_t *avl, uint64_t snapguid, char **snapname)
 487  488  {
 488  489          fsavl_node_t fn_find;
 489  490          fsavl_node_t *fn;
 490  491  
 491  492          fn_find.fn_guid = snapguid;
 492  493  
 493  494          fn = avl_find(avl, &fn_find, NULL);
 494  495          if (fn) {
 495  496                  if (snapname)
 496  497                          *snapname = fn->fn_snapname;
 497  498                  return (fn->fn_nvfs);
 498  499          }
 499  500          return (NULL);
 500  501  }
 501  502  
 502  503  static void
 503  504  fsavl_destroy(avl_tree_t *avl)
 504  505  {
 505  506          fsavl_node_t *fn;
 506  507          void *cookie;
 507  508  
 508  509          if (avl == NULL)
 509  510                  return;
 510  511  
 511  512          cookie = NULL;
 512  513          while ((fn = avl_destroy_nodes(avl, &cookie)) != NULL)
 513  514                  free(fn);
 514  515          avl_destroy(avl);
 515  516          free(avl);
 516  517  }
 517  518  
 518  519  /*
 519  520   * Given an nvlist, produce an avl tree of snapshots, ordered by guid
 520  521   */
 521  522  static avl_tree_t *
 522  523  fsavl_create(nvlist_t *fss)
 523  524  {
 524  525          avl_tree_t *fsavl;
 525  526          nvpair_t *fselem = NULL;
 526  527  
 527  528          if ((fsavl = malloc(sizeof (avl_tree_t))) == NULL)
 528  529                  return (NULL);
 529  530  
 530  531          avl_create(fsavl, fsavl_compare, sizeof (fsavl_node_t),
 531  532              offsetof(fsavl_node_t, fn_node));
 532  533  
 533  534          while ((fselem = nvlist_next_nvpair(fss, fselem)) != NULL) {
 534  535                  nvlist_t *nvfs, *snaps;
 535  536                  nvpair_t *snapelem = NULL;
 536  537  
 537  538                  VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
 538  539                  VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
 539  540  
 540  541                  while ((snapelem =
 541  542                      nvlist_next_nvpair(snaps, snapelem)) != NULL) {
 542  543                          fsavl_node_t *fn;
 543  544                          uint64_t guid;
 544  545  
 545  546                          VERIFY(0 == nvpair_value_uint64(snapelem, &guid));
 546  547                          if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) {
 547  548                                  fsavl_destroy(fsavl);
 548  549                                  return (NULL);
 549  550                          }
 550  551                          fn->fn_nvfs = nvfs;
 551  552                          fn->fn_snapname = nvpair_name(snapelem);
 552  553                          fn->fn_guid = guid;
 553  554  
 554  555                          /*
 555  556                           * Note: if there are multiple snaps with the
 556  557                           * same GUID, we ignore all but one.
 557  558                           */
 558  559                          if (avl_find(fsavl, fn, NULL) == NULL)
 559  560                                  avl_add(fsavl, fn);
 560  561                          else
 561  562                                  free(fn);
 562  563                  }
 563  564          }
 564  565  
 565  566          return (fsavl);
 566  567  }
 567  568  
 568  569  /*
 569  570   * Routines for dealing with the giant nvlist of fs-nvlists, etc.
 570  571   */
 571  572  typedef struct send_data {
 572  573          uint64_t parent_fromsnap_guid;
 573  574          nvlist_t *parent_snaps;
 574  575          nvlist_t *fss;
 575  576          nvlist_t *snapprops;
 576  577          const char *fromsnap;
 577  578          const char *tosnap;
 578  579          boolean_t recursive;
 579  580  
 580  581          /*
 581  582           * The header nvlist is of the following format:
 582  583           * {
 583  584           *   "tosnap" -> string
 584  585           *   "fromsnap" -> string (if incremental)
 585  586           *   "fss" -> {
 586  587           *      id -> {
 587  588           *
 588  589           *       "name" -> string (full name; for debugging)
 589  590           *       "parentfromsnap" -> number (guid of fromsnap in parent)
 590  591           *
 591  592           *       "props" -> { name -> value (only if set here) }
 592  593           *       "snaps" -> { name (lastname) -> number (guid) }
 593  594           *       "snapprops" -> { name (lastname) -> { name -> value } }
 594  595           *
 595  596           *       "origin" -> number (guid) (if clone)
 596  597           *       "sent" -> boolean (not on-disk)
 597  598           *      }
 598  599           *   }
 599  600           * }
 600  601           *
 601  602           */
 602  603  } send_data_t;
 603  604  
 604  605  static void send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv);
 605  606  
 606  607  static int
 607  608  send_iterate_snap(zfs_handle_t *zhp, void *arg)
 608  609  {
 609  610          send_data_t *sd = arg;
 610  611          uint64_t guid = zhp->zfs_dmustats.dds_guid;
 611  612          char *snapname;
 612  613          nvlist_t *nv;
 613  614  
 614  615          snapname = strrchr(zhp->zfs_name, '@')+1;
 615  616  
 616  617          VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
 617  618          /*
 618  619           * NB: if there is no fromsnap here (it's a newly created fs in
 619  620           * an incremental replication), we will substitute the tosnap.
 620  621           */
 621  622          if ((sd->fromsnap && strcmp(snapname, sd->fromsnap) == 0) ||
 622  623              (sd->parent_fromsnap_guid == 0 && sd->tosnap &&
 623  624              strcmp(snapname, sd->tosnap) == 0)) {
 624  625                  sd->parent_fromsnap_guid = guid;
 625  626          }
 626  627  
 627  628          VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
 628  629          send_iterate_prop(zhp, nv);
 629  630          VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv));
 630  631          nvlist_free(nv);
 631  632  
 632  633          zfs_close(zhp);
 633  634          return (0);
 634  635  }
 635  636  
 636  637  static void
 637  638  send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
 638  639  {
 639  640          nvpair_t *elem = NULL;
 640  641  
 641  642          while ((elem = nvlist_next_nvpair(zhp->zfs_props, elem)) != NULL) {
 642  643                  char *propname = nvpair_name(elem);
 643  644                  zfs_prop_t prop = zfs_name_to_prop(propname);
 644  645                  nvlist_t *propnv;
 645  646  
 646  647                  if (!zfs_prop_user(propname)) {
 647  648                          /*
 648  649                           * Realistically, this should never happen.  However,
 649  650                           * we want the ability to add DSL properties without
 650  651                           * needing to make incompatible version changes.  We
 651  652                           * need to ignore unknown properties to allow older
 652  653                           * software to still send datasets containing these
 653  654                           * properties, with the unknown properties elided.
 654  655                           */
 655  656                          if (prop == ZPROP_INVAL)
 656  657                                  continue;
 657  658  
 658  659                          if (zfs_prop_readonly(prop))
 659  660                                  continue;
 660  661                  }
 661  662  
 662  663                  verify(nvpair_value_nvlist(elem, &propnv) == 0);
 663  664                  if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION ||
 664  665                      prop == ZFS_PROP_REFQUOTA ||
 665  666                      prop == ZFS_PROP_REFRESERVATION) {
 666  667                          char *source;
 667  668                          uint64_t value;
 668  669                          verify(nvlist_lookup_uint64(propnv,
 669  670                              ZPROP_VALUE, &value) == 0);
 670  671                          if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
 671  672                                  continue;
 672  673                          /*
 673  674                           * May have no source before SPA_VERSION_RECVD_PROPS,
 674  675                           * but is still modifiable.
 675  676                           */
 676  677                          if (nvlist_lookup_string(propnv,
 677  678                              ZPROP_SOURCE, &source) == 0) {
 678  679                                  if ((strcmp(source, zhp->zfs_name) != 0) &&
 679  680                                      (strcmp(source,
 680  681                                      ZPROP_SOURCE_VAL_RECVD) != 0))
 681  682                                          continue;
 682  683                          }
 683  684                  } else {
 684  685                          char *source;
 685  686                          if (nvlist_lookup_string(propnv,
 686  687                              ZPROP_SOURCE, &source) != 0)
 687  688                                  continue;
 688  689                          if ((strcmp(source, zhp->zfs_name) != 0) &&
 689  690                              (strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0))
 690  691                                  continue;
 691  692                  }
 692  693  
 693  694                  if (zfs_prop_user(propname) ||
 694  695                      zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
 695  696                          char *value;
 696  697                          verify(nvlist_lookup_string(propnv,
 697  698                              ZPROP_VALUE, &value) == 0);
 698  699                          VERIFY(0 == nvlist_add_string(nv, propname, value));
 699  700                  } else {
 700  701                          uint64_t value;
 701  702                          verify(nvlist_lookup_uint64(propnv,
 702  703                              ZPROP_VALUE, &value) == 0);
 703  704                          VERIFY(0 == nvlist_add_uint64(nv, propname, value));
 704  705                  }
 705  706          }
 706  707  }
 707  708  
 708  709  /*
 709  710   * recursively generate nvlists describing datasets.  See comment
 710  711   * for the data structure send_data_t above for description of contents
 711  712   * of the nvlist.
 712  713   */
 713  714  static int
 714  715  send_iterate_fs(zfs_handle_t *zhp, void *arg)
 715  716  {
 716  717          send_data_t *sd = arg;
 717  718          nvlist_t *nvfs, *nv;
 718  719          int rv = 0;
 719  720          uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid;
 720  721          uint64_t guid = zhp->zfs_dmustats.dds_guid;
 721  722          char guidstring[64];
 722  723  
 723  724          VERIFY(0 == nvlist_alloc(&nvfs, NV_UNIQUE_NAME, 0));
 724  725          VERIFY(0 == nvlist_add_string(nvfs, "name", zhp->zfs_name));
 725  726          VERIFY(0 == nvlist_add_uint64(nvfs, "parentfromsnap",
 726  727              sd->parent_fromsnap_guid));
 727  728  
 728  729          if (zhp->zfs_dmustats.dds_origin[0]) {
 729  730                  zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
 730  731                      zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
 731  732                  if (origin == NULL)
 732  733                          return (-1);
 733  734                  VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
 734  735                      origin->zfs_dmustats.dds_guid));
 735  736          }
 736  737  
 737  738          /* iterate over props */
 738  739          VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
 739  740          send_iterate_prop(zhp, nv);
 740  741          VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
 741  742          nvlist_free(nv);
 742  743  
 743  744          /* iterate over snaps, and set sd->parent_fromsnap_guid */
 744  745          sd->parent_fromsnap_guid = 0;
 745  746          VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
 746  747          VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
 747  748          (void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
 748  749          VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
 749  750          VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
 750  751          nvlist_free(sd->parent_snaps);
 751  752          nvlist_free(sd->snapprops);
 752  753  
 753  754          /* add this fs to nvlist */
 754  755          (void) snprintf(guidstring, sizeof (guidstring),
 755  756              "0x%llx", (longlong_t)guid);
 756  757          VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
 757  758          nvlist_free(nvfs);
 758  759  
 759  760          /* iterate over children */
 760  761          if (sd->recursive)
 761  762                  rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
 762  763  
 763  764          sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
 764  765  
 765  766          zfs_close(zhp);
 766  767          return (rv);
 767  768  }
 768  769  
 769  770  static int
 770  771  gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
 771  772      const char *tosnap, boolean_t recursive, nvlist_t **nvlp, avl_tree_t **avlp)
 772  773  {
 773  774          zfs_handle_t *zhp;
 774  775          send_data_t sd = { 0 };
 775  776          int error;
 776  777  
 777  778          zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
 778  779          if (zhp == NULL)
 779  780                  return (EZFS_BADTYPE);
 780  781  
 781  782          VERIFY(0 == nvlist_alloc(&sd.fss, NV_UNIQUE_NAME, 0));
 782  783          sd.fromsnap = fromsnap;
 783  784          sd.tosnap = tosnap;
 784  785          sd.recursive = recursive;
 785  786  
 786  787          if ((error = send_iterate_fs(zhp, &sd)) != 0) {
 787  788                  nvlist_free(sd.fss);
 788  789                  if (avlp != NULL)
 789  790                          *avlp = NULL;
 790  791                  *nvlp = NULL;
 791  792                  return (error);
 792  793          }
 793  794  
 794  795          if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) {
 795  796                  nvlist_free(sd.fss);
 796  797                  *nvlp = NULL;
 797  798                  return (EZFS_NOMEM);
 798  799          }
 799  800  
 800  801          *nvlp = sd.fss;
 801  802          return (0);
 802  803  }
 803  804  
 804  805  /*
 805  806   * Routines specific to "zfs send"
 806  807   */
 807  808  typedef struct send_dump_data {
 808  809          /* these are all just the short snapname (the part after the @) */
 809  810          const char *fromsnap;
 810  811          const char *tosnap;
 811  812          char prevsnap[ZFS_MAXNAMELEN];
 812  813          uint64_t prevsnap_obj;
 813  814          boolean_t seenfrom, seento, replicate, doall, fromorigin;
 814  815          boolean_t verbose, dryrun, parsable, progress, embed_data, std_out;
 815  816          boolean_t large_block;
 816  817          int outfd;
 817  818          boolean_t err;
 818  819          nvlist_t *fss;
 819  820          nvlist_t *snapholds;
 820  821          avl_tree_t *fsavl;
 821  822          snapfilter_cb_t *filter_cb;
 822  823          void *filter_cb_arg;
 823  824          nvlist_t *debugnv;
 824  825          char holdtag[ZFS_MAXNAMELEN];
 825  826          int cleanup_fd;
 826  827          uint64_t size;
 827  828  } send_dump_data_t;
 828  829  
 829  830  static int
 830  831  estimate_ioctl(zfs_handle_t *zhp, uint64_t fromsnap_obj,
 831  832      boolean_t fromorigin, uint64_t *sizep)
 832  833  {
 833  834          zfs_cmd_t zc = { 0 };
 834  835          libzfs_handle_t *hdl = zhp->zfs_hdl;
 835  836  
 836  837          assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
 837  838          assert(fromsnap_obj == 0 || !fromorigin);
 838  839  
 839  840          (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 840  841          zc.zc_obj = fromorigin;
 841  842          zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
 842  843          zc.zc_fromobj = fromsnap_obj;
 843  844          zc.zc_guid = 1;  /* estimate flag */
 844  845  
 845  846          if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) {
 846  847                  char errbuf[1024];
 847  848                  (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 848  849                      "warning: cannot estimate space for '%s'"), zhp->zfs_name);
 849  850  
 850  851                  switch (errno) {
 851  852                  case EXDEV:
 852  853                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 853  854                              "not an earlier snapshot from the same fs"));
 854  855                          return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
 855  856  
 856  857                  case ENOENT:
 857  858                          if (zfs_dataset_exists(hdl, zc.zc_name,
 858  859                              ZFS_TYPE_SNAPSHOT)) {
 859  860                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 860  861                                      "incremental source (@%s) does not exist"),
 861  862                                      zc.zc_value);
 862  863                          }
 863  864                          return (zfs_error(hdl, EZFS_NOENT, errbuf));
 864  865  
 865  866                  case EDQUOT:
 866  867                  case EFBIG:
 867  868                  case EIO:
 868  869                  case ENOLINK:
 869  870                  case ENOSPC:
 870  871                  case ENOSTR:
 871  872                  case ENXIO:
 872  873                  case EPIPE:
 873  874                  case ERANGE:
 874  875                  case EFAULT:
 875  876                  case EROFS:
 876  877                          zfs_error_aux(hdl, strerror(errno));
 877  878                          return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
 878  879  
 879  880                  default:
 880  881                          return (zfs_standard_error(hdl, errno, errbuf));
 881  882                  }
 882  883          }
 883  884  
 884  885          *sizep = zc.zc_objset_type;
 885  886  
 886  887          return (0);
 887  888  }
 888  889  
 889  890  /*
 890  891   * Dumps a backup of the given snapshot (incremental from fromsnap if it's not
 891  892   * NULL) to the file descriptor specified by outfd.
 892  893   */
 893  894  static int
 894  895  dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
 895  896      boolean_t fromorigin, int outfd, enum lzc_send_flags flags,
 896  897      nvlist_t *debugnv)
 897  898  {
 898  899          zfs_cmd_t zc = { 0 };
 899  900          libzfs_handle_t *hdl = zhp->zfs_hdl;
 900  901          nvlist_t *thisdbg;
 901  902  
 902  903          assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
 903  904          assert(fromsnap_obj == 0 || !fromorigin);
 904  905  
 905  906          (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 906  907          zc.zc_cookie = outfd;
 907  908          zc.zc_obj = fromorigin;
 908  909          zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
 909  910          zc.zc_fromobj = fromsnap_obj;
 910  911          zc.zc_flags = flags;
 911  912  
 912  913          VERIFY(0 == nvlist_alloc(&thisdbg, NV_UNIQUE_NAME, 0));
 913  914          if (fromsnap && fromsnap[0] != '\0') {
 914  915                  VERIFY(0 == nvlist_add_string(thisdbg,
 915  916                      "fromsnap", fromsnap));
 916  917          }
 917  918  
 918  919          if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) {
 919  920                  char errbuf[1024];
 920  921                  (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 921  922                      "warning: cannot send '%s'"), zhp->zfs_name);
 922  923  
 923  924                  VERIFY(0 == nvlist_add_uint64(thisdbg, "error", errno));
 924  925                  if (debugnv) {
 925  926                          VERIFY(0 == nvlist_add_nvlist(debugnv,
 926  927                              zhp->zfs_name, thisdbg));
 927  928                  }
 928  929                  nvlist_free(thisdbg);
 929  930  
 930  931                  switch (errno) {
 931  932                  case EXDEV:
 932  933                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 933  934                              "not an earlier snapshot from the same fs"));
 934  935                          return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
 935  936  
 936  937                  case ENOENT:
 937  938                          if (zfs_dataset_exists(hdl, zc.zc_name,
 938  939                              ZFS_TYPE_SNAPSHOT)) {
 939  940                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 940  941                                      "incremental source (@%s) does not exist"),
 941  942                                      zc.zc_value);
 942  943                          }
 943  944                          return (zfs_error(hdl, EZFS_NOENT, errbuf));
 944  945  
 945  946                  case EDQUOT:
 946  947                  case EFBIG:
 947  948                  case EIO:
 948  949                  case ENOLINK:
 949  950                  case ENOSPC:
 950  951                  case ENOSTR:
 951  952                  case ENXIO:
 952  953                  case EPIPE:
 953  954                  case ERANGE:
 954  955                  case EFAULT:
 955  956                  case EROFS:
 956  957                          zfs_error_aux(hdl, strerror(errno));
 957  958                          return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
 958  959  
 959  960                  default:
 960  961                          return (zfs_standard_error(hdl, errno, errbuf));
 961  962                  }
 962  963          }
 963  964  
 964  965          if (debugnv)
 965  966                  VERIFY(0 == nvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg));
 966  967          nvlist_free(thisdbg);
 967  968  
 968  969          return (0);
 969  970  }
 970  971  
 971  972  static void
 972  973  gather_holds(zfs_handle_t *zhp, send_dump_data_t *sdd)
 973  974  {
 974  975          assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
 975  976  
 976  977          /*
 977  978           * zfs_send() only sets snapholds for sends that need them,
 978  979           * e.g. replication and doall.
 979  980           */
 980  981          if (sdd->snapholds == NULL)
 981  982                  return;
 982  983  
 983  984          fnvlist_add_string(sdd->snapholds, zhp->zfs_name, sdd->holdtag);
 984  985  }
 985  986  
 986  987  static void *
 987  988  send_progress_thread(void *arg)
 988  989  {
 989  990          progress_arg_t *pa = arg;
 990  991          zfs_cmd_t zc = { 0 };
 991  992          zfs_handle_t *zhp = pa->pa_zhp;
 992  993          libzfs_handle_t *hdl = zhp->zfs_hdl;
 993  994          unsigned long long bytes;
 994  995          char buf[16];
 995  996          time_t t;
 996  997          struct tm *tm;
 997  998  
 998  999          (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 999 1000  
1000 1001          if (!pa->pa_parsable)
1001 1002                  (void) fprintf(stderr, "TIME        SENT   SNAPSHOT\n");
1002 1003  
1003 1004          /*
1004 1005           * Print the progress from ZFS_IOC_SEND_PROGRESS every second.
1005 1006           */
1006 1007          for (;;) {
1007 1008                  (void) sleep(1);
1008 1009  
1009 1010                  zc.zc_cookie = pa->pa_fd;
1010 1011                  if (zfs_ioctl(hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0)
1011 1012                          return ((void *)-1);
1012 1013  
1013 1014                  (void) time(&t);
1014 1015                  tm = localtime(&t);
1015 1016                  bytes = zc.zc_cookie;
1016 1017  
1017 1018                  if (pa->pa_parsable) {
1018 1019                          (void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
1019 1020                              tm->tm_hour, tm->tm_min, tm->tm_sec,
1020 1021                              bytes, zhp->zfs_name);
1021 1022                  } else {
1022 1023                          zfs_nicenum(bytes, buf, sizeof (buf));
1023 1024                          (void) fprintf(stderr, "%02d:%02d:%02d   %5s   %s\n",
1024 1025                              tm->tm_hour, tm->tm_min, tm->tm_sec,
1025 1026                              buf, zhp->zfs_name);
1026 1027                  }
1027 1028          }
1028 1029  }
1029 1030  
1030 1031  static void
1031 1032  send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
1032 1033      uint64_t size, boolean_t parsable)
1033 1034  {
1034 1035          if (parsable) {
1035 1036                  if (fromsnap != NULL) {
1036 1037                          (void) fprintf(fout, "incremental\t%s\t%s",
1037 1038                              fromsnap, tosnap);
1038 1039                  } else {
1039 1040                          (void) fprintf(fout, "full\t%s",
1040 1041                              tosnap);
1041 1042                  }
1042 1043          } else {
1043 1044                  if (fromsnap != NULL) {
1044 1045                          if (strchr(fromsnap, '@') == NULL &&
1045 1046                              strchr(fromsnap, '#') == NULL) {
1046 1047                                  (void) fprintf(fout, dgettext(TEXT_DOMAIN,
1047 1048                                      "send from @%s to %s"),
1048 1049                                      fromsnap, tosnap);
1049 1050                          } else {
1050 1051                                  (void) fprintf(fout, dgettext(TEXT_DOMAIN,
1051 1052                                      "send from %s to %s"),
1052 1053                                      fromsnap, tosnap);
1053 1054                          }
1054 1055                  } else {
1055 1056                          (void) fprintf(fout, dgettext(TEXT_DOMAIN,
1056 1057                              "full send of %s"),
1057 1058                              tosnap);
1058 1059                  }
1059 1060          }
1060 1061  
1061 1062          if (size != 0) {
1062 1063                  if (parsable) {
1063 1064                          (void) fprintf(fout, "\t%llu",
1064 1065                              (longlong_t)size);
1065 1066                  } else {
1066 1067                          char buf[16];
1067 1068                          zfs_nicenum(size, buf, sizeof (buf));
1068 1069                          (void) fprintf(fout, dgettext(TEXT_DOMAIN,
1069 1070                              " estimated size is %s"), buf);
1070 1071                  }
1071 1072          }
1072 1073          (void) fprintf(fout, "\n");
1073 1074  }
1074 1075  
1075 1076  static int
1076 1077  dump_snapshot(zfs_handle_t *zhp, void *arg)
1077 1078  {
1078 1079          send_dump_data_t *sdd = arg;
1079 1080          progress_arg_t pa = { 0 };
1080 1081          pthread_t tid;
1081 1082          char *thissnap;
1082 1083          int err;
1083 1084          boolean_t isfromsnap, istosnap, fromorigin;
1084 1085          boolean_t exclude = B_FALSE;
1085 1086          FILE *fout = sdd->std_out ? stdout : stderr;
1086 1087  
1087 1088          err = 0;
1088 1089          thissnap = strchr(zhp->zfs_name, '@') + 1;
1089 1090          isfromsnap = (sdd->fromsnap != NULL &&
1090 1091              strcmp(sdd->fromsnap, thissnap) == 0);
1091 1092  
1092 1093          if (!sdd->seenfrom && isfromsnap) {
1093 1094                  gather_holds(zhp, sdd);
1094 1095                  sdd->seenfrom = B_TRUE;
1095 1096                  (void) strcpy(sdd->prevsnap, thissnap);
1096 1097                  sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
1097 1098                  zfs_close(zhp);
1098 1099                  return (0);
1099 1100          }
1100 1101  
1101 1102          if (sdd->seento || !sdd->seenfrom) {
1102 1103                  zfs_close(zhp);
1103 1104                  return (0);
1104 1105          }
1105 1106  
1106 1107          istosnap = (strcmp(sdd->tosnap, thissnap) == 0);
1107 1108          if (istosnap)
1108 1109                  sdd->seento = B_TRUE;
1109 1110  
1110 1111          if (!sdd->doall && !isfromsnap && !istosnap) {
1111 1112                  if (sdd->replicate) {
1112 1113                          char *snapname;
1113 1114                          nvlist_t *snapprops;
1114 1115                          /*
1115 1116                           * Filter out all intermediate snapshots except origin
1116 1117                           * snapshots needed to replicate clones.
1117 1118                           */
1118 1119                          nvlist_t *nvfs = fsavl_find(sdd->fsavl,
1119 1120                              zhp->zfs_dmustats.dds_guid, &snapname);
1120 1121  
1121 1122                          VERIFY(0 == nvlist_lookup_nvlist(nvfs,
1122 1123                              "snapprops", &snapprops));
1123 1124                          VERIFY(0 == nvlist_lookup_nvlist(snapprops,
1124 1125                              thissnap, &snapprops));
1125 1126                          exclude = !nvlist_exists(snapprops, "is_clone_origin");
1126 1127                  } else {
1127 1128                          exclude = B_TRUE;
1128 1129                  }
1129 1130          }
1130 1131  
1131 1132          /*
1132 1133           * If a filter function exists, call it to determine whether
1133 1134           * this snapshot will be sent.
1134 1135           */
1135 1136          if (exclude || (sdd->filter_cb != NULL &&
1136 1137              sdd->filter_cb(zhp, sdd->filter_cb_arg) == B_FALSE)) {
1137 1138                  /*
1138 1139                   * This snapshot is filtered out.  Don't send it, and don't
1139 1140                   * set prevsnap_obj, so it will be as if this snapshot didn't
1140 1141                   * exist, and the next accepted snapshot will be sent as
1141 1142                   * an incremental from the last accepted one, or as the
1142 1143                   * first (and full) snapshot in the case of a replication,
1143 1144                   * non-incremental send.
1144 1145                   */
1145 1146                  zfs_close(zhp);
1146 1147                  return (0);
1147 1148          }
1148 1149  
1149 1150          gather_holds(zhp, sdd);
1150 1151          fromorigin = sdd->prevsnap[0] == '\0' &&
1151 1152              (sdd->fromorigin || sdd->replicate);
1152 1153  
1153 1154          if (sdd->verbose) {
1154 1155                  uint64_t size = 0;
1155 1156                  (void) estimate_ioctl(zhp, sdd->prevsnap_obj,
1156 1157                      fromorigin, &size);
1157 1158  
1158 1159                  send_print_verbose(fout, zhp->zfs_name,
1159 1160                      sdd->prevsnap[0] ? sdd->prevsnap : NULL,
1160 1161                      size, sdd->parsable);
1161 1162                  sdd->size += size;
1162 1163          }
1163 1164  
1164 1165          if (!sdd->dryrun) {
1165 1166                  /*
1166 1167                   * If progress reporting is requested, spawn a new thread to
1167 1168                   * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
1168 1169                   */
1169 1170                  if (sdd->progress) {
1170 1171                          pa.pa_zhp = zhp;
1171 1172                          pa.pa_fd = sdd->outfd;
1172 1173                          pa.pa_parsable = sdd->parsable;
1173 1174  
1174 1175                          if (err = pthread_create(&tid, NULL,
1175 1176                              send_progress_thread, &pa)) {
1176 1177                                  zfs_close(zhp);
1177 1178                                  return (err);
1178 1179                          }
1179 1180                  }
1180 1181  
1181 1182                  enum lzc_send_flags flags = 0;
1182 1183                  if (sdd->large_block)
1183 1184                          flags |= LZC_SEND_FLAG_LARGE_BLOCK;
1184 1185                  if (sdd->embed_data)
1185 1186                          flags |= LZC_SEND_FLAG_EMBED_DATA;
1186 1187  
1187 1188                  err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
1188 1189                      fromorigin, sdd->outfd, flags, sdd->debugnv);
1189 1190  
1190 1191                  if (sdd->progress) {
1191 1192                          (void) pthread_cancel(tid);
1192 1193                          (void) pthread_join(tid, NULL);
1193 1194                  }
1194 1195          }
1195 1196  
1196 1197          (void) strcpy(sdd->prevsnap, thissnap);
1197 1198          sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
1198 1199          zfs_close(zhp);
1199 1200          return (err);
1200 1201  }
1201 1202  
1202 1203  static int
1203 1204  dump_filesystem(zfs_handle_t *zhp, void *arg)
1204 1205  {
1205 1206          int rv = 0;
1206 1207          send_dump_data_t *sdd = arg;
1207 1208          boolean_t missingfrom = B_FALSE;
1208 1209          zfs_cmd_t zc = { 0 };
1209 1210  
1210 1211          (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
1211 1212              zhp->zfs_name, sdd->tosnap);
1212 1213          if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
1213 1214                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1214 1215                      "WARNING: could not send %s@%s: does not exist\n"),
1215 1216                      zhp->zfs_name, sdd->tosnap);
1216 1217                  sdd->err = B_TRUE;
1217 1218                  return (0);
1218 1219          }
1219 1220  
1220 1221          if (sdd->replicate && sdd->fromsnap) {
1221 1222                  /*
1222 1223                   * If this fs does not have fromsnap, and we're doing
1223 1224                   * recursive, we need to send a full stream from the
1224 1225                   * beginning (or an incremental from the origin if this
1225 1226                   * is a clone).  If we're doing non-recursive, then let
1226 1227                   * them get the error.
1227 1228                   */
1228 1229                  (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
1229 1230                      zhp->zfs_name, sdd->fromsnap);
1230 1231                  if (ioctl(zhp->zfs_hdl->libzfs_fd,
1231 1232                      ZFS_IOC_OBJSET_STATS, &zc) != 0) {
1232 1233                          missingfrom = B_TRUE;
1233 1234                  }
1234 1235          }
1235 1236  
1236 1237          sdd->seenfrom = sdd->seento = sdd->prevsnap[0] = 0;
1237 1238          sdd->prevsnap_obj = 0;
1238 1239          if (sdd->fromsnap == NULL || missingfrom)
1239 1240                  sdd->seenfrom = B_TRUE;
1240 1241  
1241 1242          rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg);
1242 1243          if (!sdd->seenfrom) {
1243 1244                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1244 1245                      "WARNING: could not send %s@%s:\n"
1245 1246                      "incremental source (%s@%s) does not exist\n"),
1246 1247                      zhp->zfs_name, sdd->tosnap,
1247 1248                      zhp->zfs_name, sdd->fromsnap);
1248 1249                  sdd->err = B_TRUE;
1249 1250          } else if (!sdd->seento) {
1250 1251                  if (sdd->fromsnap) {
1251 1252                          (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1252 1253                              "WARNING: could not send %s@%s:\n"
1253 1254                              "incremental source (%s@%s) "
1254 1255                              "is not earlier than it\n"),
1255 1256                              zhp->zfs_name, sdd->tosnap,
1256 1257                              zhp->zfs_name, sdd->fromsnap);
1257 1258                  } else {
1258 1259                          (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1259 1260                              "WARNING: "
1260 1261                              "could not send %s@%s: does not exist\n"),
1261 1262                              zhp->zfs_name, sdd->tosnap);
1262 1263                  }
1263 1264                  sdd->err = B_TRUE;
1264 1265          }
1265 1266  
1266 1267          return (rv);
1267 1268  }
1268 1269  
1269 1270  static int
1270 1271  dump_filesystems(zfs_handle_t *rzhp, void *arg)
1271 1272  {
1272 1273          send_dump_data_t *sdd = arg;
1273 1274          nvpair_t *fspair;
1274 1275          boolean_t needagain, progress;
1275 1276  
1276 1277          if (!sdd->replicate)
1277 1278                  return (dump_filesystem(rzhp, sdd));
1278 1279  
1279 1280          /* Mark the clone origin snapshots. */
1280 1281          for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
1281 1282              fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
1282 1283                  nvlist_t *nvfs;
1283 1284                  uint64_t origin_guid = 0;
1284 1285  
1285 1286                  VERIFY(0 == nvpair_value_nvlist(fspair, &nvfs));
1286 1287                  (void) nvlist_lookup_uint64(nvfs, "origin", &origin_guid);
1287 1288                  if (origin_guid != 0) {
1288 1289                          char *snapname;
1289 1290                          nvlist_t *origin_nv = fsavl_find(sdd->fsavl,
1290 1291                              origin_guid, &snapname);
1291 1292                          if (origin_nv != NULL) {
1292 1293                                  nvlist_t *snapprops;
1293 1294                                  VERIFY(0 == nvlist_lookup_nvlist(origin_nv,
1294 1295                                      "snapprops", &snapprops));
1295 1296                                  VERIFY(0 == nvlist_lookup_nvlist(snapprops,
1296 1297                                      snapname, &snapprops));
1297 1298                                  VERIFY(0 == nvlist_add_boolean(
1298 1299                                      snapprops, "is_clone_origin"));
1299 1300                          }
1300 1301                  }
1301 1302          }
1302 1303  again:
1303 1304          needagain = progress = B_FALSE;
1304 1305          for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
1305 1306              fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
1306 1307                  nvlist_t *fslist, *parent_nv;
1307 1308                  char *fsname;
1308 1309                  zfs_handle_t *zhp;
1309 1310                  int err;
1310 1311                  uint64_t origin_guid = 0;
1311 1312                  uint64_t parent_guid = 0;
1312 1313  
1313 1314                  VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0);
1314 1315                  if (nvlist_lookup_boolean(fslist, "sent") == 0)
1315 1316                          continue;
1316 1317  
1317 1318                  VERIFY(nvlist_lookup_string(fslist, "name", &fsname) == 0);
1318 1319                  (void) nvlist_lookup_uint64(fslist, "origin", &origin_guid);
1319 1320                  (void) nvlist_lookup_uint64(fslist, "parentfromsnap",
1320 1321                      &parent_guid);
1321 1322  
1322 1323                  if (parent_guid != 0) {
1323 1324                          parent_nv = fsavl_find(sdd->fsavl, parent_guid, NULL);
1324 1325                          if (!nvlist_exists(parent_nv, "sent")) {
1325 1326                                  /* parent has not been sent; skip this one */
1326 1327                                  needagain = B_TRUE;
1327 1328                                  continue;
1328 1329                          }
1329 1330                  }
1330 1331  
1331 1332                  if (origin_guid != 0) {
1332 1333                          nvlist_t *origin_nv = fsavl_find(sdd->fsavl,
1333 1334                              origin_guid, NULL);
1334 1335                          if (origin_nv != NULL &&
1335 1336                              !nvlist_exists(origin_nv, "sent")) {
1336 1337                                  /*
1337 1338                                   * origin has not been sent yet;
1338 1339                                   * skip this clone.
1339 1340                                   */
1340 1341                                  needagain = B_TRUE;
1341 1342                                  continue;
1342 1343                          }
1343 1344                  }
1344 1345  
1345 1346                  zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET);
1346 1347                  if (zhp == NULL)
1347 1348                          return (-1);
1348 1349                  err = dump_filesystem(zhp, sdd);
1349 1350                  VERIFY(nvlist_add_boolean(fslist, "sent") == 0);
1350 1351                  progress = B_TRUE;
1351 1352                  zfs_close(zhp);
1352 1353                  if (err)
1353 1354                          return (err);
1354 1355          }
1355 1356          if (needagain) {
1356 1357                  assert(progress);
1357 1358                  goto again;
1358 1359          }
1359 1360  
1360 1361          /* clean out the sent flags in case we reuse this fss */
1361 1362          for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
1362 1363              fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
1363 1364                  nvlist_t *fslist;
1364 1365  
1365 1366                  VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0);
1366 1367                  (void) nvlist_remove_all(fslist, "sent");
1367 1368          }
1368 1369  
1369 1370          return (0);
1370 1371  }
1371 1372  
1372 1373  nvlist_t *
1373 1374  zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl, const char *token)
1374 1375  {
1375 1376          unsigned int version;
1376 1377          int nread;
1377 1378          unsigned long long checksum, packed_len;
1378 1379  
1379 1380          /*
1380 1381           * Decode token header, which is:
1381 1382           *   <token version>-<checksum of payload>-<uncompressed payload length>
1382 1383           * Note that the only supported token version is 1.
1383 1384           */
1384 1385          nread = sscanf(token, "%u-%llx-%llx-",
1385 1386              &version, &checksum, &packed_len);
1386 1387          if (nread != 3) {
1387 1388                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1388 1389                      "resume token is corrupt (invalid format)"));
1389 1390                  return (NULL);
1390 1391          }
1391 1392  
1392 1393          if (version != ZFS_SEND_RESUME_TOKEN_VERSION) {
1393 1394                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1394 1395                      "resume token is corrupt (invalid version %u)"),
1395 1396                      version);
1396 1397                  return (NULL);
1397 1398          }
1398 1399  
1399 1400          /* convert hexadecimal representation to binary */
1400 1401          token = strrchr(token, '-') + 1;
1401 1402          int len = strlen(token) / 2;
1402 1403          unsigned char *compressed = zfs_alloc(hdl, len);
1403 1404          for (int i = 0; i < len; i++) {
1404 1405                  nread = sscanf(token + i * 2, "%2hhx", compressed + i);
1405 1406                  if (nread != 1) {
1406 1407                          free(compressed);
1407 1408                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1408 1409                              "resume token is corrupt "
1409 1410                              "(payload is not hex-encoded)"));
1410 1411                          return (NULL);
1411 1412                  }
1412 1413          }
1413 1414  
1414 1415          /* verify checksum */
1415 1416          zio_cksum_t cksum;
1416 1417          fletcher_4_native(compressed, len, NULL, &cksum);
1417 1418          if (cksum.zc_word[0] != checksum) {
1418 1419                  free(compressed);
1419 1420                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1420 1421                      "resume token is corrupt (incorrect checksum)"));
1421 1422                  return (NULL);
1422 1423          }
1423 1424  
1424 1425          /* uncompress */
1425 1426          void *packed = zfs_alloc(hdl, packed_len);
1426 1427          uLongf packed_len_long = packed_len;
1427 1428          if (uncompress(packed, &packed_len_long, compressed, len) != Z_OK ||
1428 1429              packed_len_long != packed_len) {
1429 1430                  free(packed);
1430 1431                  free(compressed);
1431 1432                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1432 1433                      "resume token is corrupt (decompression failed)"));
1433 1434                  return (NULL);
1434 1435          }
1435 1436  
1436 1437          /* unpack nvlist */
1437 1438          nvlist_t *nv;
1438 1439          int error = nvlist_unpack(packed, packed_len, &nv, KM_SLEEP);
1439 1440          free(packed);
1440 1441          free(compressed);
1441 1442          if (error != 0) {
1442 1443                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1443 1444                      "resume token is corrupt (nvlist_unpack failed)"));
1444 1445                  return (NULL);
1445 1446          }
1446 1447          return (nv);
1447 1448  }
1448 1449  
1449 1450  int
1450 1451  zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
1451 1452      const char *resume_token)
1452 1453  {
1453 1454          char errbuf[1024];
1454 1455          char *toname;
1455 1456          char *fromname = NULL;
1456 1457          uint64_t resumeobj, resumeoff, toguid, fromguid, bytes;
1457 1458          zfs_handle_t *zhp;
1458 1459          int error = 0;
1459 1460          char name[ZFS_MAXNAMELEN];
1460 1461          enum lzc_send_flags lzc_flags = 0;
1461 1462  
1462 1463          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1463 1464              "cannot resume send"));
1464 1465  
1465 1466          nvlist_t *resume_nvl =
1466 1467              zfs_send_resume_token_to_nvlist(hdl, resume_token);
1467 1468          if (resume_nvl == NULL) {
1468 1469                  /*
1469 1470                   * zfs_error_aux has already been set by
1470 1471                   * zfs_send_resume_token_to_nvlist
1471 1472                   */
1472 1473                  return (zfs_error(hdl, EZFS_FAULT, errbuf));
1473 1474          }
1474 1475          if (flags->verbose) {
1475 1476                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1476 1477                      "resume token contents:\n"));
1477 1478                  nvlist_print(stderr, resume_nvl);
1478 1479          }
1479 1480  
1480 1481          if (nvlist_lookup_string(resume_nvl, "toname", &toname) != 0 ||
1481 1482              nvlist_lookup_uint64(resume_nvl, "object", &resumeobj) != 0 ||
1482 1483              nvlist_lookup_uint64(resume_nvl, "offset", &resumeoff) != 0 ||
1483 1484              nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 ||
1484 1485              nvlist_lookup_uint64(resume_nvl, "toguid", &toguid) != 0) {
1485 1486                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1486 1487                      "resume token is corrupt"));
1487 1488                  return (zfs_error(hdl, EZFS_FAULT, errbuf));
1488 1489          }
1489 1490          fromguid = 0;
1490 1491          (void) nvlist_lookup_uint64(resume_nvl, "fromguid", &fromguid);
1491 1492  
1492 1493          if (flags->embed_data || nvlist_exists(resume_nvl, "embedok"))
1493 1494                  lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
1494 1495  
1495 1496          if (guid_to_name(hdl, toname, toguid, B_FALSE, name) != 0) {
1496 1497                  if (zfs_dataset_exists(hdl, toname, ZFS_TYPE_DATASET)) {
1497 1498                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1498 1499                              "'%s' is no longer the same snapshot used in "
1499 1500                              "the initial send"), toname);
1500 1501                  } else {
1501 1502                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1502 1503                              "'%s' used in the initial send no longer exists"),
1503 1504                              toname);
1504 1505                  }
1505 1506                  return (zfs_error(hdl, EZFS_BADPATH, errbuf));
1506 1507          }
1507 1508          zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
1508 1509          if (zhp == NULL) {
1509 1510                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1510 1511                      "unable to access '%s'"), name);
1511 1512                  return (zfs_error(hdl, EZFS_BADPATH, errbuf));
1512 1513          }
1513 1514  
1514 1515          if (fromguid != 0) {
1515 1516                  if (guid_to_name(hdl, toname, fromguid, B_TRUE, name) != 0) {
1516 1517                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1517 1518                              "incremental source %#llx no longer exists"),
1518 1519                              (longlong_t)fromguid);
1519 1520                          return (zfs_error(hdl, EZFS_BADPATH, errbuf));
1520 1521                  }
1521 1522                  fromname = name;
1522 1523          }
1523 1524  
1524 1525          if (flags->verbose) {
1525 1526                  uint64_t size = 0;
1526 1527                  error = lzc_send_space(zhp->zfs_name, fromname, &size);
1527 1528                  if (error == 0)
1528 1529                          size = MAX(0, (int64_t)(size - bytes));
1529 1530                  send_print_verbose(stderr, zhp->zfs_name, fromname,
1530 1531                      size, flags->parsable);
1531 1532          }
1532 1533  
1533 1534          if (!flags->dryrun) {
1534 1535                  progress_arg_t pa = { 0 };
1535 1536                  pthread_t tid;
1536 1537                  /*
1537 1538                   * If progress reporting is requested, spawn a new thread to
1538 1539                   * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
1539 1540                   */
1540 1541                  if (flags->progress) {
1541 1542                          pa.pa_zhp = zhp;
1542 1543                          pa.pa_fd = outfd;
1543 1544                          pa.pa_parsable = flags->parsable;
1544 1545  
1545 1546                          error = pthread_create(&tid, NULL,
1546 1547                              send_progress_thread, &pa);
1547 1548                          if (error != 0) {
1548 1549                                  zfs_close(zhp);
1549 1550                                  return (error);
1550 1551                          }
1551 1552                  }
1552 1553  
1553 1554                  error = lzc_send_resume(zhp->zfs_name, fromname, outfd,
1554 1555                      lzc_flags, resumeobj, resumeoff);
1555 1556  
1556 1557                  if (flags->progress) {
1557 1558                          (void) pthread_cancel(tid);
1558 1559                          (void) pthread_join(tid, NULL);
1559 1560                  }
1560 1561  
1561 1562                  char errbuf[1024];
1562 1563                  (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1563 1564                      "warning: cannot send '%s'"), zhp->zfs_name);
1564 1565  
1565 1566                  zfs_close(zhp);
1566 1567  
1567 1568                  switch (error) {
1568 1569                  case 0:
1569 1570                          return (0);
1570 1571                  case EXDEV:
1571 1572                  case ENOENT:
1572 1573                  case EDQUOT:
1573 1574                  case EFBIG:
1574 1575                  case EIO:
1575 1576                  case ENOLINK:
1576 1577                  case ENOSPC:
1577 1578                  case ENOSTR:
1578 1579                  case ENXIO:
1579 1580                  case EPIPE:
1580 1581                  case ERANGE:
1581 1582                  case EFAULT:
1582 1583                  case EROFS:
1583 1584                          zfs_error_aux(hdl, strerror(errno));
1584 1585                          return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
1585 1586  
1586 1587                  default:
1587 1588                          return (zfs_standard_error(hdl, errno, errbuf));
1588 1589                  }
1589 1590          }
1590 1591  
1591 1592  
1592 1593          zfs_close(zhp);
1593 1594  
1594 1595          return (error);
1595 1596  }
1596 1597  
1597 1598  /*
1598 1599   * Generate a send stream for the dataset identified by the argument zhp.
1599 1600   *
1600 1601   * The content of the send stream is the snapshot identified by
1601 1602   * 'tosnap'.  Incremental streams are requested in two ways:
1602 1603   *     - from the snapshot identified by "fromsnap" (if non-null) or
1603 1604   *     - from the origin of the dataset identified by zhp, which must
1604 1605   *       be a clone.  In this case, "fromsnap" is null and "fromorigin"
1605 1606   *       is TRUE.
1606 1607   *
1607 1608   * The send stream is recursive (i.e. dumps a hierarchy of snapshots) and
1608 1609   * uses a special header (with a hdrtype field of DMU_COMPOUNDSTREAM)
1609 1610   * if "replicate" is set.  If "doall" is set, dump all the intermediate
1610 1611   * snapshots. The DMU_COMPOUNDSTREAM header is used in the "doall"
1611 1612   * case too. If "props" is set, send properties.
1612 1613   */
1613 1614  int
1614 1615  zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
1615 1616      sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
1616 1617      void *cb_arg, nvlist_t **debugnvp)
1617 1618  {
1618 1619          char errbuf[1024];
1619 1620          send_dump_data_t sdd = { 0 };
1620 1621          int err = 0;
1621 1622          nvlist_t *fss = NULL;
1622 1623          avl_tree_t *fsavl = NULL;
1623 1624          static uint64_t holdseq;
1624 1625          int spa_version;
1625 1626          pthread_t tid = 0;
1626 1627          int pipefd[2];
1627 1628          dedup_arg_t dda = { 0 };
1628 1629          int featureflags = 0;
1629 1630          FILE *fout;
1630 1631  
1631 1632          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1632 1633              "cannot send '%s'"), zhp->zfs_name);
1633 1634  
1634 1635          if (fromsnap && fromsnap[0] == '\0') {
1635 1636                  zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
1636 1637                      "zero-length incremental source"));
1637 1638                  return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
1638 1639          }
1639 1640  
1640 1641          if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM) {
1641 1642                  uint64_t version;
1642 1643                  version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
1643 1644                  if (version >= ZPL_VERSION_SA) {
1644 1645                          featureflags |= DMU_BACKUP_FEATURE_SA_SPILL;
1645 1646                  }
1646 1647          }
1647 1648  
1648 1649          if (flags->dedup && !flags->dryrun) {
1649 1650                  featureflags |= (DMU_BACKUP_FEATURE_DEDUP |
1650 1651                      DMU_BACKUP_FEATURE_DEDUPPROPS);
1651 1652                  if (err = pipe(pipefd)) {
1652 1653                          zfs_error_aux(zhp->zfs_hdl, strerror(errno));
1653 1654                          return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED,
1654 1655                              errbuf));
1655 1656                  }
1656 1657                  dda.outputfd = outfd;
1657 1658                  dda.inputfd = pipefd[1];
1658 1659                  dda.dedup_hdl = zhp->zfs_hdl;
1659 1660                  if (err = pthread_create(&tid, NULL, cksummer, &dda)) {
1660 1661                          (void) close(pipefd[0]);
1661 1662                          (void) close(pipefd[1]);
1662 1663                          zfs_error_aux(zhp->zfs_hdl, strerror(errno));
1663 1664                          return (zfs_error(zhp->zfs_hdl,
1664 1665                              EZFS_THREADCREATEFAILED, errbuf));
1665 1666                  }
1666 1667          }
1667 1668  
1668 1669          if (flags->replicate || flags->doall || flags->props) {
1669 1670                  dmu_replay_record_t drr = { 0 };
1670 1671                  char *packbuf = NULL;
1671 1672                  size_t buflen = 0;
1672 1673                  zio_cksum_t zc = { 0 };
1673 1674  
1674 1675                  if (flags->replicate || flags->props) {
1675 1676                          nvlist_t *hdrnv;
1676 1677  
1677 1678                          VERIFY(0 == nvlist_alloc(&hdrnv, NV_UNIQUE_NAME, 0));
1678 1679                          if (fromsnap) {
1679 1680                                  VERIFY(0 == nvlist_add_string(hdrnv,
1680 1681                                      "fromsnap", fromsnap));
1681 1682                          }
1682 1683                          VERIFY(0 == nvlist_add_string(hdrnv, "tosnap", tosnap));
1683 1684                          if (!flags->replicate) {
1684 1685                                  VERIFY(0 == nvlist_add_boolean(hdrnv,
1685 1686                                      "not_recursive"));
1686 1687                          }
1687 1688  
1688 1689                          err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
1689 1690                              fromsnap, tosnap, flags->replicate, &fss, &fsavl);
1690 1691                          if (err)
1691 1692                                  goto err_out;
1692 1693                          VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
1693 1694                          err = nvlist_pack(hdrnv, &packbuf, &buflen,
1694 1695                              NV_ENCODE_XDR, 0);
1695 1696                          if (debugnvp)
1696 1697                                  *debugnvp = hdrnv;
1697 1698                          else
1698 1699                                  nvlist_free(hdrnv);
1699 1700                          if (err)
1700 1701                                  goto stderr_out;
1701 1702                  }
1702 1703  
1703 1704                  if (!flags->dryrun) {
1704 1705                          /* write first begin record */
1705 1706                          drr.drr_type = DRR_BEGIN;
1706 1707                          drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
1707 1708                          DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.
1708 1709                              drr_versioninfo, DMU_COMPOUNDSTREAM);
1709 1710                          DMU_SET_FEATUREFLAGS(drr.drr_u.drr_begin.
1710 1711                              drr_versioninfo, featureflags);
1711 1712                          (void) snprintf(drr.drr_u.drr_begin.drr_toname,
1712 1713                              sizeof (drr.drr_u.drr_begin.drr_toname),
1713 1714                              "%s@%s", zhp->zfs_name, tosnap);
1714 1715                          drr.drr_payloadlen = buflen;
1715 1716  
1716 1717                          err = dump_record(&drr, packbuf, buflen, &zc, outfd);
1717 1718                          free(packbuf);
1718 1719                          if (err != 0)
1719 1720                                  goto stderr_out;
1720 1721  
1721 1722                          /* write end record */
1722 1723                          bzero(&drr, sizeof (drr));
1723 1724                          drr.drr_type = DRR_END;
1724 1725                          drr.drr_u.drr_end.drr_checksum = zc;
1725 1726                          err = write(outfd, &drr, sizeof (drr));
1726 1727                          if (err == -1) {
1727 1728                                  err = errno;
1728 1729                                  goto stderr_out;
1729 1730                          }
1730 1731  
1731 1732                          err = 0;
1732 1733                  }
1733 1734          }
1734 1735  
1735 1736          /* dump each stream */
1736 1737          sdd.fromsnap = fromsnap;
1737 1738          sdd.tosnap = tosnap;
1738 1739          if (tid != 0)
1739 1740                  sdd.outfd = pipefd[0];
1740 1741          else
1741 1742                  sdd.outfd = outfd;
1742 1743          sdd.replicate = flags->replicate;
1743 1744          sdd.doall = flags->doall;
1744 1745          sdd.fromorigin = flags->fromorigin;
1745 1746          sdd.fss = fss;
1746 1747          sdd.fsavl = fsavl;
1747 1748          sdd.verbose = flags->verbose;
1748 1749          sdd.parsable = flags->parsable;
1749 1750          sdd.progress = flags->progress;
1750 1751          sdd.dryrun = flags->dryrun;
1751 1752          sdd.large_block = flags->largeblock;
1752 1753          sdd.embed_data = flags->embed_data;
1753 1754          sdd.filter_cb = filter_func;
1754 1755          sdd.filter_cb_arg = cb_arg;
1755 1756          if (debugnvp)
1756 1757                  sdd.debugnv = *debugnvp;
1757 1758          if (sdd.verbose && sdd.dryrun)
1758 1759                  sdd.std_out = B_TRUE;
1759 1760          fout = sdd.std_out ? stdout : stderr;
1760 1761  
1761 1762          /*
1762 1763           * Some flags require that we place user holds on the datasets that are
1763 1764           * being sent so they don't get destroyed during the send. We can skip
1764 1765           * this step if the pool is imported read-only since the datasets cannot
1765 1766           * be destroyed.
1766 1767           */
1767 1768          if (!flags->dryrun && !zpool_get_prop_int(zfs_get_pool_handle(zhp),
1768 1769              ZPOOL_PROP_READONLY, NULL) &&
1769 1770              zfs_spa_version(zhp, &spa_version) == 0 &&
1770 1771              spa_version >= SPA_VERSION_USERREFS &&
1771 1772              (flags->doall || flags->replicate)) {
1772 1773                  ++holdseq;
1773 1774                  (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
1774 1775                      ".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
1775 1776                  sdd.cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
1776 1777                  if (sdd.cleanup_fd < 0) {
1777 1778                          err = errno;
1778 1779                          goto stderr_out;
1779 1780                  }
1780 1781                  sdd.snapholds = fnvlist_alloc();
1781 1782          } else {
1782 1783                  sdd.cleanup_fd = -1;
1783 1784                  sdd.snapholds = NULL;
1784 1785          }
1785 1786          if (flags->verbose || sdd.snapholds != NULL) {
1786 1787                  /*
1787 1788                   * Do a verbose no-op dry run to get all the verbose output
1788 1789                   * or to gather snapshot hold's before generating any data,
1789 1790                   * then do a non-verbose real run to generate the streams.
1790 1791                   */
1791 1792                  sdd.dryrun = B_TRUE;
1792 1793                  err = dump_filesystems(zhp, &sdd);
1793 1794  
1794 1795                  if (err != 0)
1795 1796                          goto stderr_out;
1796 1797  
1797 1798                  if (flags->verbose) {
1798 1799                          if (flags->parsable) {
1799 1800                                  (void) fprintf(fout, "size\t%llu\n",
1800 1801                                      (longlong_t)sdd.size);
1801 1802                          } else {
1802 1803                                  char buf[16];
1803 1804                                  zfs_nicenum(sdd.size, buf, sizeof (buf));
1804 1805                                  (void) fprintf(fout, dgettext(TEXT_DOMAIN,
1805 1806                                      "total estimated size is %s\n"), buf);
1806 1807                          }
1807 1808                  }
1808 1809  
1809 1810                  /* Ensure no snaps found is treated as an error. */
1810 1811                  if (!sdd.seento) {
1811 1812                          err = ENOENT;
1812 1813                          goto err_out;
1813 1814                  }
1814 1815  
1815 1816                  /* Skip the second run if dryrun was requested. */
1816 1817                  if (flags->dryrun)
1817 1818                          goto err_out;
1818 1819  
1819 1820                  if (sdd.snapholds != NULL) {
1820 1821                          err = zfs_hold_nvl(zhp, sdd.cleanup_fd, sdd.snapholds);
1821 1822                          if (err != 0)
1822 1823                                  goto stderr_out;
1823 1824  
1824 1825                          fnvlist_free(sdd.snapholds);
1825 1826                          sdd.snapholds = NULL;
1826 1827                  }
1827 1828  
1828 1829                  sdd.dryrun = B_FALSE;
1829 1830                  sdd.verbose = B_FALSE;
1830 1831          }
1831 1832  
1832 1833          err = dump_filesystems(zhp, &sdd);
1833 1834          fsavl_destroy(fsavl);
1834 1835          nvlist_free(fss);
1835 1836  
1836 1837          /* Ensure no snaps found is treated as an error. */
1837 1838          if (err == 0 && !sdd.seento)
1838 1839                  err = ENOENT;
1839 1840  
1840 1841          if (tid != 0) {
1841 1842                  if (err != 0)
1842 1843                          (void) pthread_cancel(tid);
1843 1844                  (void) close(pipefd[0]);
1844 1845                  (void) pthread_join(tid, NULL);
1845 1846          }
1846 1847  
1847 1848          if (sdd.cleanup_fd != -1) {
1848 1849                  VERIFY(0 == close(sdd.cleanup_fd));
1849 1850                  sdd.cleanup_fd = -1;
1850 1851          }
1851 1852  
1852 1853          if (!flags->dryrun && (flags->replicate || flags->doall ||
1853 1854              flags->props)) {
1854 1855                  /*
1855 1856                   * write final end record.  NB: want to do this even if
1856 1857                   * there was some error, because it might not be totally
1857 1858                   * failed.
1858 1859                   */
1859 1860                  dmu_replay_record_t drr = { 0 };
1860 1861                  drr.drr_type = DRR_END;
1861 1862                  if (write(outfd, &drr, sizeof (drr)) == -1) {
1862 1863                          return (zfs_standard_error(zhp->zfs_hdl,
1863 1864                              errno, errbuf));
1864 1865                  }
1865 1866          }
1866 1867  
1867 1868          return (err || sdd.err);
1868 1869  
1869 1870  stderr_out:
1870 1871          err = zfs_standard_error(zhp->zfs_hdl, err, errbuf);
1871 1872  err_out:
1872 1873          fsavl_destroy(fsavl);
1873 1874          nvlist_free(fss);
1874 1875          fnvlist_free(sdd.snapholds);
1875 1876  
1876 1877          if (sdd.cleanup_fd != -1)
1877 1878                  VERIFY(0 == close(sdd.cleanup_fd));
1878 1879          if (tid != 0) {
1879 1880                  (void) pthread_cancel(tid);
1880 1881                  (void) close(pipefd[0]);
1881 1882                  (void) pthread_join(tid, NULL);
1882 1883          }
1883 1884          return (err);
1884 1885  }
1885 1886  
1886 1887  int
1887 1888  zfs_send_one(zfs_handle_t *zhp, const char *from, int fd,
1888 1889      enum lzc_send_flags flags)
1889 1890  {
1890 1891          int err;
1891 1892          libzfs_handle_t *hdl = zhp->zfs_hdl;
1892 1893  
1893 1894          char errbuf[1024];
1894 1895          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1895 1896              "warning: cannot send '%s'"), zhp->zfs_name);
1896 1897  
1897 1898          err = lzc_send(zhp->zfs_name, from, fd, flags);
1898 1899          if (err != 0) {
1899 1900                  switch (errno) {
1900 1901                  case EXDEV:
1901 1902                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1902 1903                              "not an earlier snapshot from the same fs"));
1903 1904                          return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
1904 1905  
1905 1906                  case ENOENT:
1906 1907                  case ESRCH:
1907 1908                          if (lzc_exists(zhp->zfs_name)) {
1908 1909                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1909 1910                                      "incremental source (%s) does not exist"),
1910 1911                                      from);
1911 1912                          }
1912 1913                          return (zfs_error(hdl, EZFS_NOENT, errbuf));
1913 1914  
1914 1915                  case EBUSY:
1915 1916                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1916 1917                              "target is busy; if a filesystem, "
1917 1918                              "it must not be mounted"));
1918 1919                          return (zfs_error(hdl, EZFS_BUSY, errbuf));
1919 1920  
1920 1921                  case EDQUOT:
1921 1922                  case EFBIG:
1922 1923                  case EIO:
1923 1924                  case ENOLINK:
1924 1925                  case ENOSPC:
1925 1926                  case ENOSTR:
1926 1927                  case ENXIO:
1927 1928                  case EPIPE:
1928 1929                  case ERANGE:
1929 1930                  case EFAULT:
1930 1931                  case EROFS:
1931 1932                          zfs_error_aux(hdl, strerror(errno));
1932 1933                          return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
1933 1934  
1934 1935                  default:
1935 1936                          return (zfs_standard_error(hdl, errno, errbuf));
1936 1937                  }
1937 1938          }
1938 1939          return (err != 0);
1939 1940  }
1940 1941  
1941 1942  /*
1942 1943   * Routines specific to "zfs recv"
1943 1944   */
1944 1945  
1945 1946  static int
1946 1947  recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen,
1947 1948      boolean_t byteswap, zio_cksum_t *zc)
1948 1949  {
1949 1950          char *cp = buf;
1950 1951          int rv;
1951 1952          int len = ilen;
1952 1953  
1953 1954          assert(ilen <= SPA_MAXBLOCKSIZE);
1954 1955  
1955 1956          do {
1956 1957                  rv = read(fd, cp, len);
1957 1958                  cp += rv;
1958 1959                  len -= rv;
1959 1960          } while (rv > 0);
1960 1961  
1961 1962          if (rv < 0 || len != 0) {
1962 1963                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1963 1964                      "failed to read from stream"));
1964 1965                  return (zfs_error(hdl, EZFS_BADSTREAM, dgettext(TEXT_DOMAIN,
1965 1966                      "cannot receive")));
1966 1967          }
1967 1968  
1968 1969          if (zc) {
1969 1970                  if (byteswap)
1970 1971                          fletcher_4_incremental_byteswap(buf, ilen, zc);
1971 1972                  else
1972 1973                          fletcher_4_incremental_native(buf, ilen, zc);
1973 1974          }
1974 1975          return (0);
1975 1976  }
1976 1977  
1977 1978  static int
1978 1979  recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp,
1979 1980      boolean_t byteswap, zio_cksum_t *zc)
1980 1981  {
1981 1982          char *buf;
1982 1983          int err;
1983 1984  
1984 1985          buf = zfs_alloc(hdl, len);
1985 1986          if (buf == NULL)
1986 1987                  return (ENOMEM);
1987 1988  
1988 1989          err = recv_read(hdl, fd, buf, len, byteswap, zc);
1989 1990          if (err != 0) {
1990 1991                  free(buf);
1991 1992                  return (err);
1992 1993          }
1993 1994  
1994 1995          err = nvlist_unpack(buf, len, nvp, 0);
1995 1996          free(buf);
1996 1997          if (err != 0) {
1997 1998                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
1998 1999                      "stream (malformed nvlist)"));
1999 2000                  return (EINVAL);
2000 2001          }
2001 2002          return (0);
2002 2003  }
2003 2004  
2004 2005  static int
2005 2006  recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
2006 2007      int baselen, char *newname, recvflags_t *flags)
2007 2008  {
2008 2009          static int seq;
2009 2010          zfs_cmd_t zc = { 0 };
2010 2011          int err;
2011 2012          prop_changelist_t *clp;
2012 2013          zfs_handle_t *zhp;
2013 2014  
2014 2015          zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
2015 2016          if (zhp == NULL)
2016 2017                  return (-1);
2017 2018          clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
2018 2019              flags->force ? MS_FORCE : 0);
2019 2020          zfs_close(zhp);
2020 2021          if (clp == NULL)
2021 2022                  return (-1);
2022 2023          err = changelist_prefix(clp);
2023 2024          if (err)
2024 2025                  return (err);
2025 2026  
2026 2027          zc.zc_objset_type = DMU_OST_ZFS;
2027 2028          (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
2028 2029  
2029 2030          if (tryname) {
2030 2031                  (void) strcpy(newname, tryname);
2031 2032  
2032 2033                  (void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value));
2033 2034  
2034 2035                  if (flags->verbose) {
2035 2036                          (void) printf("attempting rename %s to %s\n",
2036 2037                              zc.zc_name, zc.zc_value);
2037 2038                  }
2038 2039                  err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
2039 2040                  if (err == 0)
2040 2041                          changelist_rename(clp, name, tryname);
2041 2042          } else {
2042 2043                  err = ENOENT;
2043 2044          }
2044 2045  
2045 2046          if (err != 0 && strncmp(name + baselen, "recv-", 5) != 0) {
2046 2047                  seq++;
2047 2048  
2048 2049                  (void) snprintf(newname, ZFS_MAXNAMELEN, "%.*srecv-%u-%u",
2049 2050                      baselen, name, getpid(), seq);
2050 2051                  (void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value));
2051 2052  
2052 2053                  if (flags->verbose) {
2053 2054                          (void) printf("failed - trying rename %s to %s\n",
2054 2055                              zc.zc_name, zc.zc_value);
2055 2056                  }
2056 2057                  err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
2057 2058                  if (err == 0)
2058 2059                          changelist_rename(clp, name, newname);
2059 2060                  if (err && flags->verbose) {
2060 2061                          (void) printf("failed (%u) - "
2061 2062                              "will try again on next pass\n", errno);
2062 2063                  }
2063 2064                  err = EAGAIN;
2064 2065          } else if (flags->verbose) {
2065 2066                  if (err == 0)
2066 2067                          (void) printf("success\n");
2067 2068                  else
2068 2069                          (void) printf("failed (%u)\n", errno);
2069 2070          }
2070 2071  
2071 2072          (void) changelist_postfix(clp);
2072 2073          changelist_free(clp);
2073 2074  
2074 2075          return (err);
2075 2076  }
2076 2077  
2077 2078  static int
2078 2079  recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
2079 2080      char *newname, recvflags_t *flags)
2080 2081  {
2081 2082          zfs_cmd_t zc = { 0 };
2082 2083          int err = 0;
2083 2084          prop_changelist_t *clp;
2084 2085          zfs_handle_t *zhp;
2085 2086          boolean_t defer = B_FALSE;
2086 2087          int spa_version;
2087 2088  
2088 2089          zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
2089 2090          if (zhp == NULL)
2090 2091                  return (-1);
2091 2092          clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
2092 2093              flags->force ? MS_FORCE : 0);
2093 2094          if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
2094 2095              zfs_spa_version(zhp, &spa_version) == 0 &&
2095 2096              spa_version >= SPA_VERSION_USERREFS)
2096 2097                  defer = B_TRUE;
2097 2098          zfs_close(zhp);
2098 2099          if (clp == NULL)
2099 2100                  return (-1);
2100 2101          err = changelist_prefix(clp);
2101 2102          if (err)
2102 2103                  return (err);
2103 2104  
2104 2105          zc.zc_objset_type = DMU_OST_ZFS;
2105 2106          zc.zc_defer_destroy = defer;
2106 2107          (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
2107 2108  
2108 2109          if (flags->verbose)
2109 2110                  (void) printf("attempting destroy %s\n", zc.zc_name);
2110 2111          err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
2111 2112          if (err == 0) {
2112 2113                  if (flags->verbose)
2113 2114                          (void) printf("success\n");
2114 2115                  changelist_remove(clp, zc.zc_name);
2115 2116          }
2116 2117  
2117 2118          (void) changelist_postfix(clp);
2118 2119          changelist_free(clp);
2119 2120  
2120 2121          /*
2121 2122           * Deferred destroy might destroy the snapshot or only mark it to be
2122 2123           * destroyed later, and it returns success in either case.
2123 2124           */
2124 2125          if (err != 0 || (defer && zfs_dataset_exists(hdl, name,
2125 2126              ZFS_TYPE_SNAPSHOT))) {
2126 2127                  err = recv_rename(hdl, name, NULL, baselen, newname, flags);
2127 2128          }
2128 2129  
2129 2130          return (err);
2130 2131  }
2131 2132  
2132 2133  typedef struct guid_to_name_data {
2133 2134          uint64_t guid;
2134 2135          boolean_t bookmark_ok;
2135 2136          char *name;
2136 2137          char *skip;
2137 2138  } guid_to_name_data_t;
2138 2139  
2139 2140  static int
2140 2141  guid_to_name_cb(zfs_handle_t *zhp, void *arg)
2141 2142  {
2142 2143          guid_to_name_data_t *gtnd = arg;
2143 2144          const char *slash;
2144 2145          int err;
2145 2146  
2146 2147          if (gtnd->skip != NULL &&
2147 2148              (slash = strrchr(zhp->zfs_name, '/')) != NULL &&
2148 2149              strcmp(slash + 1, gtnd->skip) == 0) {
2149 2150                  zfs_close(zhp);
2150 2151                  return (0);
2151 2152          }
2152 2153  
2153 2154          if (zfs_prop_get_int(zhp, ZFS_PROP_GUID) == gtnd->guid) {
2154 2155                  (void) strcpy(gtnd->name, zhp->zfs_name);
2155 2156                  zfs_close(zhp);
2156 2157                  return (EEXIST);
2157 2158          }
2158 2159  
2159 2160          err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
2160 2161          if (err != EEXIST && gtnd->bookmark_ok)
2161 2162                  err = zfs_iter_bookmarks(zhp, guid_to_name_cb, gtnd);
2162 2163          zfs_close(zhp);
2163 2164          return (err);
2164 2165  }
2165 2166  
2166 2167  /*
2167 2168   * Attempt to find the local dataset associated with this guid.  In the case of
2168 2169   * multiple matches, we attempt to find the "best" match by searching
2169 2170   * progressively larger portions of the hierarchy.  This allows one to send a
2170 2171   * tree of datasets individually and guarantee that we will find the source
2171 2172   * guid within that hierarchy, even if there are multiple matches elsewhere.
2172 2173   */
2173 2174  static int
2174 2175  guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
2175 2176      boolean_t bookmark_ok, char *name)
2176 2177  {
2177 2178          char pname[ZFS_MAXNAMELEN];
2178 2179          guid_to_name_data_t gtnd;
2179 2180  
2180 2181          gtnd.guid = guid;
2181 2182          gtnd.bookmark_ok = bookmark_ok;
2182 2183          gtnd.name = name;
2183 2184          gtnd.skip = NULL;
2184 2185  
2185 2186          /*
2186 2187           * Search progressively larger portions of the hierarchy, starting
2187 2188           * with the filesystem specified by 'parent'.  This will
2188 2189           * select the "most local" version of the origin snapshot in the case
2189 2190           * that there are multiple matching snapshots in the system.
2190 2191           */
2191 2192          (void) strlcpy(pname, parent, sizeof (pname));
2192 2193          char *cp = strrchr(pname, '@');
2193 2194          if (cp == NULL)
2194 2195                  cp = strchr(pname, '\0');
2195 2196          for (; cp != NULL; cp = strrchr(pname, '/')) {
2196 2197                  /* Chop off the last component and open the parent */
2197 2198                  *cp = '\0';
2198 2199                  zfs_handle_t *zhp = make_dataset_handle(hdl, pname);
2199 2200  
2200 2201                  if (zhp == NULL)
2201 2202                          continue;
2202 2203                  int err = guid_to_name_cb(zfs_handle_dup(zhp), >nd);
2203 2204                  if (err != EEXIST)
2204 2205                          err = zfs_iter_children(zhp, guid_to_name_cb, >nd);
2205 2206                  if (err != EEXIST && bookmark_ok)
2206 2207                          err = zfs_iter_bookmarks(zhp, guid_to_name_cb, >nd);
2207 2208                  zfs_close(zhp);
2208 2209                  if (err == EEXIST)
2209 2210                          return (0);
2210 2211  
2211 2212                  /*
2212 2213                   * Remember the last portion of the dataset so we skip it next
2213 2214                   * time through (as we've already searched that portion of the
2214 2215                   * hierarchy).
2215 2216                   */
2216 2217                  gtnd.skip = strrchr(pname, '/') + 1;
2217 2218          }
2218 2219  
2219 2220          return (ENOENT);
2220 2221  }
2221 2222  
2222 2223  /*
2223 2224   * Return +1 if guid1 is before guid2, 0 if they are the same, and -1 if
2224 2225   * guid1 is after guid2.
2225 2226   */
2226 2227  static int
2227 2228  created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
2228 2229      uint64_t guid1, uint64_t guid2)
2229 2230  {
2230 2231          nvlist_t *nvfs;
2231 2232          char *fsname, *snapname;
2232 2233          char buf[ZFS_MAXNAMELEN];
2233 2234          int rv;
2234 2235          zfs_handle_t *guid1hdl, *guid2hdl;
2235 2236          uint64_t create1, create2;
2236 2237  
2237 2238          if (guid2 == 0)
2238 2239                  return (0);
2239 2240          if (guid1 == 0)
2240 2241                  return (1);
2241 2242  
2242 2243          nvfs = fsavl_find(avl, guid1, &snapname);
2243 2244          VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
2244 2245          (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
2245 2246          guid1hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
2246 2247          if (guid1hdl == NULL)
2247 2248                  return (-1);
2248 2249  
2249 2250          nvfs = fsavl_find(avl, guid2, &snapname);
2250 2251          VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
2251 2252          (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
2252 2253          guid2hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
2253 2254          if (guid2hdl == NULL) {
2254 2255                  zfs_close(guid1hdl);
2255 2256                  return (-1);
2256 2257          }
2257 2258  
2258 2259          create1 = zfs_prop_get_int(guid1hdl, ZFS_PROP_CREATETXG);
2259 2260          create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
2260 2261  
2261 2262          if (create1 < create2)
2262 2263                  rv = -1;
2263 2264          else if (create1 > create2)
2264 2265                  rv = +1;
2265 2266          else
2266 2267                  rv = 0;
2267 2268  
2268 2269          zfs_close(guid1hdl);
2269 2270          zfs_close(guid2hdl);
2270 2271  
2271 2272          return (rv);
2272 2273  }
2273 2274  
2274 2275  static int
2275 2276  recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
2276 2277      recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
2277 2278      nvlist_t *renamed)
2278 2279  {
2279 2280          nvlist_t *local_nv;
2280 2281          avl_tree_t *local_avl;
2281 2282          nvpair_t *fselem, *nextfselem;
2282 2283          char *fromsnap;
2283 2284          char newname[ZFS_MAXNAMELEN];
2284 2285          int error;
2285 2286          boolean_t needagain, progress, recursive;
2286 2287          char *s1, *s2;
2287 2288  
2288 2289          VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
2289 2290  
2290 2291          recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2291 2292              ENOENT);
2292 2293  
2293 2294          if (flags->dryrun)
2294 2295                  return (0);
2295 2296  
2296 2297  again:
2297 2298          needagain = progress = B_FALSE;
2298 2299  
2299 2300          if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
2300 2301              recursive, &local_nv, &local_avl)) != 0)
2301 2302                  return (error);
2302 2303  
2303 2304          /*
2304 2305           * Process deletes and renames
2305 2306           */
2306 2307          for (fselem = nvlist_next_nvpair(local_nv, NULL);
2307 2308              fselem; fselem = nextfselem) {
2308 2309                  nvlist_t *nvfs, *snaps;
2309 2310                  nvlist_t *stream_nvfs = NULL;
2310 2311                  nvpair_t *snapelem, *nextsnapelem;
2311 2312                  uint64_t fromguid = 0;
2312 2313                  uint64_t originguid = 0;
2313 2314                  uint64_t stream_originguid = 0;
2314 2315                  uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
2315 2316                  char *fsname, *stream_fsname;
2316 2317  
2317 2318                  nextfselem = nvlist_next_nvpair(local_nv, fselem);
2318 2319  
2319 2320                  VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
2320 2321                  VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
2321 2322                  VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
2322 2323                  VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",
2323 2324                      &parent_fromsnap_guid));
2324 2325                  (void) nvlist_lookup_uint64(nvfs, "origin", &originguid);
2325 2326  
2326 2327                  /*
2327 2328                   * First find the stream's fs, so we can check for
2328 2329                   * a different origin (due to "zfs promote")
2329 2330                   */
2330 2331                  for (snapelem = nvlist_next_nvpair(snaps, NULL);
2331 2332                      snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) {
2332 2333                          uint64_t thisguid;
2333 2334  
2334 2335                          VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
2335 2336                          stream_nvfs = fsavl_find(stream_avl, thisguid, NULL);
2336 2337  
2337 2338                          if (stream_nvfs != NULL)
2338 2339                                  break;
2339 2340                  }
2340 2341  
2341 2342                  /* check for promote */
2342 2343                  (void) nvlist_lookup_uint64(stream_nvfs, "origin",
2343 2344                      &stream_originguid);
2344 2345                  if (stream_nvfs && originguid != stream_originguid) {
2345 2346                          switch (created_before(hdl, local_avl,
2346 2347                              stream_originguid, originguid)) {
2347 2348                          case 1: {
2348 2349                                  /* promote it! */
2349 2350                                  zfs_cmd_t zc = { 0 };
2350 2351                                  nvlist_t *origin_nvfs;
2351 2352                                  char *origin_fsname;
2352 2353  
2353 2354                                  if (flags->verbose)
2354 2355                                          (void) printf("promoting %s\n", fsname);
2355 2356  
2356 2357                                  origin_nvfs = fsavl_find(local_avl, originguid,
2357 2358                                      NULL);
2358 2359                                  VERIFY(0 == nvlist_lookup_string(origin_nvfs,
2359 2360                                      "name", &origin_fsname));
2360 2361                                  (void) strlcpy(zc.zc_value, origin_fsname,
2361 2362                                      sizeof (zc.zc_value));
2362 2363                                  (void) strlcpy(zc.zc_name, fsname,
2363 2364                                      sizeof (zc.zc_name));
2364 2365                                  error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
2365 2366                                  if (error == 0)
2366 2367                                          progress = B_TRUE;
2367 2368                                  break;
2368 2369                          }
2369 2370                          default:
2370 2371                                  break;
2371 2372                          case -1:
2372 2373                                  fsavl_destroy(local_avl);
2373 2374                                  nvlist_free(local_nv);
2374 2375                                  return (-1);
2375 2376                          }
2376 2377                          /*
2377 2378                           * We had/have the wrong origin, therefore our
2378 2379                           * list of snapshots is wrong.  Need to handle
2379 2380                           * them on the next pass.
2380 2381                           */
2381 2382                          needagain = B_TRUE;
2382 2383                          continue;
2383 2384                  }
2384 2385  
2385 2386                  for (snapelem = nvlist_next_nvpair(snaps, NULL);
2386 2387                      snapelem; snapelem = nextsnapelem) {
2387 2388                          uint64_t thisguid;
2388 2389                          char *stream_snapname;
2389 2390                          nvlist_t *found, *props;
2390 2391  
2391 2392                          nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
2392 2393  
2393 2394                          VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
2394 2395                          found = fsavl_find(stream_avl, thisguid,
2395 2396                              &stream_snapname);
2396 2397  
2397 2398                          /* check for delete */
2398 2399                          if (found == NULL) {
2399 2400                                  char name[ZFS_MAXNAMELEN];
2400 2401  
2401 2402                                  if (!flags->force)
2402 2403                                          continue;
2403 2404  
2404 2405                                  (void) snprintf(name, sizeof (name), "%s@%s",
2405 2406                                      fsname, nvpair_name(snapelem));
2406 2407  
2407 2408                                  error = recv_destroy(hdl, name,
2408 2409                                      strlen(fsname)+1, newname, flags);
2409 2410                                  if (error)
2410 2411                                          needagain = B_TRUE;
2411 2412                                  else
2412 2413                                          progress = B_TRUE;
2413 2414                                  continue;
2414 2415                          }
2415 2416  
2416 2417                          stream_nvfs = found;
2417 2418  
2418 2419                          if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
2419 2420                              &props) && 0 == nvlist_lookup_nvlist(props,
2420 2421                              stream_snapname, &props)) {
2421 2422                                  zfs_cmd_t zc = { 0 };
2422 2423  
2423 2424                                  zc.zc_cookie = B_TRUE; /* received */
2424 2425                                  (void) snprintf(zc.zc_name, sizeof (zc.zc_name),
2425 2426                                      "%s@%s", fsname, nvpair_name(snapelem));
2426 2427                                  if (zcmd_write_src_nvlist(hdl, &zc,
2427 2428                                      props) == 0) {
2428 2429                                          (void) zfs_ioctl(hdl,
2429 2430                                              ZFS_IOC_SET_PROP, &zc);
2430 2431                                          zcmd_free_nvlists(&zc);
2431 2432                                  }
2432 2433                          }
2433 2434  
2434 2435                          /* check for different snapname */
2435 2436                          if (strcmp(nvpair_name(snapelem),
2436 2437                              stream_snapname) != 0) {
2437 2438                                  char name[ZFS_MAXNAMELEN];
2438 2439                                  char tryname[ZFS_MAXNAMELEN];
2439 2440  
2440 2441                                  (void) snprintf(name, sizeof (name), "%s@%s",
2441 2442                                      fsname, nvpair_name(snapelem));
2442 2443                                  (void) snprintf(tryname, sizeof (name), "%s@%s",
2443 2444                                      fsname, stream_snapname);
2444 2445  
2445 2446                                  error = recv_rename(hdl, name, tryname,
2446 2447                                      strlen(fsname)+1, newname, flags);
2447 2448                                  if (error)
2448 2449                                          needagain = B_TRUE;
2449 2450                                  else
2450 2451                                          progress = B_TRUE;
2451 2452                          }
2452 2453  
2453 2454                          if (strcmp(stream_snapname, fromsnap) == 0)
2454 2455                                  fromguid = thisguid;
2455 2456                  }
2456 2457  
2457 2458                  /* check for delete */
2458 2459                  if (stream_nvfs == NULL) {
2459 2460                          if (!flags->force)
2460 2461                                  continue;
2461 2462  
2462 2463                          error = recv_destroy(hdl, fsname, strlen(tofs)+1,
2463 2464                              newname, flags);
2464 2465                          if (error)
2465 2466                                  needagain = B_TRUE;
2466 2467                          else
2467 2468                                  progress = B_TRUE;
2468 2469                          continue;
2469 2470                  }
2470 2471  
2471 2472                  if (fromguid == 0) {
2472 2473                          if (flags->verbose) {
2473 2474                                  (void) printf("local fs %s does not have "
2474 2475                                      "fromsnap (%s in stream); must have "
2475 2476                                      "been deleted locally; ignoring\n",
2476 2477                                      fsname, fromsnap);
2477 2478                          }
2478 2479                          continue;
2479 2480                  }
2480 2481  
2481 2482                  VERIFY(0 == nvlist_lookup_string(stream_nvfs,
2482 2483                      "name", &stream_fsname));
2483 2484                  VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
2484 2485                      "parentfromsnap", &stream_parent_fromsnap_guid));
2485 2486  
2486 2487                  s1 = strrchr(fsname, '/');
2487 2488                  s2 = strrchr(stream_fsname, '/');
2488 2489  
2489 2490                  /*
2490 2491                   * Check for rename. If the exact receive path is specified, it
2491 2492                   * does not count as a rename, but we still need to check the
2492 2493                   * datasets beneath it.
2493 2494                   */
2494 2495                  if ((stream_parent_fromsnap_guid != 0 &&
2495 2496                      parent_fromsnap_guid != 0 &&
2496 2497                      stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
2497 2498                      ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
2498 2499                      (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
2499 2500                          nvlist_t *parent;
2500 2501                          char tryname[ZFS_MAXNAMELEN];
2501 2502  
2502 2503                          parent = fsavl_find(local_avl,
2503 2504                              stream_parent_fromsnap_guid, NULL);
2504 2505                          /*
2505 2506                           * NB: parent might not be found if we used the
2506 2507                           * tosnap for stream_parent_fromsnap_guid,
2507 2508                           * because the parent is a newly-created fs;
2508 2509                           * we'll be able to rename it after we recv the
2509 2510                           * new fs.
2510 2511                           */
2511 2512                          if (parent != NULL) {
2512 2513                                  char *pname;
2513 2514  
2514 2515                                  VERIFY(0 == nvlist_lookup_string(parent, "name",
2515 2516                                      &pname));
2516 2517                                  (void) snprintf(tryname, sizeof (tryname),
2517 2518                                      "%s%s", pname, strrchr(stream_fsname, '/'));
2518 2519                          } else {
2519 2520                                  tryname[0] = '\0';
2520 2521                                  if (flags->verbose) {
2521 2522                                          (void) printf("local fs %s new parent "
2522 2523                                              "not found\n", fsname);
2523 2524                                  }
2524 2525                          }
2525 2526  
2526 2527                          newname[0] = '\0';
2527 2528  
2528 2529                          error = recv_rename(hdl, fsname, tryname,
2529 2530                              strlen(tofs)+1, newname, flags);
2530 2531  
2531 2532                          if (renamed != NULL && newname[0] != '\0') {
2532 2533                                  VERIFY(0 == nvlist_add_boolean(renamed,
2533 2534                                      newname));
2534 2535                          }
2535 2536  
2536 2537                          if (error)
2537 2538                                  needagain = B_TRUE;
2538 2539                          else
2539 2540                                  progress = B_TRUE;
2540 2541                  }
2541 2542          }
2542 2543  
2543 2544          fsavl_destroy(local_avl);
2544 2545          nvlist_free(local_nv);
2545 2546  
2546 2547          if (needagain && progress) {
2547 2548                  /* do another pass to fix up temporary names */
2548 2549                  if (flags->verbose)
2549 2550                          (void) printf("another pass:\n");
2550 2551                  goto again;
2551 2552          }
2552 2553  
2553 2554          return (needagain);
  
    | 
      ↓ open down ↓ | 
    2482 lines elided | 
    
      ↑ open up ↑ | 
  
2554 2555  }
2555 2556  
2556 2557  static int
2557 2558  zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2558 2559      recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2559 2560      char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2560 2561  {
2561 2562          nvlist_t *stream_nv = NULL;
2562 2563          avl_tree_t *stream_avl = NULL;
2563 2564          char *fromsnap = NULL;
     2565 +        char *sendsnap = NULL;
2564 2566          char *cp;
2565 2567          char tofs[ZFS_MAXNAMELEN];
2566 2568          char sendfs[ZFS_MAXNAMELEN];
2567 2569          char errbuf[1024];
2568 2570          dmu_replay_record_t drre;
2569 2571          int error;
2570 2572          boolean_t anyerr = B_FALSE;
2571 2573          boolean_t softerr = B_FALSE;
2572 2574          boolean_t recursive;
2573 2575  
2574 2576          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2575 2577              "cannot receive"));
2576 2578  
2577 2579          assert(drr->drr_type == DRR_BEGIN);
2578 2580          assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2579 2581          assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2580 2582              DMU_COMPOUNDSTREAM);
2581 2583  
2582 2584          /*
2583 2585           * Read in the nvlist from the stream.
2584 2586           */
2585 2587          if (drr->drr_payloadlen != 0) {
2586 2588                  error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen,
2587 2589                      &stream_nv, flags->byteswap, zc);
2588 2590                  if (error) {
2589 2591                          error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
2590 2592                          goto out;
2591 2593                  }
2592 2594          }
2593 2595  
2594 2596          recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2595 2597              ENOENT);
2596 2598  
2597 2599          if (recursive && strchr(destname, '@')) {
2598 2600                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2599 2601                      "cannot specify snapshot name for multi-snapshot stream"));
2600 2602                  error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
2601 2603                  goto out;
2602 2604          }
2603 2605  
2604 2606          /*
2605 2607           * Read in the end record and verify checksum.
2606 2608           */
2607 2609          if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre),
2608 2610              flags->byteswap, NULL)))
2609 2611                  goto out;
2610 2612          if (flags->byteswap) {
2611 2613                  drre.drr_type = BSWAP_32(drre.drr_type);
2612 2614                  drre.drr_u.drr_end.drr_checksum.zc_word[0] =
2613 2615                      BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]);
2614 2616                  drre.drr_u.drr_end.drr_checksum.zc_word[1] =
2615 2617                      BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[1]);
2616 2618                  drre.drr_u.drr_end.drr_checksum.zc_word[2] =
2617 2619                      BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[2]);
2618 2620                  drre.drr_u.drr_end.drr_checksum.zc_word[3] =
2619 2621                      BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[3]);
2620 2622          }
2621 2623          if (drre.drr_type != DRR_END) {
2622 2624                  error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
2623 2625                  goto out;
2624 2626          }
2625 2627          if (!ZIO_CHECKSUM_EQUAL(drre.drr_u.drr_end.drr_checksum, *zc)) {
2626 2628                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2627 2629                      "incorrect header checksum"));
2628 2630                  error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
2629 2631                  goto out;
2630 2632          }
2631 2633  
2632 2634          (void) nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap);
2633 2635  
2634 2636          if (drr->drr_payloadlen != 0) {
2635 2637                  nvlist_t *stream_fss;
2636 2638  
2637 2639                  VERIFY(0 == nvlist_lookup_nvlist(stream_nv, "fss",
2638 2640                      &stream_fss));
2639 2641                  if ((stream_avl = fsavl_create(stream_fss)) == NULL) {
2640 2642                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2641 2643                              "couldn't allocate avl tree"));
2642 2644                          error = zfs_error(hdl, EZFS_NOMEM, errbuf);
2643 2645                          goto out;
2644 2646                  }
2645 2647  
2646 2648                  if (fromsnap != NULL) {
2647 2649                          nvlist_t *renamed = NULL;
2648 2650                          nvpair_t *pair = NULL;
2649 2651  
2650 2652                          (void) strlcpy(tofs, destname, ZFS_MAXNAMELEN);
2651 2653                          if (flags->isprefix) {
2652 2654                                  struct drr_begin *drrb = &drr->drr_u.drr_begin;
2653 2655                                  int i;
2654 2656  
2655 2657                                  if (flags->istail) {
2656 2658                                          cp = strrchr(drrb->drr_toname, '/');
2657 2659                                          if (cp == NULL) {
2658 2660                                                  (void) strlcat(tofs, "/",
2659 2661                                                      ZFS_MAXNAMELEN);
2660 2662                                                  i = 0;
2661 2663                                          } else {
2662 2664                                                  i = (cp - drrb->drr_toname);
2663 2665                                          }
2664 2666                                  } else {
2665 2667                                          i = strcspn(drrb->drr_toname, "/@");
2666 2668                                  }
2667 2669                                  /* zfs_receive_one() will create_parents() */
2668 2670                                  (void) strlcat(tofs, &drrb->drr_toname[i],
2669 2671                                      ZFS_MAXNAMELEN);
2670 2672                                  *strchr(tofs, '@') = '\0';
2671 2673                          }
2672 2674  
2673 2675                          if (recursive && !flags->dryrun && !flags->nomount) {
2674 2676                                  VERIFY(0 == nvlist_alloc(&renamed,
2675 2677                                      NV_UNIQUE_NAME, 0));
2676 2678                          }
2677 2679  
2678 2680                          softerr = recv_incremental_replication(hdl, tofs, flags,
2679 2681                              stream_nv, stream_avl, renamed);
2680 2682  
2681 2683                          /* Unmount renamed filesystems before receiving. */
2682 2684                          while ((pair = nvlist_next_nvpair(renamed,
2683 2685                              pair)) != NULL) {
2684 2686                                  zfs_handle_t *zhp;
2685 2687                                  prop_changelist_t *clp = NULL;
2686 2688  
2687 2689                                  zhp = zfs_open(hdl, nvpair_name(pair),
2688 2690                                      ZFS_TYPE_FILESYSTEM);
2689 2691                                  if (zhp != NULL) {
2690 2692                                          clp = changelist_gather(zhp,
2691 2693                                              ZFS_PROP_MOUNTPOINT, 0, 0);
2692 2694                                          zfs_close(zhp);
2693 2695                                          if (clp != NULL) {
2694 2696                                                  softerr |=
2695 2697                                                      changelist_prefix(clp);
2696 2698                                                  changelist_free(clp);
2697 2699                                          }
2698 2700                                  }
2699 2701                          }
2700 2702  
2701 2703                          nvlist_free(renamed);
  
    | 
      ↓ open down ↓ | 
    128 lines elided | 
    
      ↑ open up ↑ | 
  
2702 2704                  }
2703 2705          }
2704 2706  
2705 2707          /*
2706 2708           * Get the fs specified by the first path in the stream (the top level
2707 2709           * specified by 'zfs send') and pass it to each invocation of
2708 2710           * zfs_receive_one().
2709 2711           */
2710 2712          (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2711 2713              ZFS_MAXNAMELEN);
2712      -        if ((cp = strchr(sendfs, '@')) != NULL)
     2714 +        if ((cp = strchr(sendfs, '@')) != NULL) {
2713 2715                  *cp = '\0';
     2716 +                /*
     2717 +                 * Find the "sendsnap", the final snapshot in a replication
     2718 +                 * stream.  zfs_receive_one() handles certain errors
     2719 +                 * differently, depending on if the contained stream is the
     2720 +                 * last one or not.
     2721 +                 */
     2722 +                sendsnap = (cp + 1);
     2723 +        }
2714 2724  
2715 2725          /* Finally, receive each contained stream */
2716 2726          do {
2717 2727                  /*
2718 2728                   * we should figure out if it has a recoverable
2719 2729                   * error, in which case do a recv_skip() and drive on.
2720 2730                   * Note, if we fail due to already having this guid,
2721 2731                   * zfs_receive_one() will take care of it (ie,
2722 2732                   * recv_skip() and return 0).
2723 2733                   */
2724 2734                  error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
2725 2735                      sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2726      -                    action_handlep);
     2736 +                    action_handlep, sendsnap);
2727 2737                  if (error == ENODATA) {
2728 2738                          error = 0;
2729 2739                          break;
2730 2740                  }
2731 2741                  anyerr |= error;
2732 2742          } while (error == 0);
2733 2743  
2734 2744          if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2735 2745                  /*
2736 2746                   * Now that we have the fs's they sent us, try the
2737 2747                   * renames again.
2738 2748                   */
2739 2749                  softerr = recv_incremental_replication(hdl, tofs, flags,
2740 2750                      stream_nv, stream_avl, NULL);
2741 2751          }
2742 2752  
2743 2753  out:
2744 2754          fsavl_destroy(stream_avl);
2745 2755          if (stream_nv)
2746 2756                  nvlist_free(stream_nv);
2747 2757          if (softerr)
2748 2758                  error = -2;
2749 2759          if (anyerr)
2750 2760                  error = -1;
2751 2761          return (error);
2752 2762  }
2753 2763  
2754 2764  static void
2755 2765  trunc_prop_errs(int truncated)
2756 2766  {
2757 2767          ASSERT(truncated != 0);
2758 2768  
2759 2769          if (truncated == 1)
2760 2770                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
2761 2771                      "1 more property could not be set\n"));
2762 2772          else
2763 2773                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
2764 2774                      "%d more properties could not be set\n"), truncated);
2765 2775  }
2766 2776  
2767 2777  static int
2768 2778  recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
2769 2779  {
2770 2780          dmu_replay_record_t *drr;
2771 2781          void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);
2772 2782          char errbuf[1024];
2773 2783  
2774 2784          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2775 2785              "cannot receive:"));
2776 2786  
2777 2787          /* XXX would be great to use lseek if possible... */
2778 2788          drr = buf;
2779 2789  
2780 2790          while (recv_read(hdl, fd, drr, sizeof (dmu_replay_record_t),
2781 2791              byteswap, NULL) == 0) {
2782 2792                  if (byteswap)
2783 2793                          drr->drr_type = BSWAP_32(drr->drr_type);
2784 2794  
2785 2795                  switch (drr->drr_type) {
2786 2796                  case DRR_BEGIN:
2787 2797                          if (drr->drr_payloadlen != 0) {
2788 2798                                  (void) recv_read(hdl, fd, buf,
2789 2799                                      drr->drr_payloadlen, B_FALSE, NULL);
2790 2800                          }
2791 2801                          break;
2792 2802  
2793 2803                  case DRR_END:
2794 2804                          free(buf);
2795 2805                          return (0);
2796 2806  
2797 2807                  case DRR_OBJECT:
2798 2808                          if (byteswap) {
2799 2809                                  drr->drr_u.drr_object.drr_bonuslen =
2800 2810                                      BSWAP_32(drr->drr_u.drr_object.
2801 2811                                      drr_bonuslen);
2802 2812                          }
2803 2813                          (void) recv_read(hdl, fd, buf,
2804 2814                              P2ROUNDUP(drr->drr_u.drr_object.drr_bonuslen, 8),
2805 2815                              B_FALSE, NULL);
2806 2816                          break;
2807 2817  
2808 2818                  case DRR_WRITE:
2809 2819                          if (byteswap) {
2810 2820                                  drr->drr_u.drr_write.drr_length =
2811 2821                                      BSWAP_64(drr->drr_u.drr_write.drr_length);
2812 2822                          }
2813 2823                          (void) recv_read(hdl, fd, buf,
2814 2824                              drr->drr_u.drr_write.drr_length, B_FALSE, NULL);
2815 2825                          break;
2816 2826                  case DRR_SPILL:
2817 2827                          if (byteswap) {
2818 2828                                  drr->drr_u.drr_write.drr_length =
2819 2829                                      BSWAP_64(drr->drr_u.drr_spill.drr_length);
2820 2830                          }
2821 2831                          (void) recv_read(hdl, fd, buf,
2822 2832                              drr->drr_u.drr_spill.drr_length, B_FALSE, NULL);
2823 2833                          break;
2824 2834                  case DRR_WRITE_EMBEDDED:
2825 2835                          if (byteswap) {
2826 2836                                  drr->drr_u.drr_write_embedded.drr_psize =
2827 2837                                      BSWAP_32(drr->drr_u.drr_write_embedded.
2828 2838                                      drr_psize);
2829 2839                          }
2830 2840                          (void) recv_read(hdl, fd, buf,
2831 2841                              P2ROUNDUP(drr->drr_u.drr_write_embedded.drr_psize,
2832 2842                              8), B_FALSE, NULL);
2833 2843                          break;
2834 2844                  case DRR_WRITE_BYREF:
2835 2845                  case DRR_FREEOBJECTS:
2836 2846                  case DRR_FREE:
2837 2847                          break;
2838 2848  
2839 2849                  default:
2840 2850                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2841 2851                              "invalid record type"));
2842 2852                          return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2843 2853                  }
2844 2854          }
2845 2855  
2846 2856          free(buf);
2847 2857          return (-1);
2848 2858  }
2849 2859  
2850 2860  static void
2851 2861  recv_ecksum_set_aux(libzfs_handle_t *hdl, const char *target_snap,
2852 2862      boolean_t resumable)
2853 2863  {
2854 2864          char target_fs[ZFS_MAXNAMELEN];
2855 2865  
2856 2866          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2857 2867              "checksum mismatch or incomplete stream"));
2858 2868  
2859 2869          if (!resumable)
2860 2870                  return;
2861 2871          (void) strlcpy(target_fs, target_snap, sizeof (target_fs));
2862 2872          *strchr(target_fs, '@') = '\0';
2863 2873          zfs_handle_t *zhp = zfs_open(hdl, target_fs,
2864 2874              ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
2865 2875          if (zhp == NULL)
2866 2876                  return;
2867 2877  
2868 2878          char token_buf[ZFS_MAXPROPLEN];
2869 2879          int error = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
2870 2880              token_buf, sizeof (token_buf),
2871 2881              NULL, NULL, 0, B_TRUE);
2872 2882          if (error == 0) {
2873 2883                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2874 2884                      "checksum mismatch or incomplete stream.\n"
2875 2885                      "Partially received snapshot is saved.\n"
2876 2886                      "A resuming stream can be generated on the sending "
2877 2887                      "system by running:\n"
2878 2888                      "    zfs send -t %s"),
2879 2889                      token_buf);
2880 2890          }
2881 2891          zfs_close(zhp);
  
    | 
      ↓ open down ↓ | 
    145 lines elided | 
    
      ↑ open up ↑ | 
  
2882 2892  }
2883 2893  
2884 2894  /*
2885 2895   * Restores a backup of tosnap from the file descriptor specified by infd.
2886 2896   */
2887 2897  static int
2888 2898  zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2889 2899      const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
2890 2900      dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
2891 2901      avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2892      -    uint64_t *action_handlep)
     2902 +    uint64_t *action_handlep, const char *finalsnap)
2893 2903  {
2894 2904          zfs_cmd_t zc = { 0 };
2895 2905          time_t begin_time;
2896 2906          int ioctl_err, ioctl_errno, err;
2897 2907          char *cp;
2898 2908          struct drr_begin *drrb = &drr->drr_u.drr_begin;
2899 2909          char errbuf[1024];
2900 2910          char prop_errbuf[1024];
2901 2911          const char *chopprefix;
2902 2912          boolean_t newfs = B_FALSE;
2903 2913          boolean_t stream_wantsnewfs;
2904 2914          uint64_t parent_snapguid = 0;
2905 2915          prop_changelist_t *clp = NULL;
2906 2916          nvlist_t *snapprops_nvlist = NULL;
2907 2917          zprop_errflags_t prop_errflags;
2908 2918          boolean_t recursive;
     2919 +        char *snapname = NULL;
2909 2920  
2910 2921          begin_time = time(NULL);
2911 2922  
2912 2923          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2913 2924              "cannot receive"));
2914 2925  
2915 2926          recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2916 2927              ENOENT);
2917 2928  
2918 2929          if (stream_avl != NULL) {
2919      -                char *snapname;
2920 2930                  nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2921 2931                      &snapname);
2922 2932                  nvlist_t *props;
2923 2933                  int ret;
2924 2934  
2925 2935                  (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2926 2936                      &parent_snapguid);
2927 2937                  err = nvlist_lookup_nvlist(fs, "props", &props);
2928 2938                  if (err)
2929 2939                          VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2930 2940  
2931 2941                  if (flags->canmountoff) {
2932 2942                          VERIFY(0 == nvlist_add_uint64(props,
2933 2943                              zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2934 2944                  }
2935 2945                  ret = zcmd_write_src_nvlist(hdl, &zc, props);
2936 2946                  if (err)
2937 2947                          nvlist_free(props);
2938 2948  
2939 2949                  if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
2940 2950                          VERIFY(0 == nvlist_lookup_nvlist(props,
2941 2951                              snapname, &snapprops_nvlist));
2942 2952                  }
2943 2953  
2944 2954                  if (ret != 0)
2945 2955                          return (-1);
2946 2956          }
2947 2957  
2948 2958          cp = NULL;
2949 2959  
2950 2960          /*
2951 2961           * Determine how much of the snapshot name stored in the stream
2952 2962           * we are going to tack on to the name they specified on the
2953 2963           * command line, and how much we are going to chop off.
2954 2964           *
2955 2965           * If they specified a snapshot, chop the entire name stored in
2956 2966           * the stream.
2957 2967           */
2958 2968          if (flags->istail) {
2959 2969                  /*
2960 2970                   * A filesystem was specified with -e. We want to tack on only
2961 2971                   * the tail of the sent snapshot path.
2962 2972                   */
2963 2973                  if (strchr(tosnap, '@')) {
2964 2974                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2965 2975                              "argument - snapshot not allowed with -e"));
2966 2976                          return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2967 2977                  }
2968 2978  
2969 2979                  chopprefix = strrchr(sendfs, '/');
2970 2980  
2971 2981                  if (chopprefix == NULL) {
2972 2982                          /*
2973 2983                           * The tail is the poolname, so we need to
2974 2984                           * prepend a path separator.
2975 2985                           */
2976 2986                          int len = strlen(drrb->drr_toname);
2977 2987                          cp = malloc(len + 2);
2978 2988                          cp[0] = '/';
2979 2989                          (void) strcpy(&cp[1], drrb->drr_toname);
2980 2990                          chopprefix = cp;
2981 2991                  } else {
2982 2992                          chopprefix = drrb->drr_toname + (chopprefix - sendfs);
2983 2993                  }
2984 2994          } else if (flags->isprefix) {
2985 2995                  /*
2986 2996                   * A filesystem was specified with -d. We want to tack on
2987 2997                   * everything but the first element of the sent snapshot path
2988 2998                   * (all but the pool name).
2989 2999                   */
2990 3000                  if (strchr(tosnap, '@')) {
2991 3001                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2992 3002                              "argument - snapshot not allowed with -d"));
2993 3003                          return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2994 3004                  }
2995 3005  
2996 3006                  chopprefix = strchr(drrb->drr_toname, '/');
2997 3007                  if (chopprefix == NULL)
2998 3008                          chopprefix = strchr(drrb->drr_toname, '@');
2999 3009          } else if (strchr(tosnap, '@') == NULL) {
3000 3010                  /*
3001 3011                   * If a filesystem was specified without -d or -e, we want to
3002 3012                   * tack on everything after the fs specified by 'zfs send'.
3003 3013                   */
3004 3014                  chopprefix = drrb->drr_toname + strlen(sendfs);
3005 3015          } else {
3006 3016                  /* A snapshot was specified as an exact path (no -d or -e). */
3007 3017                  if (recursive) {
3008 3018                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3009 3019                              "cannot specify snapshot name for multi-snapshot "
3010 3020                              "stream"));
3011 3021                          return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3012 3022                  }
3013 3023                  chopprefix = drrb->drr_toname + strlen(drrb->drr_toname);
3014 3024          }
3015 3025  
3016 3026          ASSERT(strstr(drrb->drr_toname, sendfs) == drrb->drr_toname);
3017 3027          ASSERT(chopprefix > drrb->drr_toname);
3018 3028          ASSERT(chopprefix <= drrb->drr_toname + strlen(drrb->drr_toname));
3019 3029          ASSERT(chopprefix[0] == '/' || chopprefix[0] == '@' ||
3020 3030              chopprefix[0] == '\0');
3021 3031  
3022 3032          /*
3023 3033           * Determine name of destination snapshot, store in zc_value.
3024 3034           */
3025 3035          (void) strcpy(zc.zc_value, tosnap);
3026 3036          (void) strncat(zc.zc_value, chopprefix, sizeof (zc.zc_value));
3027 3037          free(cp);
3028 3038          if (!zfs_name_valid(zc.zc_value, ZFS_TYPE_SNAPSHOT)) {
3029 3039                  zcmd_free_nvlists(&zc);
3030 3040                  return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3031 3041          }
3032 3042  
3033 3043          /*
3034 3044           * Determine the name of the origin snapshot, store in zc_string.
3035 3045           */
3036 3046          if (drrb->drr_flags & DRR_FLAG_CLONE) {
3037 3047                  if (guid_to_name(hdl, zc.zc_value,
3038 3048                      drrb->drr_fromguid, B_FALSE, zc.zc_string) != 0) {
3039 3049                          zcmd_free_nvlists(&zc);
3040 3050                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3041 3051                              "local origin for clone %s does not exist"),
3042 3052                              zc.zc_value);
3043 3053                          return (zfs_error(hdl, EZFS_NOENT, errbuf));
3044 3054                  }
3045 3055                  if (flags->verbose)
3046 3056                          (void) printf("found clone origin %s\n", zc.zc_string);
3047 3057          } else if (originsnap) {
3048 3058                  (void) strncpy(zc.zc_string, originsnap, ZFS_MAXNAMELEN);
3049 3059                  if (flags->verbose)
3050 3060                          (void) printf("using provided clone origin %s\n",
3051 3061                              zc.zc_string);
3052 3062          }
3053 3063  
3054 3064          boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
3055 3065              DMU_BACKUP_FEATURE_RESUMING;
3056 3066          stream_wantsnewfs = (drrb->drr_fromguid == NULL ||
3057 3067              (drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
3058 3068  
3059 3069          if (stream_wantsnewfs) {
3060 3070                  /*
3061 3071                   * if the parent fs does not exist, look for it based on
3062 3072                   * the parent snap GUID
3063 3073                   */
3064 3074                  (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3065 3075                      "cannot receive new filesystem stream"));
3066 3076  
3067 3077                  (void) strcpy(zc.zc_name, zc.zc_value);
3068 3078                  cp = strrchr(zc.zc_name, '/');
3069 3079                  if (cp)
3070 3080                          *cp = '\0';
3071 3081                  if (cp &&
3072 3082                      !zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
3073 3083                          char suffix[ZFS_MAXNAMELEN];
3074 3084                          (void) strcpy(suffix, strrchr(zc.zc_value, '/'));
3075 3085                          if (guid_to_name(hdl, zc.zc_name, parent_snapguid,
3076 3086                              B_FALSE, zc.zc_value) == 0) {
3077 3087                                  *strchr(zc.zc_value, '@') = '\0';
3078 3088                                  (void) strcat(zc.zc_value, suffix);
3079 3089                          }
3080 3090                  }
3081 3091          } else {
3082 3092                  /*
3083 3093                   * if the fs does not exist, look for it based on the
3084 3094                   * fromsnap GUID
3085 3095                   */
3086 3096                  (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3087 3097                      "cannot receive incremental stream"));
3088 3098  
3089 3099                  (void) strcpy(zc.zc_name, zc.zc_value);
3090 3100                  *strchr(zc.zc_name, '@') = '\0';
3091 3101  
3092 3102                  /*
3093 3103                   * If the exact receive path was specified and this is the
3094 3104                   * topmost path in the stream, then if the fs does not exist we
3095 3105                   * should look no further.
3096 3106                   */
3097 3107                  if ((flags->isprefix || (*(chopprefix = drrb->drr_toname +
3098 3108                      strlen(sendfs)) != '\0' && *chopprefix != '@')) &&
3099 3109                      !zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
3100 3110                          char snap[ZFS_MAXNAMELEN];
3101 3111                          (void) strcpy(snap, strchr(zc.zc_value, '@'));
3102 3112                          if (guid_to_name(hdl, zc.zc_name, drrb->drr_fromguid,
3103 3113                              B_FALSE, zc.zc_value) == 0) {
3104 3114                                  *strchr(zc.zc_value, '@') = '\0';
3105 3115                                  (void) strcat(zc.zc_value, snap);
3106 3116                          }
3107 3117                  }
3108 3118          }
3109 3119  
3110 3120          (void) strcpy(zc.zc_name, zc.zc_value);
3111 3121          *strchr(zc.zc_name, '@') = '\0';
3112 3122  
3113 3123          if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
3114 3124                  zfs_handle_t *zhp;
3115 3125  
3116 3126                  /*
3117 3127                   * Destination fs exists.  It must be one of these cases:
3118 3128                   *  - an incremental send stream
3119 3129                   *  - the stream specifies a new fs (full stream or clone)
3120 3130                   *    and they want us to blow away the existing fs (and
3121 3131                   *    have therefore specified -F and removed any snapshots)
3122 3132                   *  - we are resuming a failed receive.
3123 3133                   */
3124 3134                  if (stream_wantsnewfs) {
3125 3135                          if (!flags->force) {
3126 3136                                  zcmd_free_nvlists(&zc);
3127 3137                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3128 3138                                      "destination '%s' exists\n"
3129 3139                                      "must specify -F to overwrite it"),
3130 3140                                      zc.zc_name);
3131 3141                                  return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3132 3142                          }
3133 3143                          if (ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT,
3134 3144                              &zc) == 0) {
3135 3145                                  zcmd_free_nvlists(&zc);
3136 3146                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3137 3147                                      "destination has snapshots (eg. %s)\n"
3138 3148                                      "must destroy them to overwrite it"),
3139 3149                                      zc.zc_name);
3140 3150                                  return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3141 3151                          }
3142 3152                  }
3143 3153  
3144 3154                  if ((zhp = zfs_open(hdl, zc.zc_name,
3145 3155                      ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
3146 3156                          zcmd_free_nvlists(&zc);
3147 3157                          return (-1);
3148 3158                  }
3149 3159  
3150 3160                  if (stream_wantsnewfs &&
3151 3161                      zhp->zfs_dmustats.dds_origin[0]) {
3152 3162                          zcmd_free_nvlists(&zc);
3153 3163                          zfs_close(zhp);
3154 3164                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3155 3165                              "destination '%s' is a clone\n"
3156 3166                              "must destroy it to overwrite it"),
3157 3167                              zc.zc_name);
3158 3168                          return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3159 3169                  }
3160 3170  
3161 3171                  if (!flags->dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
3162 3172                      stream_wantsnewfs) {
3163 3173                          /* We can't do online recv in this case */
3164 3174                          clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0);
3165 3175                          if (clp == NULL) {
3166 3176                                  zfs_close(zhp);
3167 3177                                  zcmd_free_nvlists(&zc);
3168 3178                                  return (-1);
3169 3179                          }
3170 3180                          if (changelist_prefix(clp) != 0) {
3171 3181                                  changelist_free(clp);
3172 3182                                  zfs_close(zhp);
3173 3183                                  zcmd_free_nvlists(&zc);
3174 3184                                  return (-1);
3175 3185                          }
3176 3186                  }
3177 3187  
3178 3188                  /*
3179 3189                   * If we are resuming a newfs, set newfs here so that we will
3180 3190                   * mount it if the recv succeeds this time.  We can tell
3181 3191                   * that it was a newfs on the first recv because the fs
3182 3192                   * itself will be inconsistent (if the fs existed when we
3183 3193                   * did the first recv, we would have received it into
3184 3194                   * .../%recv).
3185 3195                   */
3186 3196                  if (resuming && zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT))
3187 3197                          newfs = B_TRUE;
3188 3198  
3189 3199                  zfs_close(zhp);
3190 3200          } else {
3191 3201                  /*
3192 3202                   * Destination filesystem does not exist.  Therefore we better
3193 3203                   * be creating a new filesystem (either from a full backup, or
3194 3204                   * a clone).  It would therefore be invalid if the user
3195 3205                   * specified only the pool name (i.e. if the destination name
3196 3206                   * contained no slash character).
3197 3207                   */
3198 3208                  if (!stream_wantsnewfs ||
3199 3209                      (cp = strrchr(zc.zc_name, '/')) == NULL) {
3200 3210                          zcmd_free_nvlists(&zc);
3201 3211                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3202 3212                              "destination '%s' does not exist"), zc.zc_name);
3203 3213                          return (zfs_error(hdl, EZFS_NOENT, errbuf));
3204 3214                  }
3205 3215  
3206 3216                  /*
3207 3217                   * Trim off the final dataset component so we perform the
3208 3218                   * recvbackup ioctl to the filesystems's parent.
3209 3219                   */
3210 3220                  *cp = '\0';
3211 3221  
3212 3222                  if (flags->isprefix && !flags->istail && !flags->dryrun &&
3213 3223                      create_parents(hdl, zc.zc_value, strlen(tosnap)) != 0) {
3214 3224                          zcmd_free_nvlists(&zc);
3215 3225                          return (zfs_error(hdl, EZFS_BADRESTORE, errbuf));
3216 3226                  }
3217 3227  
3218 3228                  newfs = B_TRUE;
3219 3229          }
3220 3230  
3221 3231          zc.zc_begin_record = *drr_noswap;
3222 3232          zc.zc_cookie = infd;
3223 3233          zc.zc_guid = flags->force;
3224 3234          zc.zc_resumable = flags->resumable;
3225 3235          if (flags->verbose) {
3226 3236                  (void) printf("%s %s stream of %s into %s\n",
3227 3237                      flags->dryrun ? "would receive" : "receiving",
3228 3238                      drrb->drr_fromguid ? "incremental" : "full",
3229 3239                      drrb->drr_toname, zc.zc_value);
3230 3240                  (void) fflush(stdout);
3231 3241          }
3232 3242  
3233 3243          if (flags->dryrun) {
3234 3244                  zcmd_free_nvlists(&zc);
3235 3245                  return (recv_skip(hdl, infd, flags->byteswap));
3236 3246          }
3237 3247  
3238 3248          zc.zc_nvlist_dst = (uint64_t)(uintptr_t)prop_errbuf;
3239 3249          zc.zc_nvlist_dst_size = sizeof (prop_errbuf);
3240 3250          zc.zc_cleanup_fd = cleanup_fd;
3241 3251          zc.zc_action_handle = *action_handlep;
3242 3252  
3243 3253          err = ioctl_err = zfs_ioctl(hdl, ZFS_IOC_RECV, &zc);
3244 3254          ioctl_errno = errno;
3245 3255          prop_errflags = (zprop_errflags_t)zc.zc_obj;
3246 3256  
3247 3257          if (err == 0) {
3248 3258                  nvlist_t *prop_errors;
3249 3259                  VERIFY(0 == nvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
3250 3260                      zc.zc_nvlist_dst_size, &prop_errors, 0));
3251 3261  
3252 3262                  nvpair_t *prop_err = NULL;
3253 3263  
3254 3264                  while ((prop_err = nvlist_next_nvpair(prop_errors,
3255 3265                      prop_err)) != NULL) {
  
    | 
      ↓ open down ↓ | 
    326 lines elided | 
    
      ↑ open up ↑ | 
  
3256 3266                          char tbuf[1024];
3257 3267                          zfs_prop_t prop;
3258 3268                          int intval;
3259 3269  
3260 3270                          prop = zfs_name_to_prop(nvpair_name(prop_err));
3261 3271                          (void) nvpair_value_int32(prop_err, &intval);
3262 3272                          if (strcmp(nvpair_name(prop_err),
3263 3273                              ZPROP_N_MORE_ERRORS) == 0) {
3264 3274                                  trunc_prop_errs(intval);
3265 3275                                  break;
3266      -                        } else {
     3276 +                        } else if (snapname == NULL || finalsnap == NULL ||
     3277 +                            strcmp(finalsnap, snapname) == 0 ||
     3278 +                            strcmp(nvpair_name(prop_err),
     3279 +                            zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) {
     3280 +                                /*
     3281 +                                 * Skip the special case of, for example,
     3282 +                                 * "refquota", errors on intermediate
     3283 +                                 * snapshots leading up to a final one.
     3284 +                                 * That's why we have all of the checks above.
     3285 +                                 *
     3286 +                                 * See zfs_ioctl.c's extract_delay_props() for
     3287 +                                 * a list of props which can fail on
     3288 +                                 * intermediate snapshots, but shouldn't
     3289 +                                 * affect the overall receive.
     3290 +                                 */
3267 3291                                  (void) snprintf(tbuf, sizeof (tbuf),
3268 3292                                      dgettext(TEXT_DOMAIN,
3269 3293                                      "cannot receive %s property on %s"),
3270 3294                                      nvpair_name(prop_err), zc.zc_name);
3271 3295                                  zfs_setprop_error(hdl, prop, intval, tbuf);
3272 3296                          }
3273 3297                  }
3274 3298                  nvlist_free(prop_errors);
3275 3299          }
3276 3300  
3277 3301          zc.zc_nvlist_dst = 0;
3278 3302          zc.zc_nvlist_dst_size = 0;
3279 3303          zcmd_free_nvlists(&zc);
3280 3304  
3281 3305          if (err == 0 && snapprops_nvlist) {
3282 3306                  zfs_cmd_t zc2 = { 0 };
3283 3307  
3284 3308                  (void) strcpy(zc2.zc_name, zc.zc_value);
3285 3309                  zc2.zc_cookie = B_TRUE; /* received */
3286 3310                  if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) {
3287 3311                          (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc2);
3288 3312                          zcmd_free_nvlists(&zc2);
3289 3313                  }
3290 3314          }
3291 3315  
3292 3316          if (err && (ioctl_errno == ENOENT || ioctl_errno == EEXIST)) {
3293 3317                  /*
3294 3318                   * It may be that this snapshot already exists,
3295 3319                   * in which case we want to consume & ignore it
3296 3320                   * rather than failing.
3297 3321                   */
3298 3322                  avl_tree_t *local_avl;
3299 3323                  nvlist_t *local_nv, *fs;
3300 3324                  cp = strchr(zc.zc_value, '@');
3301 3325  
3302 3326                  /*
3303 3327                   * XXX Do this faster by just iterating over snaps in
3304 3328                   * this fs.  Also if zc_value does not exist, we will
3305 3329                   * get a strange "does not exist" error message.
3306 3330                   */
3307 3331                  *cp = '\0';
3308 3332                  if (gather_nvlist(hdl, zc.zc_value, NULL, NULL, B_FALSE,
3309 3333                      &local_nv, &local_avl) == 0) {
3310 3334                          *cp = '@';
3311 3335                          fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
3312 3336                          fsavl_destroy(local_avl);
3313 3337                          nvlist_free(local_nv);
3314 3338  
3315 3339                          if (fs != NULL) {
3316 3340                                  if (flags->verbose) {
3317 3341                                          (void) printf("snap %s already exists; "
3318 3342                                              "ignoring\n", zc.zc_value);
3319 3343                                  }
3320 3344                                  err = ioctl_err = recv_skip(hdl, infd,
3321 3345                                      flags->byteswap);
3322 3346                          }
3323 3347                  }
3324 3348                  *cp = '@';
3325 3349          }
3326 3350  
3327 3351          if (ioctl_err != 0) {
3328 3352                  switch (ioctl_errno) {
3329 3353                  case ENODEV:
3330 3354                          cp = strchr(zc.zc_value, '@');
3331 3355                          *cp = '\0';
3332 3356                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3333 3357                              "most recent snapshot of %s does not\n"
3334 3358                              "match incremental source"), zc.zc_value);
3335 3359                          (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
3336 3360                          *cp = '@';
3337 3361                          break;
3338 3362                  case ETXTBSY:
3339 3363                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3340 3364                              "destination %s has been modified\n"
3341 3365                              "since most recent snapshot"), zc.zc_name);
3342 3366                          (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
3343 3367                          break;
3344 3368                  case EEXIST:
3345 3369                          cp = strchr(zc.zc_value, '@');
3346 3370                          if (newfs) {
3347 3371                                  /* it's the containing fs that exists */
3348 3372                                  *cp = '\0';
3349 3373                          }
3350 3374                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3351 3375                              "destination already exists"));
3352 3376                          (void) zfs_error_fmt(hdl, EZFS_EXISTS,
3353 3377                              dgettext(TEXT_DOMAIN, "cannot restore to %s"),
3354 3378                              zc.zc_value);
3355 3379                          *cp = '@';
3356 3380                          break;
3357 3381                  case EINVAL:
3358 3382                          (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
3359 3383                          break;
3360 3384                  case ECKSUM:
3361 3385                          recv_ecksum_set_aux(hdl, zc.zc_value, flags->resumable);
3362 3386                          (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
3363 3387                          break;
3364 3388                  case ENOTSUP:
3365 3389                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3366 3390                              "pool must be upgraded to receive this stream."));
3367 3391                          (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
3368 3392                          break;
3369 3393                  case EDQUOT:
3370 3394                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3371 3395                              "destination %s space quota exceeded"), zc.zc_name);
3372 3396                          (void) zfs_error(hdl, EZFS_NOSPC, errbuf);
3373 3397                          break;
3374 3398                  default:
3375 3399                          (void) zfs_standard_error(hdl, ioctl_errno, errbuf);
3376 3400                  }
3377 3401          }
3378 3402  
3379 3403          /*
3380 3404           * Mount the target filesystem (if created).  Also mount any
3381 3405           * children of the target filesystem if we did a replication
3382 3406           * receive (indicated by stream_avl being non-NULL).
3383 3407           */
3384 3408          cp = strchr(zc.zc_value, '@');
3385 3409          if (cp && (ioctl_err == 0 || !newfs)) {
3386 3410                  zfs_handle_t *h;
3387 3411  
3388 3412                  *cp = '\0';
3389 3413                  h = zfs_open(hdl, zc.zc_value,
3390 3414                      ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
3391 3415                  if (h != NULL) {
3392 3416                          if (h->zfs_type == ZFS_TYPE_VOLUME) {
3393 3417                                  *cp = '@';
3394 3418                          } else if (newfs || stream_avl) {
3395 3419                                  /*
3396 3420                                   * Track the first/top of hierarchy fs,
3397 3421                                   * for mounting and sharing later.
3398 3422                                   */
3399 3423                                  if (top_zfs && *top_zfs == NULL)
3400 3424                                          *top_zfs = zfs_strdup(hdl, zc.zc_value);
3401 3425                          }
3402 3426                          zfs_close(h);
3403 3427                  }
3404 3428                  *cp = '@';
3405 3429          }
3406 3430  
3407 3431          if (clp) {
3408 3432                  err |= changelist_postfix(clp);
3409 3433                  changelist_free(clp);
3410 3434          }
3411 3435  
3412 3436          if (prop_errflags & ZPROP_ERR_NOCLEAR) {
3413 3437                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: "
3414 3438                      "failed to clear unreceived properties on %s"),
3415 3439                      zc.zc_name);
3416 3440                  (void) fprintf(stderr, "\n");
3417 3441          }
3418 3442          if (prop_errflags & ZPROP_ERR_NORESTORE) {
3419 3443                  (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: "
3420 3444                      "failed to restore original properties on %s"),
3421 3445                      zc.zc_name);
3422 3446                  (void) fprintf(stderr, "\n");
3423 3447          }
3424 3448  
3425 3449          if (err || ioctl_err)
3426 3450                  return (-1);
3427 3451  
3428 3452          *action_handlep = zc.zc_action_handle;
3429 3453  
3430 3454          if (flags->verbose) {
3431 3455                  char buf1[64];
3432 3456                  char buf2[64];
3433 3457                  uint64_t bytes = zc.zc_cookie;
3434 3458                  time_t delta = time(NULL) - begin_time;
3435 3459                  if (delta == 0)
3436 3460                          delta = 1;
3437 3461                  zfs_nicenum(bytes, buf1, sizeof (buf1));
3438 3462                  zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3439 3463  
3440 3464                  (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
  
    | 
      ↓ open down ↓ | 
    164 lines elided | 
    
      ↑ open up ↑ | 
  
3441 3465                      buf1, delta, buf2);
3442 3466          }
3443 3467  
3444 3468          return (0);
3445 3469  }
3446 3470  
3447 3471  static int
3448 3472  zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
3449 3473      const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
3450 3474      nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
3451      -    uint64_t *action_handlep)
     3475 +    uint64_t *action_handlep, const char *finalsnap)
3452 3476  {
3453 3477          int err;
3454 3478          dmu_replay_record_t drr, drr_noswap;
3455 3479          struct drr_begin *drrb = &drr.drr_u.drr_begin;
3456 3480          char errbuf[1024];
3457 3481          zio_cksum_t zcksum = { 0 };
3458 3482          uint64_t featureflags;
3459 3483          int hdrtype;
3460 3484  
3461 3485          (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3462 3486              "cannot receive"));
3463 3487  
3464 3488          if (flags->isprefix &&
3465 3489              !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3466 3490                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3467 3491                      "(%s) does not exist"), tosnap);
3468 3492                  return (zfs_error(hdl, EZFS_NOENT, errbuf));
3469 3493          }
3470 3494          if (originsnap &&
3471 3495              !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
3472 3496                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified origin fs "
3473 3497                      "(%s) does not exist"), originsnap);
3474 3498                  return (zfs_error(hdl, EZFS_NOENT, errbuf));
3475 3499          }
3476 3500  
3477 3501          /* read in the BEGIN record */
3478 3502          if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE,
3479 3503              &zcksum)))
3480 3504                  return (err);
3481 3505  
3482 3506          if (drr.drr_type == DRR_END || drr.drr_type == BSWAP_32(DRR_END)) {
3483 3507                  /* It's the double end record at the end of a package */
3484 3508                  return (ENODATA);
3485 3509          }
3486 3510  
3487 3511          /* the kernel needs the non-byteswapped begin record */
3488 3512          drr_noswap = drr;
3489 3513  
3490 3514          flags->byteswap = B_FALSE;
3491 3515          if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
3492 3516                  /*
3493 3517                   * We computed the checksum in the wrong byteorder in
3494 3518                   * recv_read() above; do it again correctly.
3495 3519                   */
3496 3520                  bzero(&zcksum, sizeof (zio_cksum_t));
3497 3521                  fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum);
3498 3522                  flags->byteswap = B_TRUE;
3499 3523  
3500 3524                  drr.drr_type = BSWAP_32(drr.drr_type);
3501 3525                  drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen);
3502 3526                  drrb->drr_magic = BSWAP_64(drrb->drr_magic);
3503 3527                  drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo);
3504 3528                  drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
3505 3529                  drrb->drr_type = BSWAP_32(drrb->drr_type);
3506 3530                  drrb->drr_flags = BSWAP_32(drrb->drr_flags);
3507 3531                  drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
3508 3532                  drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
3509 3533          }
3510 3534  
3511 3535          if (drrb->drr_magic != DMU_BACKUP_MAGIC || drr.drr_type != DRR_BEGIN) {
3512 3536                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3513 3537                      "stream (bad magic number)"));
3514 3538                  return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3515 3539          }
3516 3540  
3517 3541          featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
3518 3542          hdrtype = DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo);
3519 3543  
3520 3544          if (!DMU_STREAM_SUPPORTED(featureflags) ||
3521 3545              (hdrtype != DMU_SUBSTREAM && hdrtype != DMU_COMPOUNDSTREAM)) {
3522 3546                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3523 3547                      "stream has unsupported feature, feature flags = %lx"),
3524 3548                      featureflags);
3525 3549                  return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3526 3550          }
3527 3551  
3528 3552          if (strchr(drrb->drr_toname, '@') == NULL) {
3529 3553                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3530 3554                      "stream (bad snapshot name)"));
3531 3555                  return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3532 3556          }
3533 3557  
3534 3558          if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3535 3559                  char nonpackage_sendfs[ZFS_MAXNAMELEN];
3536 3560                  if (sendfs == NULL) {
  
    | 
      ↓ open down ↓ | 
    75 lines elided | 
    
      ↑ open up ↑ | 
  
3537 3561                          /*
3538 3562                           * We were not called from zfs_receive_package(). Get
3539 3563                           * the fs specified by 'zfs send'.
3540 3564                           */
3541 3565                          char *cp;
3542 3566                          (void) strlcpy(nonpackage_sendfs,
3543 3567                              drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3544 3568                          if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3545 3569                                  *cp = '\0';
3546 3570                          sendfs = nonpackage_sendfs;
     3571 +                        VERIFY(finalsnap == NULL);
3547 3572                  }
3548 3573                  return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
3549 3574                      &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
3550      -                    cleanup_fd, action_handlep));
     3575 +                    cleanup_fd, action_handlep, finalsnap));
3551 3576          } else {
3552 3577                  assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3553 3578                      DMU_COMPOUNDSTREAM);
3554 3579                  return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
3555 3580                      &zcksum, top_zfs, cleanup_fd, action_handlep));
3556 3581          }
3557 3582  }
3558 3583  
3559 3584  /*
3560 3585   * Restores a backup of tosnap from the file descriptor specified by infd.
3561 3586   * Return 0 on total success, -2 if some things couldn't be
3562 3587   * destroyed/renamed/promoted, -1 if some things couldn't be received.
3563 3588   * (-1 will override -2, if -1 and the resumable flag was specified the
3564 3589   * transfer can be resumed if the sending side supports it).
3565 3590   */
3566 3591  int
3567 3592  zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
3568 3593      recvflags_t *flags, int infd, avl_tree_t *stream_avl)
3569 3594  {
3570 3595          char *top_zfs = NULL;
3571 3596          int err;
3572 3597          int cleanup_fd;
3573 3598          uint64_t action_handle = 0;
3574 3599          char *originsnap = NULL;
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
3575 3600          if (props) {
3576 3601                  err = nvlist_lookup_string(props, "origin", &originsnap);
3577 3602                  if (err && err != ENOENT)
3578 3603                          return (err);
3579 3604          }
3580 3605  
3581 3606          cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3582 3607          VERIFY(cleanup_fd >= 0);
3583 3608  
3584 3609          err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
3585      -            stream_avl, &top_zfs, cleanup_fd, &action_handle);
     3610 +            stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
3586 3611  
3587 3612          VERIFY(0 == close(cleanup_fd));
3588 3613  
3589 3614          if (err == 0 && !flags->nomount && top_zfs) {
3590 3615                  zfs_handle_t *zhp;
3591 3616                  prop_changelist_t *clp;
3592 3617  
3593 3618                  zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3594 3619                  if (zhp != NULL) {
3595 3620                          clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3596 3621                              CL_GATHER_MOUNT_ALWAYS, 0);
3597 3622                          zfs_close(zhp);
3598 3623                          if (clp != NULL) {
3599 3624                                  /* mount and share received datasets */
3600 3625                                  err = changelist_postfix(clp);
3601 3626                                  changelist_free(clp);
3602 3627                          }
3603 3628                  }
3604 3629                  if (zhp == NULL || clp == NULL || err)
3605 3630                          err = -1;
3606 3631          }
3607 3632          if (top_zfs)
3608 3633                  free(top_zfs);
3609 3634  
3610 3635          return (err);
3611 3636  }
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX