comparison usr/src/lib/libzfs/common/libzfs_dataset.c @ 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 1a272fe1337b
children 520f3adc5d46
comparison
equal deleted inserted replaced
14059:1a63e2c4c1b9 14060:aeb4e8fef072
19 * CDDL HEADER END 19 * CDDL HEADER END
20 */ 20 */
21 21
22 /* 22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * 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.
25 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved. 25 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
26 * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 26 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
27 * Copyright (c) 2013 Martin Matuska. All rights reserved. 27 * Copyright (c) 2013 Martin Matuska. All rights reserved.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved. 28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
29 */ 29 */
4071 struct holdarg { 4071 struct holdarg {
4072 nvlist_t *nvl; 4072 nvlist_t *nvl;
4073 const char *snapname; 4073 const char *snapname;
4074 const char *tag; 4074 const char *tag;
4075 boolean_t recursive; 4075 boolean_t recursive;
4076 int error;
4076 }; 4077 };
4077 4078
4078 static int 4079 static int
4079 zfs_hold_one(zfs_handle_t *zhp, void *arg) 4080 zfs_hold_one(zfs_handle_t *zhp, void *arg)
4080 { 4081 {
4198 zfs_release_one(zfs_handle_t *zhp, void *arg) 4199 zfs_release_one(zfs_handle_t *zhp, void *arg)
4199 { 4200 {
4200 struct holdarg *ha = arg; 4201 struct holdarg *ha = arg;
4201 char name[ZFS_MAXNAMELEN]; 4202 char name[ZFS_MAXNAMELEN];
4202 int rv = 0; 4203 int rv = 0;
4204 nvlist_t *existing_holds;
4203 4205
4204 (void) snprintf(name, sizeof (name), 4206 (void) snprintf(name, sizeof (name),
4205 "%s@%s", zhp->zfs_name, ha->snapname); 4207 "%s@%s", zhp->zfs_name, ha->snapname);
4206 4208
4207 if (lzc_exists(name)) { 4209 if (lzc_get_holds(name, &existing_holds) != 0) {
4208 nvlist_t *holds = fnvlist_alloc(); 4210 ha->error = ENOENT;
4209 fnvlist_add_boolean(holds, ha->tag); 4211 } else if (!nvlist_exists(existing_holds, ha->tag)) {
4210 fnvlist_add_nvlist(ha->nvl, name, holds); 4212 ha->error = ESRCH;
4211 fnvlist_free(holds); 4213 } else {
4214 nvlist_t *torelease = fnvlist_alloc();
4215 fnvlist_add_boolean(torelease, ha->tag);
4216 fnvlist_add_nvlist(ha->nvl, name, torelease);
4217 fnvlist_free(torelease);
4212 } 4218 }
4213 4219
4214 if (ha->recursive) 4220 if (ha->recursive)
4215 rv = zfs_iter_filesystems(zhp, zfs_release_one, ha); 4221 rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
4216 zfs_close(zhp); 4222 zfs_close(zhp);
4230 4236
4231 ha.nvl = fnvlist_alloc(); 4237 ha.nvl = fnvlist_alloc();
4232 ha.snapname = snapname; 4238 ha.snapname = snapname;
4233 ha.tag = tag; 4239 ha.tag = tag;
4234 ha.recursive = recursive; 4240 ha.recursive = recursive;
4241 ha.error = 0;
4235 (void) zfs_release_one(zfs_handle_dup(zhp), &ha); 4242 (void) zfs_release_one(zfs_handle_dup(zhp), &ha);
4236 4243
4237 if (nvlist_empty(ha.nvl)) { 4244 if (nvlist_empty(ha.nvl)) {
4238 fnvlist_free(ha.nvl); 4245 fnvlist_free(ha.nvl);
4239 ret = ENOENT; 4246 ret = ha.error;
4240 (void) snprintf(errbuf, sizeof (errbuf), 4247 (void) snprintf(errbuf, sizeof (errbuf),
4241 dgettext(TEXT_DOMAIN, 4248 dgettext(TEXT_DOMAIN,
4242 "cannot release hold from snapshot '%s@%s'"), 4249 "cannot release hold from snapshot '%s@%s'"),
4243 zhp->zfs_name, snapname); 4250 zhp->zfs_name, snapname);
4244 (void) zfs_standard_error(hdl, ret, errbuf); 4251 if (ret == ESRCH) {
4252 (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4253 } else {
4254 (void) zfs_standard_error(hdl, ret, errbuf);
4255 }
4245 return (ret); 4256 return (ret);
4246 } 4257 }
4247 4258
4248 ret = lzc_release(ha.nvl, &errors); 4259 ret = lzc_release(ha.nvl, &errors);
4249 fnvlist_free(ha.nvl); 4260 fnvlist_free(ha.nvl);