changeset 14060:aeb4e8fef072

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>
author Matthew Ahrens <mahrens@delphix.com>
date Thu, 20 Jun 2013 14:43:17 -0800
parents 1a63e2c4c1b9
children ea145778fff5
files usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/lib/libzfs_core/common/libzfs_core.c usr/src/uts/common/fs/zfs/dsl_destroy.c usr/src/uts/common/fs/zfs/dsl_userhold.c
diffstat 4 files changed, 25 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Apr 24 18:37:28 2013 +0000
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Thu Jun 20 14:43:17 2013 -0800
@@ -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 @@
 	const char *snapname;
 	const char *tag;
 	boolean_t recursive;
+	int error;
 };
 
 static int
@@ -4200,15 +4201,20 @@
 	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 @@
 	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);
 	}
 
--- a/usr/src/lib/libzfs_core/common/libzfs_core.c	Wed Apr 24 18:37:28 2013 +0000
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.c	Thu Jun 20 14:43:17 2013 -0800
@@ -255,11 +255,8 @@
  * 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 @@
  * 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.
+ * added to errlist, but will not cause an overall failure.
  *
- * The return value will be ENOENT if none of the snapshots for the requested
- * holds existed.
- *
- * 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 @@
  * 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.
--- a/usr/src/uts/common/fs/zfs/dsl_destroy.c	Wed Apr 24 18:37:28 2013 +0000
+++ b/usr/src/uts/common/fs/zfs/dsl_destroy.c	Thu Jun 20 14:43:17 2013 -0800
@@ -129,9 +129,6 @@
 	if (pair != NULL)
 		return (fnvpair_value_int32(pair));
 
-	if (nvlist_empty(dsda->dsda_successful_snaps))
-		return (SET_ERROR(ENOENT));
-
 	return (0);
 }
 
--- a/usr/src/uts/common/fs/zfs/dsl_userhold.c	Wed Apr 24 18:37:28 2013 +0000
+++ b/usr/src/uts/common/fs/zfs/dsl_userhold.c	Thu Jun 20 14:43:17 2013 -0800
@@ -126,10 +126,6 @@
 		}
 	}
 
-	/* Return ENOENT if no holds would be created. */
-	if (nvlist_empty(dduha->dduha_chkholds))
-		return (SET_ERROR(ENOENT));
-
 	return (0);
 }
 
@@ -468,10 +464,6 @@
 		}
 	}
 
-	/* Return ENOENT if none of the holds existed. */
-	if (nvlist_empty(ddura->ddura_chkholds))
-		return (SET_ERROR(ENOENT));
-
 	return (0);
 }