MFV r252215:

Restore a previous behavior before r251646, where when destructing
ZFS snapshot, the ioctl would return ENOENT when it hit any of
them in the errlist (the new behavior was only return ENOENT when
all returns error).

Illumos ZFS issues:
  3829 fix for 3740 changed behavior of zfs destroy/hold/release ioctl

MFC after:	1 week
This commit is contained in:
delphij 2013-06-25 22:14:32 +00:00
parent 5240466227
commit 4dfc3c75a2
4 changed files with 26 additions and 37 deletions

View File

@ -21,9 +21,9 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 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) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
@ -4159,6 +4159,7 @@ struct holdarg {
const char *snapname;
const char *tag;
boolean_t recursive;
int error;
};
static int
@ -4286,15 +4287,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)
@ -4318,16 +4324,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);
}

View File

@ -302,11 +302,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
@ -397,15 +394,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.
* 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.
@ -449,13 +441,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.

View File

@ -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);
}

View File

@ -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);
}