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

*** 4079,4128 **** static int zfs_hold_one(zfs_handle_t *zhp, void *arg) { struct holdarg *ha = arg; - zfs_handle_t *szhp; char name[ZFS_MAXNAMELEN]; int rv = 0; (void) snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, ha->snapname); ! szhp = make_dataset_handle(zhp->zfs_hdl, name); ! if (szhp) { fnvlist_add_string(ha->nvl, name, ha->tag); - zfs_close(szhp); - } if (ha->recursive) rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha); zfs_close(zhp); return (rv); } int zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, ! boolean_t recursive, boolean_t enoent_ok, int cleanup_fd) { int ret; struct holdarg ha; - nvlist_t *errors; - libzfs_handle_t *hdl = zhp->zfs_hdl; - char errbuf[1024]; - nvpair_t *elem; ha.nvl = fnvlist_alloc(); ha.snapname = snapname; ha.tag = tag; ha.recursive = recursive; (void) zfs_hold_one(zfs_handle_dup(zhp), &ha); ! ret = lzc_hold(ha.nvl, cleanup_fd, &errors); fnvlist_free(ha.nvl); ! if (ret == 0) return (0); if (nvlist_next_nvpair(errors, NULL) == NULL) { /* no hold-specific errors */ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot hold")); --- 4079,4138 ---- static int zfs_hold_one(zfs_handle_t *zhp, void *arg) { struct holdarg *ha = arg; char name[ZFS_MAXNAMELEN]; int rv = 0; (void) snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, ha->snapname); ! if (lzc_exists(name)) fnvlist_add_string(ha->nvl, name, ha->tag); if (ha->recursive) rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha); zfs_close(zhp); return (rv); } int zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, ! boolean_t recursive, int cleanup_fd) { int ret; struct holdarg ha; ha.nvl = fnvlist_alloc(); ha.snapname = snapname; ha.tag = tag; ha.recursive = recursive; (void) zfs_hold_one(zfs_handle_dup(zhp), &ha); ! ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl); fnvlist_free(ha.nvl); ! return (ret); ! } ! ! int ! zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds) ! { ! int ret; ! nvlist_t *errors; ! libzfs_handle_t *hdl = zhp->zfs_hdl; ! char errbuf[1024]; ! nvpair_t *elem; ! ! errors = NULL; ! ret = lzc_hold(holds, cleanup_fd, &errors); ! ! if (ret == 0) { ! /* There may be errors even in the success case. */ ! fnvlist_free(errors); return (0); + } if (nvlist_next_nvpair(errors, NULL) == NULL) { /* no hold-specific errors */ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot hold"));
*** 4160,4207 **** (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); break; case EEXIST: (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf); break; - case ENOENT: - if (enoent_ok) - return (ENOENT); - /* FALLTHROUGH */ default: (void) zfs_standard_error(hdl, fnvpair_value_int32(elem), errbuf); } } fnvlist_free(errors); return (ret); } - struct releasearg { - nvlist_t *nvl; - const char *snapname; - const char *tag; - boolean_t recursive; - }; - static int zfs_release_one(zfs_handle_t *zhp, void *arg) { struct holdarg *ha = arg; - zfs_handle_t *szhp; char name[ZFS_MAXNAMELEN]; int rv = 0; (void) snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, ha->snapname); ! szhp = make_dataset_handle(zhp->zfs_hdl, name); ! if (szhp) { nvlist_t *holds = fnvlist_alloc(); fnvlist_add_boolean(holds, ha->tag); fnvlist_add_nvlist(ha->nvl, name, holds); ! zfs_close(szhp); } if (ha->recursive) rv = zfs_iter_filesystems(zhp, zfs_release_one, ha); zfs_close(zhp); --- 4170,4204 ---- (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); break; case EEXIST: (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf); break; default: (void) zfs_standard_error(hdl, fnvpair_value_int32(elem), errbuf); } } fnvlist_free(errors); return (ret); } static int zfs_release_one(zfs_handle_t *zhp, void *arg) { struct holdarg *ha = arg; char name[ZFS_MAXNAMELEN]; int rv = 0; (void) snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, ha->snapname); ! if (lzc_exists(name)) { nvlist_t *holds = fnvlist_alloc(); fnvlist_add_boolean(holds, ha->tag); fnvlist_add_nvlist(ha->nvl, name, holds); ! fnvlist_free(holds); } if (ha->recursive) rv = zfs_iter_filesystems(zhp, zfs_release_one, ha); zfs_close(zhp);
*** 4221,4235 **** ha.nvl = fnvlist_alloc(); ha.snapname = snapname; ha.tag = tag; ha.recursive = recursive; (void) zfs_release_one(zfs_handle_dup(zhp), &ha); ret = lzc_release(ha.nvl, &errors); fnvlist_free(ha.nvl); ! if (ret == 0) return (0); if (nvlist_next_nvpair(errors, NULL) == NULL) { /* no hold-specific errors */ char errbuf[1024]; --- 4218,4236 ---- ha.nvl = fnvlist_alloc(); ha.snapname = snapname; ha.tag = tag; ha.recursive = recursive; (void) zfs_release_one(zfs_handle_dup(zhp), &ha); + errors = NULL; ret = lzc_release(ha.nvl, &errors); fnvlist_free(ha.nvl); ! if (ret == 0) { ! /* There may be errors even in the success case. */ ! fnvlist_free(errors); return (0); + } if (nvlist_next_nvpair(errors, NULL) == NULL) { /* no hold-specific errors */ char errbuf[1024];