Skip to content

Commit 1a07775

Browse files
ahrensbehlendorf
authored andcommitted
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@bb6e707 Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775
1 parent 34ffbed commit 1a07775

File tree

4 files changed

+25
-36
lines changed

4 files changed

+25
-36
lines changed

lib/libzfs/libzfs_dataset.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
/*
2323
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24-
* Copyright (c) 2012 by Delphix. All rights reserved.
24+
* Copyright (c) 2013 by Delphix. All rights reserved.
2525
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
2626
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
2727
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
@@ -4412,6 +4412,7 @@ struct holdarg {
44124412
const char *snapname;
44134413
const char *tag;
44144414
boolean_t recursive;
4415+
int error;
44154416
};
44164417

44174418
static int
@@ -4539,15 +4540,20 @@ zfs_release_one(zfs_handle_t *zhp, void *arg)
45394540
struct holdarg *ha = arg;
45404541
char name[ZFS_MAXNAMELEN];
45414542
int rv = 0;
4543+
nvlist_t *existing_holds;
45424544

45434545
(void) snprintf(name, sizeof (name),
45444546
"%s@%s", zhp->zfs_name, ha->snapname);
45454547

4546-
if (lzc_exists(name)) {
4547-
nvlist_t *holds = fnvlist_alloc();
4548-
fnvlist_add_boolean(holds, ha->tag);
4549-
fnvlist_add_nvlist(ha->nvl, name, holds);
4550-
fnvlist_free(holds);
4548+
if (lzc_get_holds(name, &existing_holds) != 0) {
4549+
ha->error = ENOENT;
4550+
} else if (!nvlist_exists(existing_holds, ha->tag)) {
4551+
ha->error = ESRCH;
4552+
} else {
4553+
nvlist_t *torelease = fnvlist_alloc();
4554+
fnvlist_add_boolean(torelease, ha->tag);
4555+
fnvlist_add_nvlist(ha->nvl, name, torelease);
4556+
fnvlist_free(torelease);
45514557
}
45524558

45534559
if (ha->recursive)
@@ -4571,16 +4577,21 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
45714577
ha.snapname = snapname;
45724578
ha.tag = tag;
45734579
ha.recursive = recursive;
4580+
ha.error = 0;
45744581
(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
45754582

45764583
if (nvlist_empty(ha.nvl)) {
45774584
fnvlist_free(ha.nvl);
4578-
ret = ENOENT;
4585+
ret = ha.error;
45794586
(void) snprintf(errbuf, sizeof (errbuf),
45804587
dgettext(TEXT_DOMAIN,
45814588
"cannot release hold from snapshot '%s@%s'"),
45824589
zhp->zfs_name, snapname);
4583-
(void) zfs_standard_error(hdl, ret, errbuf);
4590+
if (ret == ESRCH) {
4591+
(void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4592+
} else {
4593+
(void) zfs_standard_error(hdl, ret, errbuf);
4594+
}
45844595
return (ret);
45854596
}
45864597

lib/libzfs_core/libzfs_core.c

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,8 @@ lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
255255
* marked for deferred destruction, and will be destroyed when the last hold
256256
* or clone is removed/destroyed.
257257
*
258-
* The return value will be ENOENT if none of the snapshots existed.
259-
*
260258
* The return value will be 0 if all snapshots were destroyed (or marked for
261-
* later destruction if 'defer' is set) or didn't exist to begin with and
262-
* at least one snapshot was destroyed.
259+
* later destruction if 'defer' is set) or didn't exist to begin with.
263260
*
264261
* Otherwise the return value will be the errno of a (unspecified) snapshot
265262
* that failed, no snapshots will be destroyed, and the errlist will have an
@@ -350,15 +347,10 @@ lzc_exists(const char *dataset)
350347
* or imported.
351348
*
352349
* Holds for snapshots which don't exist will be skipped and have an entry
353-
* added to errlist, but will not cause an overall failure, except in the
354-
* case that all holds where skipped.
355-
*
356-
* The return value will be ENOENT if none of the snapshots for the requested
357-
* holds existed.
350+
* added to errlist, but will not cause an overall failure.
358351
*
359-
* The return value will be 0 if the nvl holds was empty or all holds, for
360-
* snapshots that existed, were succesfully created and at least one hold
361-
* was created.
352+
* The return value will be 0 if all holds, for snapshots that existed,
353+
* were succesfully created.
362354
*
363355
* Otherwise the return value will be the errno of a (unspecified) hold that
364356
* failed and no holds will be created.
@@ -402,13 +394,10 @@ lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
402394
* The value is a nvlist whose keys are the holds to remove.
403395
*
404396
* Holds which failed to release because they didn't exist will have an entry
405-
* added to errlist, but will not cause an overall failure, except in the
406-
* case that all releases where skipped.
407-
*
408-
* The return value will be ENOENT if none of the specified holds existed.
397+
* added to errlist, but will not cause an overall failure.
409398
*
410399
* The return value will be 0 if the nvl holds was empty or all holds that
411-
* existed, were successfully removed and at least one hold was removed.
400+
* existed, were successfully removed.
412401
*
413402
* Otherwise the return value will be the errno of a (unspecified) hold that
414403
* failed to release and no holds will be released.

module/zfs/dsl_destroy.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,6 @@ dsl_destroy_snapshot_check(void *arg, dmu_tx_t *tx)
129129
if (pair != NULL)
130130
return (fnvpair_value_int32(pair));
131131

132-
if (nvlist_empty(dsda->dsda_successful_snaps))
133-
return (SET_ERROR(ENOENT));
134-
135132
return (0);
136133
}
137134

module/zfs/dsl_userhold.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,6 @@ dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx)
127127
}
128128
}
129129

130-
/* Return ENOENT if no holds would be created. */
131-
if (nvlist_empty(dduha->dduha_chkholds))
132-
return (SET_ERROR(ENOENT));
133-
134130
return (0);
135131
}
136132

@@ -472,10 +468,6 @@ dsl_dataset_user_release_check(void *arg, dmu_tx_t *tx)
472468
}
473469
}
474470

475-
/* Return ENOENT if none of the holds existed. */
476-
if (nvlist_empty(ddura->ddura_chkholds))
477-
return (SET_ERROR(ENOENT));
478-
479471
return (0);
480472
}
481473

0 commit comments

Comments
 (0)