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];