mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
Illumos #3829
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> References: https://www.illumos.org/issues/3829 illumos/illumos-gate@bb6e70758d Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775
This commit is contained in:
parent
34ffbed88c
commit
1a077756e8
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* 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 (c) 2012 DEY Storage Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
|
||||||
@ -4412,6 +4412,7 @@ struct holdarg {
|
|||||||
const char *snapname;
|
const char *snapname;
|
||||||
const char *tag;
|
const char *tag;
|
||||||
boolean_t recursive;
|
boolean_t recursive;
|
||||||
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -4539,15 +4540,20 @@ zfs_release_one(zfs_handle_t *zhp, void *arg)
|
|||||||
struct holdarg *ha = arg;
|
struct holdarg *ha = arg;
|
||||||
char name[ZFS_MAXNAMELEN];
|
char name[ZFS_MAXNAMELEN];
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
nvlist_t *existing_holds;
|
||||||
|
|
||||||
(void) snprintf(name, sizeof (name),
|
(void) snprintf(name, sizeof (name),
|
||||||
"%s@%s", zhp->zfs_name, ha->snapname);
|
"%s@%s", zhp->zfs_name, ha->snapname);
|
||||||
|
|
||||||
if (lzc_exists(name)) {
|
if (lzc_get_holds(name, &existing_holds) != 0) {
|
||||||
nvlist_t *holds = fnvlist_alloc();
|
ha->error = ENOENT;
|
||||||
fnvlist_add_boolean(holds, ha->tag);
|
} else if (!nvlist_exists(existing_holds, ha->tag)) {
|
||||||
fnvlist_add_nvlist(ha->nvl, name, holds);
|
ha->error = ESRCH;
|
||||||
fnvlist_free(holds);
|
} 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)
|
if (ha->recursive)
|
||||||
@ -4571,16 +4577,21 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
|
|||||||
ha.snapname = snapname;
|
ha.snapname = snapname;
|
||||||
ha.tag = tag;
|
ha.tag = tag;
|
||||||
ha.recursive = recursive;
|
ha.recursive = recursive;
|
||||||
|
ha.error = 0;
|
||||||
(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
|
(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
|
||||||
|
|
||||||
if (nvlist_empty(ha.nvl)) {
|
if (nvlist_empty(ha.nvl)) {
|
||||||
fnvlist_free(ha.nvl);
|
fnvlist_free(ha.nvl);
|
||||||
ret = ENOENT;
|
ret = ha.error;
|
||||||
(void) snprintf(errbuf, sizeof (errbuf),
|
(void) snprintf(errbuf, sizeof (errbuf),
|
||||||
dgettext(TEXT_DOMAIN,
|
dgettext(TEXT_DOMAIN,
|
||||||
"cannot release hold from snapshot '%s@%s'"),
|
"cannot release hold from snapshot '%s@%s'"),
|
||||||
zhp->zfs_name, snapname);
|
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);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
* marked for deferred destruction, and will be destroyed when the last hold
|
||||||
* or clone is removed/destroyed.
|
* 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
|
* 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
|
* later destruction if 'defer' is set) or didn't exist to begin with.
|
||||||
* at least one snapshot was destroyed.
|
|
||||||
*
|
*
|
||||||
* Otherwise the return value will be the errno of a (unspecified) snapshot
|
* 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
|
* that failed, no snapshots will be destroyed, and the errlist will have an
|
||||||
@ -350,15 +347,10 @@ lzc_exists(const char *dataset)
|
|||||||
* or imported.
|
* or imported.
|
||||||
*
|
*
|
||||||
* Holds for snapshots which don't exist will be skipped and have an entry
|
* 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
|
* added to errlist, but will not cause an overall failure.
|
||||||
* case that all holds where skipped.
|
|
||||||
*
|
*
|
||||||
* The return value will be ENOENT if none of the snapshots for the requested
|
* The return value will be 0 if all holds, for snapshots that existed,
|
||||||
* holds existed.
|
* were succesfully created.
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* Otherwise the return value will be the errno of a (unspecified) hold that
|
* Otherwise the return value will be the errno of a (unspecified) hold that
|
||||||
* failed and no holds will be created.
|
* 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.
|
* 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
|
* 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
|
* added to errlist, but will not cause an overall failure.
|
||||||
* case that all releases where skipped.
|
|
||||||
*
|
|
||||||
* The return value will be ENOENT if none of the specified holds existed.
|
|
||||||
*
|
*
|
||||||
* The return value will be 0 if the nvl holds was empty or all holds that
|
* 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
|
* Otherwise the return value will be the errno of a (unspecified) hold that
|
||||||
* failed to release and no holds will be released.
|
* failed to release and no holds will be released.
|
||||||
|
@ -129,9 +129,6 @@ dsl_destroy_snapshot_check(void *arg, dmu_tx_t *tx)
|
|||||||
if (pair != NULL)
|
if (pair != NULL)
|
||||||
return (fnvpair_value_int32(pair));
|
return (fnvpair_value_int32(pair));
|
||||||
|
|
||||||
if (nvlist_empty(dsda->dsda_successful_snaps))
|
|
||||||
return (SET_ERROR(ENOENT));
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +127,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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,10 +468,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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user