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