Print this page
3740 Poor ZFS send / receive performance due to snapshot hold / release processing
Submitted by: Steven Hartland <steven.hartland@multiplay.co.uk>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libzfs_core/common/libzfs_core.c
          +++ new/usr/src/lib/libzfs_core/common/libzfs_core.c
↓ open down ↓ 338 lines elided ↑ open up ↑
 339  339   * The keys in the nvlist are snapshot names.
 340  340   * The snapshots must all be in the same pool.
 341  341   * The value is the name of the hold (string type).
 342  342   *
 343  343   * If cleanup_fd is not -1, it must be the result of open("/dev/zfs", O_EXCL).
 344  344   * In this case, when the cleanup_fd is closed (including on process
 345  345   * termination), the holds will be released.  If the system is shut down
 346  346   * uncleanly, the holds will be released when the pool is next opened
 347  347   * or imported.
 348  348   *
 349      - * The return value will be 0 if all holds were created. Otherwise the return
 350      - * value will be the errno of a (unspecified) hold that failed, no holds will
 351      - * be created, and the errlist will have an entry for each hold that
 352      - * failed (name = snapshot).  The value in the errlist will be the error
 353      - * code (int32).
      349 + * Holds for snapshots which don't exist will be skipped and have an entry
      350 + * added to errlist, but will not cause an overall failure, except in the
      351 + * case that all holds where skipped.
      352 + *
      353 + * The return value will be 0 if the nvl holds was empty or all holds, for
      354 + * snapshots that existed, were succesfully created and at least one hold
      355 + * was created.
      356 + *
      357 + * If none of the snapshots for the requested holds existed ENOENT will be
      358 + * returned.
      359 + *
      360 + * Otherwise the return value will be the errno of a (unspecified) hold that
      361 + * failed, no holds will be created.
      362 + *
      363 + * In all cases the errlist will have an entry for each hold that failed
      364 + * (name = snapshot), with its value being the error code (int32).
 354  365   */
 355  366  int
 356  367  lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
 357  368  {
 358  369          char pool[MAXNAMELEN];
 359  370          nvlist_t *args;
 360  371          nvpair_t *elem;
 361  372          int error;
 362  373  
 363  374          /* determine the pool name */
↓ open down ↓ 16 lines elided ↑ open up ↑
 380  391  /*
 381  392   * Release "user holds" on snapshots.  If the snapshot has been marked for
 382  393   * deferred destroy (by lzc_destroy_snaps(defer=B_TRUE)), it does not have
 383  394   * any clones, and all the user holds are removed, then the snapshot will be
 384  395   * destroyed.
 385  396   *
 386  397   * The keys in the nvlist are snapshot names.
 387  398   * The snapshots must all be in the same pool.
 388  399   * The value is a nvlist whose keys are the holds to remove.
 389  400   *
 390      - * The return value will be 0 if all holds were removed.
 391      - * Otherwise the return value will be the errno of a (unspecified) release
 392      - * that failed, no holds will be released, and the errlist will have an
 393      - * entry for each snapshot that has failed releases (name = snapshot).
 394      - * The value in the errlist will be the error code (int32) of a failed release.
      401 + * Holds which failed to release because they didn't exist will have an entry
      402 + * added to errlist, but will not cause an overall failure.
      403 + *
      404 + * The return value will be 0 if the nvl holds was empty or all holds, that
      405 + * existed, were succesfully removed and at least one hold was removed.
      406 + *
      407 + * If none of the holds specified existed ENOENT will be returned.
      408 + *
      409 + * Otherwise the return value will be the errno of a (unspecified) hold that
      410 + * failed to release and no holds will be released.
      411 + *
      412 + * In all cases the errlist will have an entry for each hold that failed to
      413 + * to release.
 395  414   */
 396  415  int
 397  416  lzc_release(nvlist_t *holds, nvlist_t **errlist)
 398  417  {
 399  418          char pool[MAXNAMELEN];
 400  419          nvpair_t *elem;
 401  420  
 402  421          /* determine the pool name */
 403  422          elem = nvlist_next_nvpair(holds, NULL);
 404  423          if (elem == NULL)
↓ open down ↓ 167 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX