Skip to content

Commit

Permalink
3740 Poor ZFS send / receive performance due to snapshot hold / relea…
Browse files Browse the repository at this point in the history
…se processing

Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Christopher Siden <christopher.siden@delphix.com>
  • Loading branch information
Steven Hartland authored and Christopher Siden committed Jun 12, 2013
1 parent 3cb69f7 commit a7a845e
Show file tree
Hide file tree
Showing 14 changed files with 550 additions and 387 deletions.
3 changes: 2 additions & 1 deletion usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/

/*
Expand Down Expand Up @@ -203,7 +204,7 @@ snapshot_hold(char *volname, char *snapname, char *jname, boolean_t recursive)
}

p = strchr(snapname, '@') + 1;
if (zfs_hold(zhp, p, jname, recursive, B_FALSE, cleanup_fd) != 0) {
if (zfs_hold(zhp, p, jname, recursive, cleanup_fd) != 0) {
NDMP_LOG(LOG_ERR, "Cannot hold snapshot %s", p);
zfs_close(zhp);
return (-1);
Expand Down
4 changes: 2 additions & 2 deletions usr/src/cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/

#include <assert.h>
Expand Down Expand Up @@ -5164,8 +5165,7 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
continue;
}
if (holding) {
if (zfs_hold(zhp, delim+1, tag, recursive,
B_FALSE, -1) != 0)
if (zfs_hold(zhp, delim+1, tag, recursive, -1) != 0)
++errors;
} else {
if (zfs_release(zhp, delim+1, tag, recursive) != 0)
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/zhack/zhack.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

/*
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/

/*
Expand Down Expand Up @@ -153,7 +154,7 @@ import_pool(const char *target, boolean_t readonly)
g_importargs.poolname = g_pool;
pools = zpool_search_import(g_zfs, &g_importargs);

if (pools == NULL || nvlist_next_nvpair(pools, NULL) == NULL) {
if (nvlist_empty(pools)) {
if (!g_importargs.can_be_active) {
g_importargs.can_be_active = B_TRUE;
if (zpool_search_import(g_zfs, &g_importargs) != NULL ||
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/ztest/ztest.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/

/*
Expand Down Expand Up @@ -4711,7 +4712,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)

error = user_release_one(fullname, tag);
if (error)
fatal(0, "user_release_one(%s)", fullname, tag);
fatal(0, "user_release_one(%s, %s) = %d", fullname, tag, error);

VERIFY3U(dmu_objset_hold(fullname, FTAG, &origin), ==, ENOENT);

Expand Down
4 changes: 3 additions & 1 deletion usr/src/lib/libzfs/common/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/

#ifndef _LIBZFS_H
Expand Down Expand Up @@ -594,7 +595,8 @@ extern int zfs_send(zfs_handle_t *, const char *, const char *,

extern int zfs_promote(zfs_handle_t *);
extern int zfs_hold(zfs_handle_t *, const char *, const char *,
boolean_t, boolean_t, int);
boolean_t, int);
extern int zfs_hold_nvl(zfs_handle_t *, int, nvlist_t *);
extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t);
extern int zfs_get_holds(zfs_handle_t *, nvlist_t **);
extern uint64_t zvol_volsize_to_reservation(uint64_t, nvlist_t *);
Expand Down
91 changes: 44 additions & 47 deletions usr/src/lib/libzfs/common/libzfs_dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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"));
Expand Down Expand Up @@ -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);
Expand All @@ -4103,41 +4096,55 @@ 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;
ha.tag = 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"));
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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];
Expand All @@ -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),
Expand All @@ -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"));
Expand Down
Loading

0 comments on commit a7a845e

Please sign in to comment.