diff options
author | Steven Hartland <smh@freebsd.org> | 2013-06-11 22:01:53 -0800 |
---|---|---|
committer | Christopher Siden <chris.siden@delphix.com> | 2013-06-11 23:01:53 -0700 |
commit | a7a845e4bf22fd1b2a284729ccd95c7370a0438c (patch) | |
tree | 761a7618b306660db2217226a0c2e5e6485f9786 /usr/src/lib/libzfs/common/libzfs_dataset.c | |
parent | 3cb69f734bc60bbb4d56a28c83706db862bec082 (diff) | |
download | illumos-gate-a7a845e4bf22fd1b2a284729ccd95c7370a0438c.tar.gz |
3740 Poor ZFS send / receive performance due to snapshot hold / release processing
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Christopher Siden <christopher.siden@delphix.com>
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_dataset.c')
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_dataset.c | 91 |
1 files changed, 44 insertions, 47 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index 257b77e3db..635bc87e29 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -25,6 +25,7 @@ * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013 Martin Matuska. All rights reserved. + * Copyright (c) 2013 Steven Hartland. All rights reserved. */ #include <ctype.h> @@ -3104,18 +3105,14 @@ static int zfs_check_snap_cb(zfs_handle_t *zhp, void *arg) { struct destroydata *dd = arg; - zfs_handle_t *szhp; char name[ZFS_MAXNAMELEN]; int rv = 0; (void) snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, dd->snapname); - szhp = make_dataset_handle(zhp->zfs_hdl, name); - if (szhp) { + if (lzc_exists(name)) verify(nvlist_add_boolean(dd->nvl, name) == 0); - zfs_close(szhp); - } rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd); zfs_close(zhp); @@ -3135,7 +3132,7 @@ zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer) verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0); (void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd); - if (nvlist_next_nvpair(dd.nvl, NULL) == NULL) { + if (nvlist_empty(dd.nvl)) { ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), zhp->zfs_name, snapname); @@ -3160,7 +3157,7 @@ zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer) if (ret == 0) return (0); - if (nvlist_next_nvpair(errlist, NULL) == NULL) { + if (nvlist_empty(errlist)) { char errbuf[1024]; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot destroy snapshots")); @@ -4082,18 +4079,14 @@ 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) { + if (lzc_exists(name)) fnvlist_add_string(ha->nvl, name, ha->tag); - zfs_close(szhp); - } if (ha->recursive) rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha); @@ -4103,14 +4096,10 @@ zfs_hold_one(zfs_handle_t *zhp, void *arg) int zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, - boolean_t recursive, boolean_t enoent_ok, int cleanup_fd) + boolean_t recursive, 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; @@ -4118,26 +4107,44 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, ha.recursive = recursive; (void) zfs_hold_one(zfs_handle_dup(zhp), &ha); - if (nvlist_next_nvpair(ha.nvl, NULL) == NULL) { + if (nvlist_empty(ha.nvl)) { + char errbuf[1024]; + fnvlist_free(ha.nvl); ret = ENOENT; - if (!enoent_ok) { - (void) snprintf(errbuf, sizeof (errbuf), - dgettext(TEXT_DOMAIN, - "cannot hold snapshot '%s@%s'"), - zhp->zfs_name, snapname); - (void) zfs_standard_error(hdl, ret, errbuf); - } + (void) snprintf(errbuf, sizeof (errbuf), + dgettext(TEXT_DOMAIN, + "cannot hold snapshot '%s@%s'"), + zhp->zfs_name, snapname); + (void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf); return (ret); } - ret = lzc_hold(ha.nvl, cleanup_fd, &errors); + ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl); fnvlist_free(ha.nvl); - if (ret == 0) + 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) { + if (nvlist_empty(errors)) { /* no hold-specific errors */ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot hold")); @@ -4177,10 +4184,6 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, 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); @@ -4191,30 +4194,21 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, 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) { + if (lzc_exists(name)) { nvlist_t *holds = fnvlist_alloc(); fnvlist_add_boolean(holds, ha->tag); fnvlist_add_nvlist(ha->nvl, name, holds); - zfs_close(szhp); + fnvlist_free(holds); } if (ha->recursive) @@ -4229,7 +4223,7 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag, { int ret; struct holdarg ha; - nvlist_t *errors; + nvlist_t *errors = NULL; nvpair_t *elem; libzfs_handle_t *hdl = zhp->zfs_hdl; char errbuf[1024]; @@ -4240,7 +4234,7 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag, ha.recursive = recursive; (void) zfs_release_one(zfs_handle_dup(zhp), &ha); - if (nvlist_next_nvpair(ha.nvl, NULL) == NULL) { + if (nvlist_empty(ha.nvl)) { fnvlist_free(ha.nvl); ret = ENOENT; (void) snprintf(errbuf, sizeof (errbuf), @@ -4254,10 +4248,13 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag, ret = lzc_release(ha.nvl, &errors); fnvlist_free(ha.nvl); - if (ret == 0) + if (ret == 0) { + /* There may be errors even in the success case. */ + fnvlist_free(errors); return (0); + } - if (nvlist_next_nvpair(errors, NULL) == NULL) { + if (nvlist_empty(errors)) { /* no hold-specific errors */ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot release")); |