summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Ahrens <mahrens@delphix.com>2013-06-20 14:43:17 -0800
committerChristopher Siden <chris.siden@delphix.com>2013-06-20 15:43:17 -0700
commitbb6e70758d0c30c09f148026d6e686e21cfc8d18 (patch)
tree459ebb70610e7dc95b527e8a677b92f9a6d670e9
parent296749875bd503e7a14e25b4c57d3142cb496df1 (diff)
downloadillumos-joyent-bb6e70758d0c30c09f148026d6e686e21cfc8d18.tar.gz
3829 fix for 3740 changed behavior of zfs destroy/hold/release ioctl
Reviewed by: Matt Amdur <matt.amdur@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c27
-rw-r--r--usr/src/lib/libzfs_core/common/libzfs_core.c23
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_destroy.c3
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_userhold.c8
4 files changed, 25 insertions, 36 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 635bc87e29..58af6dfa04 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
* 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.
@@ -4073,6 +4073,7 @@ struct holdarg {
const char *snapname;
const char *tag;
boolean_t recursive;
+ int error;
};
static int
@@ -4200,15 +4201,20 @@ zfs_release_one(zfs_handle_t *zhp, void *arg)
struct holdarg *ha = arg;
char name[ZFS_MAXNAMELEN];
int rv = 0;
+ nvlist_t *existing_holds;
(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 (lzc_get_holds(name, &existing_holds) != 0) {
+ ha->error = ENOENT;
+ } else if (!nvlist_exists(existing_holds, ha->tag)) {
+ ha->error = ESRCH;
+ } else {
+ nvlist_t *torelease = fnvlist_alloc();
+ fnvlist_add_boolean(torelease, ha->tag);
+ fnvlist_add_nvlist(ha->nvl, name, torelease);
+ fnvlist_free(torelease);
}
if (ha->recursive)
@@ -4232,16 +4238,21 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
ha.snapname = snapname;
ha.tag = tag;
ha.recursive = recursive;
+ ha.error = 0;
(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
if (nvlist_empty(ha.nvl)) {
fnvlist_free(ha.nvl);
- ret = ENOENT;
+ ret = ha.error;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN,
"cannot release hold from snapshot '%s@%s'"),
zhp->zfs_name, snapname);
- (void) zfs_standard_error(hdl, ret, errbuf);
+ if (ret == ESRCH) {
+ (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
+ } else {
+ (void) zfs_standard_error(hdl, ret, errbuf);
+ }
return (ret);
}
diff --git a/usr/src/lib/libzfs_core/common/libzfs_core.c b/usr/src/lib/libzfs_core/common/libzfs_core.c
index 990beafd1f..a4f51233f4 100644
--- a/usr/src/lib/libzfs_core/common/libzfs_core.c
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.c
@@ -255,11 +255,8 @@ lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
* marked for deferred destruction, and will be destroyed when the last hold
* or clone is removed/destroyed.
*
- * The return value will be ENOENT if none of the snapshots existed.
- *
* The return value will be 0 if all snapshots were destroyed (or marked for
- * later destruction if 'defer' is set) or didn't exist to begin with and
- * at least one snapshot was destroyed.
+ * later destruction if 'defer' is set) or didn't exist to begin with.
*
* Otherwise the return value will be the errno of a (unspecified) snapshot
* that failed, no snapshots will be destroyed, and the errlist will have an
@@ -350,15 +347,10 @@ lzc_exists(const char *dataset)
* or imported.
*
* Holds for snapshots which don't exist will be skipped and have an entry
- * added to errlist, but will not cause an overall failure, except in the
- * case that all holds where skipped.
- *
- * The return value will be ENOENT if none of the snapshots for the requested
- * holds existed.
+ * added to errlist, but will not cause an overall failure.
*
- * The return value will be 0 if the nvl holds was empty or all holds, for
- * snapshots that existed, were succesfully created and at least one hold
- * was created.
+ * The return value will be 0 if all holds, for snapshots that existed,
+ * were succesfully created.
*
* Otherwise the return value will be the errno of a (unspecified) hold that
* failed and no holds will be created.
@@ -402,13 +394,10 @@ lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
* The value is a nvlist whose keys are the holds to remove.
*
* Holds which failed to release because they didn't exist will have an entry
- * added to errlist, but will not cause an overall failure, except in the
- * case that all releases where skipped.
- *
- * The return value will be ENOENT if none of the specified holds existed.
+ * added to errlist, but will not cause an overall failure.
*
* The return value will be 0 if the nvl holds was empty or all holds that
- * existed, were successfully removed and at least one hold was removed.
+ * existed, were successfully removed.
*
* Otherwise the return value will be the errno of a (unspecified) hold that
* failed to release and no holds will be released.
diff --git a/usr/src/uts/common/fs/zfs/dsl_destroy.c b/usr/src/uts/common/fs/zfs/dsl_destroy.c
index e74b53f1aa..f968215db0 100644
--- a/usr/src/uts/common/fs/zfs/dsl_destroy.c
+++ b/usr/src/uts/common/fs/zfs/dsl_destroy.c
@@ -129,9 +129,6 @@ dsl_destroy_snapshot_check(void *arg, dmu_tx_t *tx)
if (pair != NULL)
return (fnvpair_value_int32(pair));
- if (nvlist_empty(dsda->dsda_successful_snaps))
- return (SET_ERROR(ENOENT));
-
return (0);
}
diff --git a/usr/src/uts/common/fs/zfs/dsl_userhold.c b/usr/src/uts/common/fs/zfs/dsl_userhold.c
index b6fa417eec..a948e10b12 100644
--- a/usr/src/uts/common/fs/zfs/dsl_userhold.c
+++ b/usr/src/uts/common/fs/zfs/dsl_userhold.c
@@ -126,10 +126,6 @@ dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx)
}
}
- /* Return ENOENT if no holds would be created. */
- if (nvlist_empty(dduha->dduha_chkholds))
- return (SET_ERROR(ENOENT));
-
return (0);
}
@@ -468,10 +464,6 @@ dsl_dataset_user_release_check(void *arg, dmu_tx_t *tx)
}
}
- /* Return ENOENT if none of the holds existed. */
- if (nvlist_empty(ddura->ddura_chkholds))
- return (SET_ERROR(ENOENT));
-
return (0);
}