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