xref: /titanic_52/usr/src/lib/libzfs/common/libzfs_dataset.c (revision 6a3e8e8695d5c7d1d18c6800d676990d7f61a2a4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
25  * Copyright (c) 2012 by Delphix. All rights reserved.
26  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
27  */
28 
29 #include <ctype.h>
30 #include <errno.h>
31 #include <libintl.h>
32 #include <math.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <strings.h>
36 #include <unistd.h>
37 #include <stddef.h>
38 #include <zone.h>
39 #include <fcntl.h>
40 #include <sys/mntent.h>
41 #include <sys/mount.h>
42 #include <priv.h>
43 #include <pwd.h>
44 #include <grp.h>
45 #include <stddef.h>
46 #include <ucred.h>
47 #include <idmap.h>
48 #include <aclutils.h>
49 #include <directory.h>
50 
51 #include <sys/dnode.h>
52 #include <sys/spa.h>
53 #include <sys/zap.h>
54 #include <libzfs.h>
55 
56 #include "zfs_namecheck.h"
57 #include "zfs_prop.h"
58 #include "libzfs_impl.h"
59 #include "zfs_deleg.h"
60 
61 static int userquota_propname_decode(const char *propname, boolean_t zoned,
62     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
63 
64 /*
65  * Given a single type (not a mask of types), return the type in a human
66  * readable form.
67  */
68 const char *
69 zfs_type_to_name(zfs_type_t type)
70 {
71 	switch (type) {
72 	case ZFS_TYPE_FILESYSTEM:
73 		return (dgettext(TEXT_DOMAIN, "filesystem"));
74 	case ZFS_TYPE_SNAPSHOT:
75 		return (dgettext(TEXT_DOMAIN, "snapshot"));
76 	case ZFS_TYPE_VOLUME:
77 		return (dgettext(TEXT_DOMAIN, "volume"));
78 	}
79 
80 	return (NULL);
81 }
82 
83 /*
84  * Given a path and mask of ZFS types, return a string describing this dataset.
85  * This is used when we fail to open a dataset and we cannot get an exact type.
86  * We guess what the type would have been based on the path and the mask of
87  * acceptable types.
88  */
89 static const char *
90 path_to_str(const char *path, int types)
91 {
92 	/*
93 	 * When given a single type, always report the exact type.
94 	 */
95 	if (types == ZFS_TYPE_SNAPSHOT)
96 		return (dgettext(TEXT_DOMAIN, "snapshot"));
97 	if (types == ZFS_TYPE_FILESYSTEM)
98 		return (dgettext(TEXT_DOMAIN, "filesystem"));
99 	if (types == ZFS_TYPE_VOLUME)
100 		return (dgettext(TEXT_DOMAIN, "volume"));
101 
102 	/*
103 	 * The user is requesting more than one type of dataset.  If this is the
104 	 * case, consult the path itself.  If we're looking for a snapshot, and
105 	 * a '@' is found, then report it as "snapshot".  Otherwise, remove the
106 	 * snapshot attribute and try again.
107 	 */
108 	if (types & ZFS_TYPE_SNAPSHOT) {
109 		if (strchr(path, '@') != NULL)
110 			return (dgettext(TEXT_DOMAIN, "snapshot"));
111 		return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
112 	}
113 
114 	/*
115 	 * The user has requested either filesystems or volumes.
116 	 * We have no way of knowing a priori what type this would be, so always
117 	 * report it as "filesystem" or "volume", our two primitive types.
118 	 */
119 	if (types & ZFS_TYPE_FILESYSTEM)
120 		return (dgettext(TEXT_DOMAIN, "filesystem"));
121 
122 	assert(types & ZFS_TYPE_VOLUME);
123 	return (dgettext(TEXT_DOMAIN, "volume"));
124 }
125 
126 /*
127  * Validate a ZFS path.  This is used even before trying to open the dataset, to
128  * provide a more meaningful error message.  We call zfs_error_aux() to
129  * explain exactly why the name was not valid.
130  */
131 int
132 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
133     boolean_t modifying)
134 {
135 	namecheck_err_t why;
136 	char what;
137 
138 	(void) zfs_prop_get_table();
139 	if (dataset_namecheck(path, &why, &what) != 0) {
140 		if (hdl != NULL) {
141 			switch (why) {
142 			case NAME_ERR_TOOLONG:
143 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
144 				    "name is too long"));
145 				break;
146 
147 			case NAME_ERR_LEADING_SLASH:
148 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
149 				    "leading slash in name"));
150 				break;
151 
152 			case NAME_ERR_EMPTY_COMPONENT:
153 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
154 				    "empty component in name"));
155 				break;
156 
157 			case NAME_ERR_TRAILING_SLASH:
158 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
159 				    "trailing slash in name"));
160 				break;
161 
162 			case NAME_ERR_INVALCHAR:
163 				zfs_error_aux(hdl,
164 				    dgettext(TEXT_DOMAIN, "invalid character "
165 				    "'%c' in name"), what);
166 				break;
167 
168 			case NAME_ERR_MULTIPLE_AT:
169 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
170 				    "multiple '@' delimiters in name"));
171 				break;
172 
173 			case NAME_ERR_NOLETTER:
174 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
175 				    "pool doesn't begin with a letter"));
176 				break;
177 
178 			case NAME_ERR_RESERVED:
179 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
180 				    "name is reserved"));
181 				break;
182 
183 			case NAME_ERR_DISKLIKE:
184 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
185 				    "reserved disk name"));
186 				break;
187 			}
188 		}
189 
190 		return (0);
191 	}
192 
193 	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
194 		if (hdl != NULL)
195 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
196 			    "snapshot delimiter '@' in filesystem name"));
197 		return (0);
198 	}
199 
200 	if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
201 		if (hdl != NULL)
202 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
203 			    "missing '@' delimiter in snapshot name"));
204 		return (0);
205 	}
206 
207 	if (modifying && strchr(path, '%') != NULL) {
208 		if (hdl != NULL)
209 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
210 			    "invalid character %c in name"), '%');
211 		return (0);
212 	}
213 
214 	return (-1);
215 }
216 
217 int
218 zfs_name_valid(const char *name, zfs_type_t type)
219 {
220 	if (type == ZFS_TYPE_POOL)
221 		return (zpool_name_valid(NULL, B_FALSE, name));
222 	return (zfs_validate_name(NULL, name, type, B_FALSE));
223 }
224 
225 /*
226  * This function takes the raw DSL properties, and filters out the user-defined
227  * properties into a separate nvlist.
228  */
229 static nvlist_t *
230 process_user_props(zfs_handle_t *zhp, nvlist_t *props)
231 {
232 	libzfs_handle_t *hdl = zhp->zfs_hdl;
233 	nvpair_t *elem;
234 	nvlist_t *propval;
235 	nvlist_t *nvl;
236 
237 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
238 		(void) no_memory(hdl);
239 		return (NULL);
240 	}
241 
242 	elem = NULL;
243 	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
244 		if (!zfs_prop_user(nvpair_name(elem)))
245 			continue;
246 
247 		verify(nvpair_value_nvlist(elem, &propval) == 0);
248 		if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
249 			nvlist_free(nvl);
250 			(void) no_memory(hdl);
251 			return (NULL);
252 		}
253 	}
254 
255 	return (nvl);
256 }
257 
258 static zpool_handle_t *
259 zpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
260 {
261 	libzfs_handle_t *hdl = zhp->zfs_hdl;
262 	zpool_handle_t *zph;
263 
264 	if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
265 		if (hdl->libzfs_pool_handles != NULL)
266 			zph->zpool_next = hdl->libzfs_pool_handles;
267 		hdl->libzfs_pool_handles = zph;
268 	}
269 	return (zph);
270 }
271 
272 static zpool_handle_t *
273 zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
274 {
275 	libzfs_handle_t *hdl = zhp->zfs_hdl;
276 	zpool_handle_t *zph = hdl->libzfs_pool_handles;
277 
278 	while ((zph != NULL) &&
279 	    (strncmp(pool_name, zpool_get_name(zph), len) != 0))
280 		zph = zph->zpool_next;
281 	return (zph);
282 }
283 
284 /*
285  * Returns a handle to the pool that contains the provided dataset.
286  * If a handle to that pool already exists then that handle is returned.
287  * Otherwise, a new handle is created and added to the list of handles.
288  */
289 static zpool_handle_t *
290 zpool_handle(zfs_handle_t *zhp)
291 {
292 	char *pool_name;
293 	int len;
294 	zpool_handle_t *zph;
295 
296 	len = strcspn(zhp->zfs_name, "/@") + 1;
297 	pool_name = zfs_alloc(zhp->zfs_hdl, len);
298 	(void) strlcpy(pool_name, zhp->zfs_name, len);
299 
300 	zph = zpool_find_handle(zhp, pool_name, len);
301 	if (zph == NULL)
302 		zph = zpool_add_handle(zhp, pool_name);
303 
304 	free(pool_name);
305 	return (zph);
306 }
307 
308 void
309 zpool_free_handles(libzfs_handle_t *hdl)
310 {
311 	zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
312 
313 	while (zph != NULL) {
314 		next = zph->zpool_next;
315 		zpool_close(zph);
316 		zph = next;
317 	}
318 	hdl->libzfs_pool_handles = NULL;
319 }
320 
321 /*
322  * Utility function to gather stats (objset and zpl) for the given object.
323  */
324 static int
325 get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc)
326 {
327 	libzfs_handle_t *hdl = zhp->zfs_hdl;
328 
329 	(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
330 
331 	while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) {
332 		if (errno == ENOMEM) {
333 			if (zcmd_expand_dst_nvlist(hdl, zc) != 0) {
334 				return (-1);
335 			}
336 		} else {
337 			return (-1);
338 		}
339 	}
340 	return (0);
341 }
342 
343 /*
344  * Utility function to get the received properties of the given object.
345  */
346 static int
347 get_recvd_props_ioctl(zfs_handle_t *zhp)
348 {
349 	libzfs_handle_t *hdl = zhp->zfs_hdl;
350 	nvlist_t *recvdprops;
351 	zfs_cmd_t zc = { 0 };
352 	int err;
353 
354 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
355 		return (-1);
356 
357 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
358 
359 	while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) {
360 		if (errno == ENOMEM) {
361 			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
362 				return (-1);
363 			}
364 		} else {
365 			zcmd_free_nvlists(&zc);
366 			return (-1);
367 		}
368 	}
369 
370 	err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops);
371 	zcmd_free_nvlists(&zc);
372 	if (err != 0)
373 		return (-1);
374 
375 	nvlist_free(zhp->zfs_recvd_props);
376 	zhp->zfs_recvd_props = recvdprops;
377 
378 	return (0);
379 }
380 
381 static int
382 put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc)
383 {
384 	nvlist_t *allprops, *userprops;
385 
386 	zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */
387 
388 	if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
389 		return (-1);
390 	}
391 
392 	/*
393 	 * XXX Why do we store the user props separately, in addition to
394 	 * storing them in zfs_props?
395 	 */
396 	if ((userprops = process_user_props(zhp, allprops)) == NULL) {
397 		nvlist_free(allprops);
398 		return (-1);
399 	}
400 
401 	nvlist_free(zhp->zfs_props);
402 	nvlist_free(zhp->zfs_user_props);
403 
404 	zhp->zfs_props = allprops;
405 	zhp->zfs_user_props = userprops;
406 
407 	return (0);
408 }
409 
410 static int
411 get_stats(zfs_handle_t *zhp)
412 {
413 	int rc = 0;
414 	zfs_cmd_t zc = { 0 };
415 
416 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
417 		return (-1);
418 	if (get_stats_ioctl(zhp, &zc) != 0)
419 		rc = -1;
420 	else if (put_stats_zhdl(zhp, &zc) != 0)
421 		rc = -1;
422 	zcmd_free_nvlists(&zc);
423 	return (rc);
424 }
425 
426 /*
427  * Refresh the properties currently stored in the handle.
428  */
429 void
430 zfs_refresh_properties(zfs_handle_t *zhp)
431 {
432 	(void) get_stats(zhp);
433 }
434 
435 /*
436  * Makes a handle from the given dataset name.  Used by zfs_open() and
437  * zfs_iter_* to create child handles on the fly.
438  */
439 static int
440 make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
441 {
442 	if (put_stats_zhdl(zhp, zc) != 0)
443 		return (-1);
444 
445 	/*
446 	 * We've managed to open the dataset and gather statistics.  Determine
447 	 * the high-level type.
448 	 */
449 	if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
450 		zhp->zfs_head_type = ZFS_TYPE_VOLUME;
451 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
452 		zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
453 	else
454 		abort();
455 
456 	if (zhp->zfs_dmustats.dds_is_snapshot)
457 		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
458 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
459 		zhp->zfs_type = ZFS_TYPE_VOLUME;
460 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
461 		zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
462 	else
463 		abort();	/* we should never see any other types */
464 
465 	if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL)
466 		return (-1);
467 
468 	return (0);
469 }
470 
471 zfs_handle_t *
472 make_dataset_handle(libzfs_handle_t *hdl, const char *path)
473 {
474 	zfs_cmd_t zc = { 0 };
475 
476 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
477 
478 	if (zhp == NULL)
479 		return (NULL);
480 
481 	zhp->zfs_hdl = hdl;
482 	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
483 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) {
484 		free(zhp);
485 		return (NULL);
486 	}
487 	if (get_stats_ioctl(zhp, &zc) == -1) {
488 		zcmd_free_nvlists(&zc);
489 		free(zhp);
490 		return (NULL);
491 	}
492 	if (make_dataset_handle_common(zhp, &zc) == -1) {
493 		free(zhp);
494 		zhp = NULL;
495 	}
496 	zcmd_free_nvlists(&zc);
497 	return (zhp);
498 }
499 
500 zfs_handle_t *
501 make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
502 {
503 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
504 
505 	if (zhp == NULL)
506 		return (NULL);
507 
508 	zhp->zfs_hdl = hdl;
509 	(void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
510 	if (make_dataset_handle_common(zhp, zc) == -1) {
511 		free(zhp);
512 		return (NULL);
513 	}
514 	return (zhp);
515 }
516 
517 zfs_handle_t *
518 zfs_handle_dup(zfs_handle_t *zhp_orig)
519 {
520 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
521 
522 	if (zhp == NULL)
523 		return (NULL);
524 
525 	zhp->zfs_hdl = zhp_orig->zfs_hdl;
526 	zhp->zpool_hdl = zhp_orig->zpool_hdl;
527 	(void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name,
528 	    sizeof (zhp->zfs_name));
529 	zhp->zfs_type = zhp_orig->zfs_type;
530 	zhp->zfs_head_type = zhp_orig->zfs_head_type;
531 	zhp->zfs_dmustats = zhp_orig->zfs_dmustats;
532 	if (zhp_orig->zfs_props != NULL) {
533 		if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
534 			(void) no_memory(zhp->zfs_hdl);
535 			zfs_close(zhp);
536 			return (NULL);
537 		}
538 	}
539 	if (zhp_orig->zfs_user_props != NULL) {
540 		if (nvlist_dup(zhp_orig->zfs_user_props,
541 		    &zhp->zfs_user_props, 0) != 0) {
542 			(void) no_memory(zhp->zfs_hdl);
543 			zfs_close(zhp);
544 			return (NULL);
545 		}
546 	}
547 	if (zhp_orig->zfs_recvd_props != NULL) {
548 		if (nvlist_dup(zhp_orig->zfs_recvd_props,
549 		    &zhp->zfs_recvd_props, 0)) {
550 			(void) no_memory(zhp->zfs_hdl);
551 			zfs_close(zhp);
552 			return (NULL);
553 		}
554 	}
555 	zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck;
556 	if (zhp_orig->zfs_mntopts != NULL) {
557 		zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl,
558 		    zhp_orig->zfs_mntopts);
559 	}
560 	zhp->zfs_props_table = zhp_orig->zfs_props_table;
561 	return (zhp);
562 }
563 
564 /*
565  * Opens the given snapshot, filesystem, or volume.   The 'types'
566  * argument is a mask of acceptable types.  The function will print an
567  * appropriate error message and return NULL if it can't be opened.
568  */
569 zfs_handle_t *
570 zfs_open(libzfs_handle_t *hdl, const char *path, int types)
571 {
572 	zfs_handle_t *zhp;
573 	char errbuf[1024];
574 
575 	(void) snprintf(errbuf, sizeof (errbuf),
576 	    dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
577 
578 	/*
579 	 * Validate the name before we even try to open it.
580 	 */
581 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
582 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
583 		    "invalid dataset name"));
584 		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
585 		return (NULL);
586 	}
587 
588 	/*
589 	 * Try to get stats for the dataset, which will tell us if it exists.
590 	 */
591 	errno = 0;
592 	if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
593 		(void) zfs_standard_error(hdl, errno, errbuf);
594 		return (NULL);
595 	}
596 
597 	if (!(types & zhp->zfs_type)) {
598 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
599 		zfs_close(zhp);
600 		return (NULL);
601 	}
602 
603 	return (zhp);
604 }
605 
606 /*
607  * Release a ZFS handle.  Nothing to do but free the associated memory.
608  */
609 void
610 zfs_close(zfs_handle_t *zhp)
611 {
612 	if (zhp->zfs_mntopts)
613 		free(zhp->zfs_mntopts);
614 	nvlist_free(zhp->zfs_props);
615 	nvlist_free(zhp->zfs_user_props);
616 	nvlist_free(zhp->zfs_recvd_props);
617 	free(zhp);
618 }
619 
620 typedef struct mnttab_node {
621 	struct mnttab mtn_mt;
622 	avl_node_t mtn_node;
623 } mnttab_node_t;
624 
625 static int
626 libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
627 {
628 	const mnttab_node_t *mtn1 = arg1;
629 	const mnttab_node_t *mtn2 = arg2;
630 	int rv;
631 
632 	rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
633 
634 	if (rv == 0)
635 		return (0);
636 	return (rv > 0 ? 1 : -1);
637 }
638 
639 void
640 libzfs_mnttab_init(libzfs_handle_t *hdl)
641 {
642 	assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
643 	avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
644 	    sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
645 }
646 
647 void
648 libzfs_mnttab_update(libzfs_handle_t *hdl)
649 {
650 	struct mnttab entry;
651 
652 	rewind(hdl->libzfs_mnttab);
653 	while (getmntent(hdl->libzfs_mnttab, &entry) == 0) {
654 		mnttab_node_t *mtn;
655 
656 		if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
657 			continue;
658 		mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
659 		mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
660 		mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
661 		mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
662 		mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
663 		avl_add(&hdl->libzfs_mnttab_cache, mtn);
664 	}
665 }
666 
667 void
668 libzfs_mnttab_fini(libzfs_handle_t *hdl)
669 {
670 	void *cookie = NULL;
671 	mnttab_node_t *mtn;
672 
673 	while (mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) {
674 		free(mtn->mtn_mt.mnt_special);
675 		free(mtn->mtn_mt.mnt_mountp);
676 		free(mtn->mtn_mt.mnt_fstype);
677 		free(mtn->mtn_mt.mnt_mntopts);
678 		free(mtn);
679 	}
680 	avl_destroy(&hdl->libzfs_mnttab_cache);
681 }
682 
683 void
684 libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
685 {
686 	hdl->libzfs_mnttab_enable = enable;
687 }
688 
689 int
690 libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
691     struct mnttab *entry)
692 {
693 	mnttab_node_t find;
694 	mnttab_node_t *mtn;
695 
696 	if (!hdl->libzfs_mnttab_enable) {
697 		struct mnttab srch = { 0 };
698 
699 		if (avl_numnodes(&hdl->libzfs_mnttab_cache))
700 			libzfs_mnttab_fini(hdl);
701 		rewind(hdl->libzfs_mnttab);
702 		srch.mnt_special = (char *)fsname;
703 		srch.mnt_fstype = MNTTYPE_ZFS;
704 		if (getmntany(hdl->libzfs_mnttab, entry, &srch) == 0)
705 			return (0);
706 		else
707 			return (ENOENT);
708 	}
709 
710 	if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
711 		libzfs_mnttab_update(hdl);
712 
713 	find.mtn_mt.mnt_special = (char *)fsname;
714 	mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
715 	if (mtn) {
716 		*entry = mtn->mtn_mt;
717 		return (0);
718 	}
719 	return (ENOENT);
720 }
721 
722 void
723 libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
724     const char *mountp, const char *mntopts)
725 {
726 	mnttab_node_t *mtn;
727 
728 	if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
729 		return;
730 	mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
731 	mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
732 	mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
733 	mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
734 	mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
735 	avl_add(&hdl->libzfs_mnttab_cache, mtn);
736 }
737 
738 void
739 libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
740 {
741 	mnttab_node_t find;
742 	mnttab_node_t *ret;
743 
744 	find.mtn_mt.mnt_special = (char *)fsname;
745 	if (ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) {
746 		avl_remove(&hdl->libzfs_mnttab_cache, ret);
747 		free(ret->mtn_mt.mnt_special);
748 		free(ret->mtn_mt.mnt_mountp);
749 		free(ret->mtn_mt.mnt_fstype);
750 		free(ret->mtn_mt.mnt_mntopts);
751 		free(ret);
752 	}
753 }
754 
755 int
756 zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
757 {
758 	zpool_handle_t *zpool_handle = zhp->zpool_hdl;
759 
760 	if (zpool_handle == NULL)
761 		return (-1);
762 
763 	*spa_version = zpool_get_prop_int(zpool_handle,
764 	    ZPOOL_PROP_VERSION, NULL);
765 	return (0);
766 }
767 
768 /*
769  * The choice of reservation property depends on the SPA version.
770  */
771 static int
772 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
773 {
774 	int spa_version;
775 
776 	if (zfs_spa_version(zhp, &spa_version) < 0)
777 		return (-1);
778 
779 	if (spa_version >= SPA_VERSION_REFRESERVATION)
780 		*resv_prop = ZFS_PROP_REFRESERVATION;
781 	else
782 		*resv_prop = ZFS_PROP_RESERVATION;
783 
784 	return (0);
785 }
786 
787 /*
788  * Given an nvlist of properties to set, validates that they are correct, and
789  * parses any numeric properties (index, boolean, etc) if they are specified as
790  * strings.
791  */
792 nvlist_t *
793 zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
794     uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
795 {
796 	nvpair_t *elem;
797 	uint64_t intval;
798 	char *strval;
799 	zfs_prop_t prop;
800 	nvlist_t *ret;
801 	int chosen_normal = -1;
802 	int chosen_utf = -1;
803 
804 	if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
805 		(void) no_memory(hdl);
806 		return (NULL);
807 	}
808 
809 	/*
810 	 * Make sure this property is valid and applies to this type.
811 	 */
812 
813 	elem = NULL;
814 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
815 		const char *propname = nvpair_name(elem);
816 
817 		prop = zfs_name_to_prop(propname);
818 		if (prop == ZPROP_INVAL && zfs_prop_user(propname)) {
819 			/*
820 			 * This is a user property: make sure it's a
821 			 * string, and that it's less than ZAP_MAXNAMELEN.
822 			 */
823 			if (nvpair_type(elem) != DATA_TYPE_STRING) {
824 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
825 				    "'%s' must be a string"), propname);
826 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
827 				goto error;
828 			}
829 
830 			if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
831 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
832 				    "property name '%s' is too long"),
833 				    propname);
834 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
835 				goto error;
836 			}
837 
838 			(void) nvpair_value_string(elem, &strval);
839 			if (nvlist_add_string(ret, propname, strval) != 0) {
840 				(void) no_memory(hdl);
841 				goto error;
842 			}
843 			continue;
844 		}
845 
846 		/*
847 		 * Currently, only user properties can be modified on
848 		 * snapshots.
849 		 */
850 		if (type == ZFS_TYPE_SNAPSHOT) {
851 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
852 			    "this property can not be modified for snapshots"));
853 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
854 			goto error;
855 		}
856 
857 		if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) {
858 			zfs_userquota_prop_t uqtype;
859 			char newpropname[128];
860 			char domain[128];
861 			uint64_t rid;
862 			uint64_t valary[3];
863 
864 			if (userquota_propname_decode(propname, zoned,
865 			    &uqtype, domain, sizeof (domain), &rid) != 0) {
866 				zfs_error_aux(hdl,
867 				    dgettext(TEXT_DOMAIN,
868 				    "'%s' has an invalid user/group name"),
869 				    propname);
870 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
871 				goto error;
872 			}
873 
874 			if (uqtype != ZFS_PROP_USERQUOTA &&
875 			    uqtype != ZFS_PROP_GROUPQUOTA) {
876 				zfs_error_aux(hdl,
877 				    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
878 				    propname);
879 				(void) zfs_error(hdl, EZFS_PROPREADONLY,
880 				    errbuf);
881 				goto error;
882 			}
883 
884 			if (nvpair_type(elem) == DATA_TYPE_STRING) {
885 				(void) nvpair_value_string(elem, &strval);
886 				if (strcmp(strval, "none") == 0) {
887 					intval = 0;
888 				} else if (zfs_nicestrtonum(hdl,
889 				    strval, &intval) != 0) {
890 					(void) zfs_error(hdl,
891 					    EZFS_BADPROP, errbuf);
892 					goto error;
893 				}
894 			} else if (nvpair_type(elem) ==
895 			    DATA_TYPE_UINT64) {
896 				(void) nvpair_value_uint64(elem, &intval);
897 				if (intval == 0) {
898 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
899 					    "use 'none' to disable "
900 					    "userquota/groupquota"));
901 					goto error;
902 				}
903 			} else {
904 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
905 				    "'%s' must be a number"), propname);
906 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
907 				goto error;
908 			}
909 
910 			/*
911 			 * Encode the prop name as
912 			 * userquota@<hex-rid>-domain, to make it easy
913 			 * for the kernel to decode.
914 			 */
915 			(void) snprintf(newpropname, sizeof (newpropname),
916 			    "%s%llx-%s", zfs_userquota_prop_prefixes[uqtype],
917 			    (longlong_t)rid, domain);
918 			valary[0] = uqtype;
919 			valary[1] = rid;
920 			valary[2] = intval;
921 			if (nvlist_add_uint64_array(ret, newpropname,
922 			    valary, 3) != 0) {
923 				(void) no_memory(hdl);
924 				goto error;
925 			}
926 			continue;
927 		} else if (prop == ZPROP_INVAL && zfs_prop_written(propname)) {
928 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
929 			    "'%s' is readonly"),
930 			    propname);
931 			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
932 			goto error;
933 		}
934 
935 		if (prop == ZPROP_INVAL) {
936 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
937 			    "invalid property '%s'"), propname);
938 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
939 			goto error;
940 		}
941 
942 		if (!zfs_prop_valid_for_type(prop, type)) {
943 			zfs_error_aux(hdl,
944 			    dgettext(TEXT_DOMAIN, "'%s' does not "
945 			    "apply to datasets of this type"), propname);
946 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
947 			goto error;
948 		}
949 
950 		if (zfs_prop_readonly(prop) &&
951 		    (!zfs_prop_setonce(prop) || zhp != NULL)) {
952 			zfs_error_aux(hdl,
953 			    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
954 			    propname);
955 			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
956 			goto error;
957 		}
958 
959 		if (zprop_parse_value(hdl, elem, prop, type, ret,
960 		    &strval, &intval, errbuf) != 0)
961 			goto error;
962 
963 		/*
964 		 * Perform some additional checks for specific properties.
965 		 */
966 		switch (prop) {
967 		case ZFS_PROP_VERSION:
968 		{
969 			int version;
970 
971 			if (zhp == NULL)
972 				break;
973 			version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
974 			if (intval < version) {
975 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
976 				    "Can not downgrade; already at version %u"),
977 				    version);
978 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
979 				goto error;
980 			}
981 			break;
982 		}
983 
984 		case ZFS_PROP_RECORDSIZE:
985 		case ZFS_PROP_VOLBLOCKSIZE:
986 			/* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
987 			if (intval < SPA_MINBLOCKSIZE ||
988 			    intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) {
989 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
990 				    "'%s' must be power of 2 from %u "
991 				    "to %uk"), propname,
992 				    (uint_t)SPA_MINBLOCKSIZE,
993 				    (uint_t)SPA_MAXBLOCKSIZE >> 10);
994 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
995 				goto error;
996 			}
997 			break;
998 
999 		case ZFS_PROP_MLSLABEL:
1000 		{
1001 			/*
1002 			 * Verify the mlslabel string and convert to
1003 			 * internal hex label string.
1004 			 */
1005 
1006 			m_label_t *new_sl;
1007 			char *hex = NULL;	/* internal label string */
1008 
1009 			/* Default value is already OK. */
1010 			if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
1011 				break;
1012 
1013 			/* Verify the label can be converted to binary form */
1014 			if (((new_sl = m_label_alloc(MAC_LABEL)) == NULL) ||
1015 			    (str_to_label(strval, &new_sl, MAC_LABEL,
1016 			    L_NO_CORRECTION, NULL) == -1)) {
1017 				goto badlabel;
1018 			}
1019 
1020 			/* Now translate to hex internal label string */
1021 			if (label_to_str(new_sl, &hex, M_INTERNAL,
1022 			    DEF_NAMES) != 0) {
1023 				if (hex)
1024 					free(hex);
1025 				goto badlabel;
1026 			}
1027 			m_label_free(new_sl);
1028 
1029 			/* If string is already in internal form, we're done. */
1030 			if (strcmp(strval, hex) == 0) {
1031 				free(hex);
1032 				break;
1033 			}
1034 
1035 			/* Replace the label string with the internal form. */
1036 			(void) nvlist_remove(ret, zfs_prop_to_name(prop),
1037 			    DATA_TYPE_STRING);
1038 			verify(nvlist_add_string(ret, zfs_prop_to_name(prop),
1039 			    hex) == 0);
1040 			free(hex);
1041 
1042 			break;
1043 
1044 badlabel:
1045 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1046 			    "invalid mlslabel '%s'"), strval);
1047 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1048 			m_label_free(new_sl);	/* OK if null */
1049 			goto error;
1050 
1051 		}
1052 
1053 		case ZFS_PROP_MOUNTPOINT:
1054 		{
1055 			namecheck_err_t why;
1056 
1057 			if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
1058 			    strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
1059 				break;
1060 
1061 			if (mountpoint_namecheck(strval, &why)) {
1062 				switch (why) {
1063 				case NAME_ERR_LEADING_SLASH:
1064 					zfs_error_aux(hdl,
1065 					    dgettext(TEXT_DOMAIN,
1066 					    "'%s' must be an absolute path, "
1067 					    "'none', or 'legacy'"), propname);
1068 					break;
1069 				case NAME_ERR_TOOLONG:
1070 					zfs_error_aux(hdl,
1071 					    dgettext(TEXT_DOMAIN,
1072 					    "component of '%s' is too long"),
1073 					    propname);
1074 					break;
1075 				}
1076 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1077 				goto error;
1078 			}
1079 		}
1080 
1081 			/*FALLTHRU*/
1082 
1083 		case ZFS_PROP_SHARESMB:
1084 		case ZFS_PROP_SHARENFS:
1085 			/*
1086 			 * For the mountpoint and sharenfs or sharesmb
1087 			 * properties, check if it can be set in a
1088 			 * global/non-global zone based on
1089 			 * the zoned property value:
1090 			 *
1091 			 *		global zone	    non-global zone
1092 			 * --------------------------------------------------
1093 			 * zoned=on	mountpoint (no)	    mountpoint (yes)
1094 			 *		sharenfs (no)	    sharenfs (no)
1095 			 *		sharesmb (no)	    sharesmb (no)
1096 			 *
1097 			 * zoned=off	mountpoint (yes)	N/A
1098 			 *		sharenfs (yes)
1099 			 *		sharesmb (yes)
1100 			 */
1101 			if (zoned) {
1102 				if (getzoneid() == GLOBAL_ZONEID) {
1103 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1104 					    "'%s' cannot be set on "
1105 					    "dataset in a non-global zone"),
1106 					    propname);
1107 					(void) zfs_error(hdl, EZFS_ZONED,
1108 					    errbuf);
1109 					goto error;
1110 				} else if (prop == ZFS_PROP_SHARENFS ||
1111 				    prop == ZFS_PROP_SHARESMB) {
1112 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1113 					    "'%s' cannot be set in "
1114 					    "a non-global zone"), propname);
1115 					(void) zfs_error(hdl, EZFS_ZONED,
1116 					    errbuf);
1117 					goto error;
1118 				}
1119 			} else if (getzoneid() != GLOBAL_ZONEID) {
1120 				/*
1121 				 * If zoned property is 'off', this must be in
1122 				 * a global zone. If not, something is wrong.
1123 				 */
1124 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1125 				    "'%s' cannot be set while dataset "
1126 				    "'zoned' property is set"), propname);
1127 				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
1128 				goto error;
1129 			}
1130 
1131 			/*
1132 			 * At this point, it is legitimate to set the
1133 			 * property. Now we want to make sure that the
1134 			 * property value is valid if it is sharenfs.
1135 			 */
1136 			if ((prop == ZFS_PROP_SHARENFS ||
1137 			    prop == ZFS_PROP_SHARESMB) &&
1138 			    strcmp(strval, "on") != 0 &&
1139 			    strcmp(strval, "off") != 0) {
1140 				zfs_share_proto_t proto;
1141 
1142 				if (prop == ZFS_PROP_SHARESMB)
1143 					proto = PROTO_SMB;
1144 				else
1145 					proto = PROTO_NFS;
1146 
1147 				/*
1148 				 * Must be an valid sharing protocol
1149 				 * option string so init the libshare
1150 				 * in order to enable the parser and
1151 				 * then parse the options. We use the
1152 				 * control API since we don't care about
1153 				 * the current configuration and don't
1154 				 * want the overhead of loading it
1155 				 * until we actually do something.
1156 				 */
1157 
1158 				if (zfs_init_libshare(hdl,
1159 				    SA_INIT_CONTROL_API) != SA_OK) {
1160 					/*
1161 					 * An error occurred so we can't do
1162 					 * anything
1163 					 */
1164 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1165 					    "'%s' cannot be set: problem "
1166 					    "in share initialization"),
1167 					    propname);
1168 					(void) zfs_error(hdl, EZFS_BADPROP,
1169 					    errbuf);
1170 					goto error;
1171 				}
1172 
1173 				if (zfs_parse_options(strval, proto) != SA_OK) {
1174 					/*
1175 					 * There was an error in parsing so
1176 					 * deal with it by issuing an error
1177 					 * message and leaving after
1178 					 * uninitializing the the libshare
1179 					 * interface.
1180 					 */
1181 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1182 					    "'%s' cannot be set to invalid "
1183 					    "options"), propname);
1184 					(void) zfs_error(hdl, EZFS_BADPROP,
1185 					    errbuf);
1186 					zfs_uninit_libshare(hdl);
1187 					goto error;
1188 				}
1189 				zfs_uninit_libshare(hdl);
1190 			}
1191 
1192 			break;
1193 		case ZFS_PROP_UTF8ONLY:
1194 			chosen_utf = (int)intval;
1195 			break;
1196 		case ZFS_PROP_NORMALIZE:
1197 			chosen_normal = (int)intval;
1198 			break;
1199 		}
1200 
1201 		/*
1202 		 * For changes to existing volumes, we have some additional
1203 		 * checks to enforce.
1204 		 */
1205 		if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1206 			uint64_t volsize = zfs_prop_get_int(zhp,
1207 			    ZFS_PROP_VOLSIZE);
1208 			uint64_t blocksize = zfs_prop_get_int(zhp,
1209 			    ZFS_PROP_VOLBLOCKSIZE);
1210 			char buf[64];
1211 
1212 			switch (prop) {
1213 			case ZFS_PROP_RESERVATION:
1214 			case ZFS_PROP_REFRESERVATION:
1215 				if (intval > volsize) {
1216 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1217 					    "'%s' is greater than current "
1218 					    "volume size"), propname);
1219 					(void) zfs_error(hdl, EZFS_BADPROP,
1220 					    errbuf);
1221 					goto error;
1222 				}
1223 				break;
1224 
1225 			case ZFS_PROP_VOLSIZE:
1226 				if (intval % blocksize != 0) {
1227 					zfs_nicenum(blocksize, buf,
1228 					    sizeof (buf));
1229 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1230 					    "'%s' must be a multiple of "
1231 					    "volume block size (%s)"),
1232 					    propname, buf);
1233 					(void) zfs_error(hdl, EZFS_BADPROP,
1234 					    errbuf);
1235 					goto error;
1236 				}
1237 
1238 				if (intval == 0) {
1239 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1240 					    "'%s' cannot be zero"),
1241 					    propname);
1242 					(void) zfs_error(hdl, EZFS_BADPROP,
1243 					    errbuf);
1244 					goto error;
1245 				}
1246 				break;
1247 			}
1248 		}
1249 	}
1250 
1251 	/*
1252 	 * If normalization was chosen, but no UTF8 choice was made,
1253 	 * enforce rejection of non-UTF8 names.
1254 	 *
1255 	 * If normalization was chosen, but rejecting non-UTF8 names
1256 	 * was explicitly not chosen, it is an error.
1257 	 */
1258 	if (chosen_normal > 0 && chosen_utf < 0) {
1259 		if (nvlist_add_uint64(ret,
1260 		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
1261 			(void) no_memory(hdl);
1262 			goto error;
1263 		}
1264 	} else if (chosen_normal > 0 && chosen_utf == 0) {
1265 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1266 		    "'%s' must be set 'on' if normalization chosen"),
1267 		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
1268 		(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1269 		goto error;
1270 	}
1271 	return (ret);
1272 
1273 error:
1274 	nvlist_free(ret);
1275 	return (NULL);
1276 }
1277 
1278 int
1279 zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1280 {
1281 	uint64_t old_volsize;
1282 	uint64_t new_volsize;
1283 	uint64_t old_reservation;
1284 	uint64_t new_reservation;
1285 	zfs_prop_t resv_prop;
1286 
1287 	/*
1288 	 * If this is an existing volume, and someone is setting the volsize,
1289 	 * make sure that it matches the reservation, or add it if necessary.
1290 	 */
1291 	old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1292 	if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
1293 		return (-1);
1294 	old_reservation = zfs_prop_get_int(zhp, resv_prop);
1295 	if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) !=
1296 	    old_reservation) || nvlist_lookup_uint64(nvl,
1297 	    zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) {
1298 		return (0);
1299 	}
1300 	if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1301 	    &new_volsize) != 0)
1302 		return (-1);
1303 	new_reservation = zvol_volsize_to_reservation(new_volsize,
1304 	    zhp->zfs_props);
1305 	if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
1306 	    new_reservation) != 0) {
1307 		(void) no_memory(zhp->zfs_hdl);
1308 		return (-1);
1309 	}
1310 	return (1);
1311 }
1312 
1313 void
1314 zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
1315     char *errbuf)
1316 {
1317 	switch (err) {
1318 
1319 	case ENOSPC:
1320 		/*
1321 		 * For quotas and reservations, ENOSPC indicates
1322 		 * something different; setting a quota or reservation
1323 		 * doesn't use any disk space.
1324 		 */
1325 		switch (prop) {
1326 		case ZFS_PROP_QUOTA:
1327 		case ZFS_PROP_REFQUOTA:
1328 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1329 			    "size is less than current used or "
1330 			    "reserved space"));
1331 			(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1332 			break;
1333 
1334 		case ZFS_PROP_RESERVATION:
1335 		case ZFS_PROP_REFRESERVATION:
1336 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1337 			    "size is greater than available space"));
1338 			(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1339 			break;
1340 
1341 		default:
1342 			(void) zfs_standard_error(hdl, err, errbuf);
1343 			break;
1344 		}
1345 		break;
1346 
1347 	case EBUSY:
1348 		(void) zfs_standard_error(hdl, EBUSY, errbuf);
1349 		break;
1350 
1351 	case EROFS:
1352 		(void) zfs_error(hdl, EZFS_DSREADONLY, errbuf);
1353 		break;
1354 
1355 	case ENOTSUP:
1356 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1357 		    "pool and or dataset must be upgraded to set this "
1358 		    "property or value"));
1359 		(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
1360 		break;
1361 
1362 	case ERANGE:
1363 		if (prop == ZFS_PROP_COMPRESSION) {
1364 			(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1365 			    "property setting is not allowed on "
1366 			    "bootable datasets"));
1367 			(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
1368 		} else {
1369 			(void) zfs_standard_error(hdl, err, errbuf);
1370 		}
1371 		break;
1372 
1373 	case EINVAL:
1374 		if (prop == ZPROP_INVAL) {
1375 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1376 		} else {
1377 			(void) zfs_standard_error(hdl, err, errbuf);
1378 		}
1379 		break;
1380 
1381 	case EOVERFLOW:
1382 		/*
1383 		 * This platform can't address a volume this big.
1384 		 */
1385 #ifdef _ILP32
1386 		if (prop == ZFS_PROP_VOLSIZE) {
1387 			(void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf);
1388 			break;
1389 		}
1390 #endif
1391 		/* FALLTHROUGH */
1392 	default:
1393 		(void) zfs_standard_error(hdl, err, errbuf);
1394 	}
1395 }
1396 
1397 /*
1398  * Given a property name and value, set the property for the given dataset.
1399  */
1400 int
1401 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1402 {
1403 	zfs_cmd_t zc = { 0 };
1404 	int ret = -1;
1405 	prop_changelist_t *cl = NULL;
1406 	char errbuf[1024];
1407 	libzfs_handle_t *hdl = zhp->zfs_hdl;
1408 	nvlist_t *nvl = NULL, *realprops;
1409 	zfs_prop_t prop;
1410 	boolean_t do_prefix;
1411 	uint64_t idx;
1412 	int added_resv;
1413 
1414 	(void) snprintf(errbuf, sizeof (errbuf),
1415 	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1416 	    zhp->zfs_name);
1417 
1418 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1419 	    nvlist_add_string(nvl, propname, propval) != 0) {
1420 		(void) no_memory(hdl);
1421 		goto error;
1422 	}
1423 
1424 	if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1425 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1426 		goto error;
1427 
1428 	nvlist_free(nvl);
1429 	nvl = realprops;
1430 
1431 	prop = zfs_name_to_prop(propname);
1432 
1433 	if (prop == ZFS_PROP_VOLSIZE) {
1434 		if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
1435 			goto error;
1436 	}
1437 
1438 	if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1439 		goto error;
1440 
1441 	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1442 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1443 		    "child dataset with inherited mountpoint is used "
1444 		    "in a non-global zone"));
1445 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1446 		goto error;
1447 	}
1448 
1449 	/*
1450 	 * If the dataset's canmount property is being set to noauto,
1451 	 * then we want to prevent unmounting & remounting it.
1452 	 */
1453 	do_prefix = !((prop == ZFS_PROP_CANMOUNT) &&
1454 	    (zprop_string_to_index(prop, propval, &idx,
1455 	    ZFS_TYPE_DATASET) == 0) && (idx == ZFS_CANMOUNT_NOAUTO));
1456 
1457 	if (do_prefix && (ret = changelist_prefix(cl)) != 0)
1458 		goto error;
1459 
1460 	/*
1461 	 * Execute the corresponding ioctl() to set this property.
1462 	 */
1463 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1464 
1465 	if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1466 		goto error;
1467 
1468 	ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1469 
1470 	if (ret != 0) {
1471 		zfs_setprop_error(hdl, prop, errno, errbuf);
1472 		if (added_resv && errno == ENOSPC) {
1473 			/* clean up the volsize property we tried to set */
1474 			uint64_t old_volsize = zfs_prop_get_int(zhp,
1475 			    ZFS_PROP_VOLSIZE);
1476 			nvlist_free(nvl);
1477 			zcmd_free_nvlists(&zc);
1478 			if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
1479 				goto error;
1480 			if (nvlist_add_uint64(nvl,
1481 			    zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1482 			    old_volsize) != 0)
1483 				goto error;
1484 			if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1485 				goto error;
1486 			(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1487 		}
1488 	} else {
1489 		if (do_prefix)
1490 			ret = changelist_postfix(cl);
1491 
1492 		/*
1493 		 * Refresh the statistics so the new property value
1494 		 * is reflected.
1495 		 */
1496 		if (ret == 0)
1497 			(void) get_stats(zhp);
1498 	}
1499 
1500 error:
1501 	nvlist_free(nvl);
1502 	zcmd_free_nvlists(&zc);
1503 	if (cl)
1504 		changelist_free(cl);
1505 	return (ret);
1506 }
1507 
1508 /*
1509  * Given a property, inherit the value from the parent dataset, or if received
1510  * is TRUE, revert to the received value, if any.
1511  */
1512 int
1513 zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
1514 {
1515 	zfs_cmd_t zc = { 0 };
1516 	int ret;
1517 	prop_changelist_t *cl;
1518 	libzfs_handle_t *hdl = zhp->zfs_hdl;
1519 	char errbuf[1024];
1520 	zfs_prop_t prop;
1521 
1522 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1523 	    "cannot inherit %s for '%s'"), propname, zhp->zfs_name);
1524 
1525 	zc.zc_cookie = received;
1526 	if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
1527 		/*
1528 		 * For user properties, the amount of work we have to do is very
1529 		 * small, so just do it here.
1530 		 */
1531 		if (!zfs_prop_user(propname)) {
1532 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1533 			    "invalid property"));
1534 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
1535 		}
1536 
1537 		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1538 		(void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1539 
1540 		if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0)
1541 			return (zfs_standard_error(hdl, errno, errbuf));
1542 
1543 		return (0);
1544 	}
1545 
1546 	/*
1547 	 * Verify that this property is inheritable.
1548 	 */
1549 	if (zfs_prop_readonly(prop))
1550 		return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf));
1551 
1552 	if (!zfs_prop_inheritable(prop) && !received)
1553 		return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
1554 
1555 	/*
1556 	 * Check to see if the value applies to this type
1557 	 */
1558 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1559 		return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
1560 
1561 	/*
1562 	 * Normalize the name, to get rid of shorthand abbreviations.
1563 	 */
1564 	propname = zfs_prop_to_name(prop);
1565 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1566 	(void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1567 
1568 	if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID &&
1569 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
1570 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1571 		    "dataset is used in a non-global zone"));
1572 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
1573 	}
1574 
1575 	/*
1576 	 * Determine datasets which will be affected by this change, if any.
1577 	 */
1578 	if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1579 		return (-1);
1580 
1581 	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1582 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1583 		    "child dataset with inherited mountpoint is used "
1584 		    "in a non-global zone"));
1585 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1586 		goto error;
1587 	}
1588 
1589 	if ((ret = changelist_prefix(cl)) != 0)
1590 		goto error;
1591 
1592 	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) {
1593 		return (zfs_standard_error(hdl, errno, errbuf));
1594 	} else {
1595 
1596 		if ((ret = changelist_postfix(cl)) != 0)
1597 			goto error;
1598 
1599 		/*
1600 		 * Refresh the statistics so the new property is reflected.
1601 		 */
1602 		(void) get_stats(zhp);
1603 	}
1604 
1605 error:
1606 	changelist_free(cl);
1607 	return (ret);
1608 }
1609 
1610 /*
1611  * True DSL properties are stored in an nvlist.  The following two functions
1612  * extract them appropriately.
1613  */
1614 static uint64_t
1615 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1616 {
1617 	nvlist_t *nv;
1618 	uint64_t value;
1619 
1620 	*source = NULL;
1621 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1622 	    zfs_prop_to_name(prop), &nv) == 0) {
1623 		verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
1624 		(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
1625 	} else {
1626 		verify(!zhp->zfs_props_table ||
1627 		    zhp->zfs_props_table[prop] == B_TRUE);
1628 		value = zfs_prop_default_numeric(prop);
1629 		*source = "";
1630 	}
1631 
1632 	return (value);
1633 }
1634 
1635 static char *
1636 getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1637 {
1638 	nvlist_t *nv;
1639 	char *value;
1640 
1641 	*source = NULL;
1642 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1643 	    zfs_prop_to_name(prop), &nv) == 0) {
1644 		verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
1645 		(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
1646 	} else {
1647 		verify(!zhp->zfs_props_table ||
1648 		    zhp->zfs_props_table[prop] == B_TRUE);
1649 		if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
1650 			value = "";
1651 		*source = "";
1652 	}
1653 
1654 	return (value);
1655 }
1656 
1657 static boolean_t
1658 zfs_is_recvd_props_mode(zfs_handle_t *zhp)
1659 {
1660 	return (zhp->zfs_props == zhp->zfs_recvd_props);
1661 }
1662 
1663 static void
1664 zfs_set_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
1665 {
1666 	*cookie = (uint64_t)(uintptr_t)zhp->zfs_props;
1667 	zhp->zfs_props = zhp->zfs_recvd_props;
1668 }
1669 
1670 static void
1671 zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
1672 {
1673 	zhp->zfs_props = (nvlist_t *)(uintptr_t)*cookie;
1674 	*cookie = 0;
1675 }
1676 
1677 /*
1678  * Internal function for getting a numeric property.  Both zfs_prop_get() and
1679  * zfs_prop_get_int() are built using this interface.
1680  *
1681  * Certain properties can be overridden using 'mount -o'.  In this case, scan
1682  * the contents of the /etc/mnttab entry, searching for the appropriate options.
1683  * If they differ from the on-disk values, report the current values and mark
1684  * the source "temporary".
1685  */
1686 static int
1687 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
1688     char **source, uint64_t *val)
1689 {
1690 	zfs_cmd_t zc = { 0 };
1691 	nvlist_t *zplprops = NULL;
1692 	struct mnttab mnt;
1693 	char *mntopt_on = NULL;
1694 	char *mntopt_off = NULL;
1695 	boolean_t received = zfs_is_recvd_props_mode(zhp);
1696 
1697 	*source = NULL;
1698 
1699 	switch (prop) {
1700 	case ZFS_PROP_ATIME:
1701 		mntopt_on = MNTOPT_ATIME;
1702 		mntopt_off = MNTOPT_NOATIME;
1703 		break;
1704 
1705 	case ZFS_PROP_DEVICES:
1706 		mntopt_on = MNTOPT_DEVICES;
1707 		mntopt_off = MNTOPT_NODEVICES;
1708 		break;
1709 
1710 	case ZFS_PROP_EXEC:
1711 		mntopt_on = MNTOPT_EXEC;
1712 		mntopt_off = MNTOPT_NOEXEC;
1713 		break;
1714 
1715 	case ZFS_PROP_READONLY:
1716 		mntopt_on = MNTOPT_RO;
1717 		mntopt_off = MNTOPT_RW;
1718 		break;
1719 
1720 	case ZFS_PROP_SETUID:
1721 		mntopt_on = MNTOPT_SETUID;
1722 		mntopt_off = MNTOPT_NOSETUID;
1723 		break;
1724 
1725 	case ZFS_PROP_XATTR:
1726 		mntopt_on = MNTOPT_XATTR;
1727 		mntopt_off = MNTOPT_NOXATTR;
1728 		break;
1729 
1730 	case ZFS_PROP_NBMAND:
1731 		mntopt_on = MNTOPT_NBMAND;
1732 		mntopt_off = MNTOPT_NONBMAND;
1733 		break;
1734 	}
1735 
1736 	/*
1737 	 * Because looking up the mount options is potentially expensive
1738 	 * (iterating over all of /etc/mnttab), we defer its calculation until
1739 	 * we're looking up a property which requires its presence.
1740 	 */
1741 	if (!zhp->zfs_mntcheck &&
1742 	    (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
1743 		libzfs_handle_t *hdl = zhp->zfs_hdl;
1744 		struct mnttab entry;
1745 
1746 		if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) {
1747 			zhp->zfs_mntopts = zfs_strdup(hdl,
1748 			    entry.mnt_mntopts);
1749 			if (zhp->zfs_mntopts == NULL)
1750 				return (-1);
1751 		}
1752 
1753 		zhp->zfs_mntcheck = B_TRUE;
1754 	}
1755 
1756 	if (zhp->zfs_mntopts == NULL)
1757 		mnt.mnt_mntopts = "";
1758 	else
1759 		mnt.mnt_mntopts = zhp->zfs_mntopts;
1760 
1761 	switch (prop) {
1762 	case ZFS_PROP_ATIME:
1763 	case ZFS_PROP_DEVICES:
1764 	case ZFS_PROP_EXEC:
1765 	case ZFS_PROP_READONLY:
1766 	case ZFS_PROP_SETUID:
1767 	case ZFS_PROP_XATTR:
1768 	case ZFS_PROP_NBMAND:
1769 		*val = getprop_uint64(zhp, prop, source);
1770 
1771 		if (received)
1772 			break;
1773 
1774 		if (hasmntopt(&mnt, mntopt_on) && !*val) {
1775 			*val = B_TRUE;
1776 			if (src)
1777 				*src = ZPROP_SRC_TEMPORARY;
1778 		} else if (hasmntopt(&mnt, mntopt_off) && *val) {
1779 			*val = B_FALSE;
1780 			if (src)
1781 				*src = ZPROP_SRC_TEMPORARY;
1782 		}
1783 		break;
1784 
1785 	case ZFS_PROP_CANMOUNT:
1786 	case ZFS_PROP_VOLSIZE:
1787 	case ZFS_PROP_QUOTA:
1788 	case ZFS_PROP_REFQUOTA:
1789 	case ZFS_PROP_RESERVATION:
1790 	case ZFS_PROP_REFRESERVATION:
1791 		*val = getprop_uint64(zhp, prop, source);
1792 
1793 		if (*source == NULL) {
1794 			/* not default, must be local */
1795 			*source = zhp->zfs_name;
1796 		}
1797 		break;
1798 
1799 	case ZFS_PROP_MOUNTED:
1800 		*val = (zhp->zfs_mntopts != NULL);
1801 		break;
1802 
1803 	case ZFS_PROP_NUMCLONES:
1804 		*val = zhp->zfs_dmustats.dds_num_clones;
1805 		break;
1806 
1807 	case ZFS_PROP_VERSION:
1808 	case ZFS_PROP_NORMALIZE:
1809 	case ZFS_PROP_UTF8ONLY:
1810 	case ZFS_PROP_CASE:
1811 		if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
1812 		    zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
1813 			return (-1);
1814 		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1815 		if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
1816 			zcmd_free_nvlists(&zc);
1817 			return (-1);
1818 		}
1819 		if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
1820 		    nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
1821 		    val) != 0) {
1822 			zcmd_free_nvlists(&zc);
1823 			return (-1);
1824 		}
1825 		if (zplprops)
1826 			nvlist_free(zplprops);
1827 		zcmd_free_nvlists(&zc);
1828 		break;
1829 
1830 	default:
1831 		switch (zfs_prop_get_type(prop)) {
1832 		case PROP_TYPE_NUMBER:
1833 		case PROP_TYPE_INDEX:
1834 			*val = getprop_uint64(zhp, prop, source);
1835 			/*
1836 			 * If we tried to use a default value for a
1837 			 * readonly property, it means that it was not
1838 			 * present.
1839 			 */
1840 			if (zfs_prop_readonly(prop) &&
1841 			    *source != NULL && (*source)[0] == '\0') {
1842 				*source = NULL;
1843 			}
1844 			break;
1845 
1846 		case PROP_TYPE_STRING:
1847 		default:
1848 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
1849 			    "cannot get non-numeric property"));
1850 			return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
1851 			    dgettext(TEXT_DOMAIN, "internal error")));
1852 		}
1853 	}
1854 
1855 	return (0);
1856 }
1857 
1858 /*
1859  * Calculate the source type, given the raw source string.
1860  */
1861 static void
1862 get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
1863     char *statbuf, size_t statlen)
1864 {
1865 	if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY)
1866 		return;
1867 
1868 	if (source == NULL) {
1869 		*srctype = ZPROP_SRC_NONE;
1870 	} else if (source[0] == '\0') {
1871 		*srctype = ZPROP_SRC_DEFAULT;
1872 	} else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) {
1873 		*srctype = ZPROP_SRC_RECEIVED;
1874 	} else {
1875 		if (strcmp(source, zhp->zfs_name) == 0) {
1876 			*srctype = ZPROP_SRC_LOCAL;
1877 		} else {
1878 			(void) strlcpy(statbuf, source, statlen);
1879 			*srctype = ZPROP_SRC_INHERITED;
1880 		}
1881 	}
1882 
1883 }
1884 
1885 int
1886 zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
1887     size_t proplen, boolean_t literal)
1888 {
1889 	zfs_prop_t prop;
1890 	int err = 0;
1891 
1892 	if (zhp->zfs_recvd_props == NULL)
1893 		if (get_recvd_props_ioctl(zhp) != 0)
1894 			return (-1);
1895 
1896 	prop = zfs_name_to_prop(propname);
1897 
1898 	if (prop != ZPROP_INVAL) {
1899 		uint64_t cookie;
1900 		if (!nvlist_exists(zhp->zfs_recvd_props, propname))
1901 			return (-1);
1902 		zfs_set_recvd_props_mode(zhp, &cookie);
1903 		err = zfs_prop_get(zhp, prop, propbuf, proplen,
1904 		    NULL, NULL, 0, literal);
1905 		zfs_unset_recvd_props_mode(zhp, &cookie);
1906 	} else {
1907 		nvlist_t *propval;
1908 		char *recvdval;
1909 		if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
1910 		    propname, &propval) != 0)
1911 			return (-1);
1912 		verify(nvlist_lookup_string(propval, ZPROP_VALUE,
1913 		    &recvdval) == 0);
1914 		(void) strlcpy(propbuf, recvdval, proplen);
1915 	}
1916 
1917 	return (err == 0 ? 0 : -1);
1918 }
1919 
1920 static int
1921 get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
1922 {
1923 	nvlist_t *value;
1924 	nvpair_t *pair;
1925 
1926 	value = zfs_get_clones_nvl(zhp);
1927 	if (value == NULL)
1928 		return (-1);
1929 
1930 	propbuf[0] = '\0';
1931 	for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
1932 	    pair = nvlist_next_nvpair(value, pair)) {
1933 		if (propbuf[0] != '\0')
1934 			(void) strlcat(propbuf, ",", proplen);
1935 		(void) strlcat(propbuf, nvpair_name(pair), proplen);
1936 	}
1937 
1938 	return (0);
1939 }
1940 
1941 struct get_clones_arg {
1942 	uint64_t numclones;
1943 	nvlist_t *value;
1944 	const char *origin;
1945 	char buf[ZFS_MAXNAMELEN];
1946 };
1947 
1948 int
1949 get_clones_cb(zfs_handle_t *zhp, void *arg)
1950 {
1951 	struct get_clones_arg *gca = arg;
1952 
1953 	if (gca->numclones == 0) {
1954 		zfs_close(zhp);
1955 		return (0);
1956 	}
1957 
1958 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
1959 	    NULL, NULL, 0, B_TRUE) != 0)
1960 		goto out;
1961 	if (strcmp(gca->buf, gca->origin) == 0) {
1962 		if (nvlist_add_boolean(gca->value, zfs_get_name(zhp)) != 0) {
1963 			zfs_close(zhp);
1964 			return (no_memory(zhp->zfs_hdl));
1965 		}
1966 		gca->numclones--;
1967 	}
1968 
1969 out:
1970 	(void) zfs_iter_children(zhp, get_clones_cb, gca);
1971 	zfs_close(zhp);
1972 	return (0);
1973 }
1974 
1975 nvlist_t *
1976 zfs_get_clones_nvl(zfs_handle_t *zhp)
1977 {
1978 	nvlist_t *nv, *value;
1979 
1980 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1981 	    zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
1982 		struct get_clones_arg gca;
1983 
1984 		/*
1985 		 * if this is a snapshot, then the kernel wasn't able
1986 		 * to get the clones.  Do it by slowly iterating.
1987 		 */
1988 		if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
1989 			return (NULL);
1990 		if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
1991 			return (NULL);
1992 		if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
1993 			nvlist_free(nv);
1994 			return (NULL);
1995 		}
1996 
1997 		gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
1998 		gca.value = value;
1999 		gca.origin = zhp->zfs_name;
2000 
2001 		if (gca.numclones != 0) {
2002 			zfs_handle_t *root;
2003 			char pool[ZFS_MAXNAMELEN];
2004 			char *cp = pool;
2005 
2006 			/* get the pool name */
2007 			(void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
2008 			(void) strsep(&cp, "/@");
2009 			root = zfs_open(zhp->zfs_hdl, pool,
2010 			    ZFS_TYPE_FILESYSTEM);
2011 
2012 			(void) get_clones_cb(root, &gca);
2013 		}
2014 
2015 		if (gca.numclones != 0 ||
2016 		    nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
2017 		    nvlist_add_nvlist(zhp->zfs_props,
2018 		    zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
2019 			nvlist_free(nv);
2020 			nvlist_free(value);
2021 			return (NULL);
2022 		}
2023 		nvlist_free(nv);
2024 		nvlist_free(value);
2025 		verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
2026 		    zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
2027 	}
2028 
2029 	verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
2030 
2031 	return (value);
2032 }
2033 
2034 /*
2035  * Retrieve a property from the given object.  If 'literal' is specified, then
2036  * numbers are left as exact values.  Otherwise, numbers are converted to a
2037  * human-readable form.
2038  *
2039  * Returns 0 on success, or -1 on error.
2040  */
2041 int
2042 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
2043     zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
2044 {
2045 	char *source = NULL;
2046 	uint64_t val;
2047 	char *str;
2048 	const char *strval;
2049 	boolean_t received = zfs_is_recvd_props_mode(zhp);
2050 
2051 	/*
2052 	 * Check to see if this property applies to our object
2053 	 */
2054 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
2055 		return (-1);
2056 
2057 	if (received && zfs_prop_readonly(prop))
2058 		return (-1);
2059 
2060 	if (src)
2061 		*src = ZPROP_SRC_NONE;
2062 
2063 	switch (prop) {
2064 	case ZFS_PROP_CREATION:
2065 		/*
2066 		 * 'creation' is a time_t stored in the statistics.  We convert
2067 		 * this into a string unless 'literal' is specified.
2068 		 */
2069 		{
2070 			val = getprop_uint64(zhp, prop, &source);
2071 			time_t time = (time_t)val;
2072 			struct tm t;
2073 
2074 			if (literal ||
2075 			    localtime_r(&time, &t) == NULL ||
2076 			    strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
2077 			    &t) == 0)
2078 				(void) snprintf(propbuf, proplen, "%llu", val);
2079 		}
2080 		break;
2081 
2082 	case ZFS_PROP_MOUNTPOINT:
2083 		/*
2084 		 * Getting the precise mountpoint can be tricky.
2085 		 *
2086 		 *  - for 'none' or 'legacy', return those values.
2087 		 *  - for inherited mountpoints, we want to take everything
2088 		 *    after our ancestor and append it to the inherited value.
2089 		 *
2090 		 * If the pool has an alternate root, we want to prepend that
2091 		 * root to any values we return.
2092 		 */
2093 
2094 		str = getprop_string(zhp, prop, &source);
2095 
2096 		if (str[0] == '/') {
2097 			char buf[MAXPATHLEN];
2098 			char *root = buf;
2099 			const char *relpath;
2100 
2101 			/*
2102 			 * If we inherit the mountpoint, even from a dataset
2103 			 * with a received value, the source will be the path of
2104 			 * the dataset we inherit from. If source is
2105 			 * ZPROP_SOURCE_VAL_RECVD, the received value is not
2106 			 * inherited.
2107 			 */
2108 			if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2109 				relpath = "";
2110 			} else {
2111 				relpath = zhp->zfs_name + strlen(source);
2112 				if (relpath[0] == '/')
2113 					relpath++;
2114 			}
2115 
2116 			if ((zpool_get_prop(zhp->zpool_hdl,
2117 			    ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
2118 			    (strcmp(root, "-") == 0))
2119 				root[0] = '\0';
2120 			/*
2121 			 * Special case an alternate root of '/'. This will
2122 			 * avoid having multiple leading slashes in the
2123 			 * mountpoint path.
2124 			 */
2125 			if (strcmp(root, "/") == 0)
2126 				root++;
2127 
2128 			/*
2129 			 * If the mountpoint is '/' then skip over this
2130 			 * if we are obtaining either an alternate root or
2131 			 * an inherited mountpoint.
2132 			 */
2133 			if (str[1] == '\0' && (root[0] != '\0' ||
2134 			    relpath[0] != '\0'))
2135 				str++;
2136 
2137 			if (relpath[0] == '\0')
2138 				(void) snprintf(propbuf, proplen, "%s%s",
2139 				    root, str);
2140 			else
2141 				(void) snprintf(propbuf, proplen, "%s%s%s%s",
2142 				    root, str, relpath[0] == '@' ? "" : "/",
2143 				    relpath);
2144 		} else {
2145 			/* 'legacy' or 'none' */
2146 			(void) strlcpy(propbuf, str, proplen);
2147 		}
2148 
2149 		break;
2150 
2151 	case ZFS_PROP_ORIGIN:
2152 		(void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
2153 		    proplen);
2154 		/*
2155 		 * If there is no parent at all, return failure to indicate that
2156 		 * it doesn't apply to this dataset.
2157 		 */
2158 		if (propbuf[0] == '\0')
2159 			return (-1);
2160 		break;
2161 
2162 	case ZFS_PROP_CLONES:
2163 		if (get_clones_string(zhp, propbuf, proplen) != 0)
2164 			return (-1);
2165 		break;
2166 
2167 	case ZFS_PROP_QUOTA:
2168 	case ZFS_PROP_REFQUOTA:
2169 	case ZFS_PROP_RESERVATION:
2170 	case ZFS_PROP_REFRESERVATION:
2171 
2172 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2173 			return (-1);
2174 
2175 		/*
2176 		 * If quota or reservation is 0, we translate this into 'none'
2177 		 * (unless literal is set), and indicate that it's the default
2178 		 * value.  Otherwise, we print the number nicely and indicate
2179 		 * that its set locally.
2180 		 */
2181 		if (val == 0) {
2182 			if (literal)
2183 				(void) strlcpy(propbuf, "0", proplen);
2184 			else
2185 				(void) strlcpy(propbuf, "none", proplen);
2186 		} else {
2187 			if (literal)
2188 				(void) snprintf(propbuf, proplen, "%llu",
2189 				    (u_longlong_t)val);
2190 			else
2191 				zfs_nicenum(val, propbuf, proplen);
2192 		}
2193 		break;
2194 
2195 	case ZFS_PROP_REFRATIO:
2196 	case ZFS_PROP_COMPRESSRATIO:
2197 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2198 			return (-1);
2199 		(void) snprintf(propbuf, proplen, "%llu.%02llux",
2200 		    (u_longlong_t)(val / 100),
2201 		    (u_longlong_t)(val % 100));
2202 		break;
2203 
2204 	case ZFS_PROP_TYPE:
2205 		switch (zhp->zfs_type) {
2206 		case ZFS_TYPE_FILESYSTEM:
2207 			str = "filesystem";
2208 			break;
2209 		case ZFS_TYPE_VOLUME:
2210 			str = "volume";
2211 			break;
2212 		case ZFS_TYPE_SNAPSHOT:
2213 			str = "snapshot";
2214 			break;
2215 		default:
2216 			abort();
2217 		}
2218 		(void) snprintf(propbuf, proplen, "%s", str);
2219 		break;
2220 
2221 	case ZFS_PROP_MOUNTED:
2222 		/*
2223 		 * The 'mounted' property is a pseudo-property that described
2224 		 * whether the filesystem is currently mounted.  Even though
2225 		 * it's a boolean value, the typical values of "on" and "off"
2226 		 * don't make sense, so we translate to "yes" and "no".
2227 		 */
2228 		if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
2229 		    src, &source, &val) != 0)
2230 			return (-1);
2231 		if (val)
2232 			(void) strlcpy(propbuf, "yes", proplen);
2233 		else
2234 			(void) strlcpy(propbuf, "no", proplen);
2235 		break;
2236 
2237 	case ZFS_PROP_NAME:
2238 		/*
2239 		 * The 'name' property is a pseudo-property derived from the
2240 		 * dataset name.  It is presented as a real property to simplify
2241 		 * consumers.
2242 		 */
2243 		(void) strlcpy(propbuf, zhp->zfs_name, proplen);
2244 		break;
2245 
2246 	case ZFS_PROP_MLSLABEL:
2247 		{
2248 			m_label_t *new_sl = NULL;
2249 			char *ascii = NULL;	/* human readable label */
2250 
2251 			(void) strlcpy(propbuf,
2252 			    getprop_string(zhp, prop, &source), proplen);
2253 
2254 			if (literal || (strcasecmp(propbuf,
2255 			    ZFS_MLSLABEL_DEFAULT) == 0))
2256 				break;
2257 
2258 			/*
2259 			 * Try to translate the internal hex string to
2260 			 * human-readable output.  If there are any
2261 			 * problems just use the hex string.
2262 			 */
2263 
2264 			if (str_to_label(propbuf, &new_sl, MAC_LABEL,
2265 			    L_NO_CORRECTION, NULL) == -1) {
2266 				m_label_free(new_sl);
2267 				break;
2268 			}
2269 
2270 			if (label_to_str(new_sl, &ascii, M_LABEL,
2271 			    DEF_NAMES) != 0) {
2272 				if (ascii)
2273 					free(ascii);
2274 				m_label_free(new_sl);
2275 				break;
2276 			}
2277 			m_label_free(new_sl);
2278 
2279 			(void) strlcpy(propbuf, ascii, proplen);
2280 			free(ascii);
2281 		}
2282 		break;
2283 
2284 	case ZFS_PROP_GUID:
2285 		/*
2286 		 * GUIDs are stored as numbers, but they are identifiers.
2287 		 * We don't want them to be pretty printed, because pretty
2288 		 * printing mangles the ID into a truncated and useless value.
2289 		 */
2290 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2291 			return (-1);
2292 		(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
2293 		break;
2294 
2295 	default:
2296 		switch (zfs_prop_get_type(prop)) {
2297 		case PROP_TYPE_NUMBER:
2298 			if (get_numeric_property(zhp, prop, src,
2299 			    &source, &val) != 0)
2300 				return (-1);
2301 			if (literal)
2302 				(void) snprintf(propbuf, proplen, "%llu",
2303 				    (u_longlong_t)val);
2304 			else
2305 				zfs_nicenum(val, propbuf, proplen);
2306 			break;
2307 
2308 		case PROP_TYPE_STRING:
2309 			(void) strlcpy(propbuf,
2310 			    getprop_string(zhp, prop, &source), proplen);
2311 			break;
2312 
2313 		case PROP_TYPE_INDEX:
2314 			if (get_numeric_property(zhp, prop, src,
2315 			    &source, &val) != 0)
2316 				return (-1);
2317 			if (zfs_prop_index_to_string(prop, val, &strval) != 0)
2318 				return (-1);
2319 			(void) strlcpy(propbuf, strval, proplen);
2320 			break;
2321 
2322 		default:
2323 			abort();
2324 		}
2325 	}
2326 
2327 	get_source(zhp, src, source, statbuf, statlen);
2328 
2329 	return (0);
2330 }
2331 
2332 /*
2333  * Utility function to get the given numeric property.  Does no validation that
2334  * the given property is the appropriate type; should only be used with
2335  * hard-coded property types.
2336  */
2337 uint64_t
2338 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
2339 {
2340 	char *source;
2341 	uint64_t val;
2342 
2343 	(void) get_numeric_property(zhp, prop, NULL, &source, &val);
2344 
2345 	return (val);
2346 }
2347 
2348 int
2349 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
2350 {
2351 	char buf[64];
2352 
2353 	(void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
2354 	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
2355 }
2356 
2357 /*
2358  * Similar to zfs_prop_get(), but returns the value as an integer.
2359  */
2360 int
2361 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
2362     zprop_source_t *src, char *statbuf, size_t statlen)
2363 {
2364 	char *source;
2365 
2366 	/*
2367 	 * Check to see if this property applies to our object
2368 	 */
2369 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
2370 		return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
2371 		    dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
2372 		    zfs_prop_to_name(prop)));
2373 	}
2374 
2375 	if (src)
2376 		*src = ZPROP_SRC_NONE;
2377 
2378 	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
2379 		return (-1);
2380 
2381 	get_source(zhp, src, source, statbuf, statlen);
2382 
2383 	return (0);
2384 }
2385 
2386 static int
2387 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
2388     char **domainp, idmap_rid_t *ridp)
2389 {
2390 	idmap_get_handle_t *get_hdl = NULL;
2391 	idmap_stat status;
2392 	int err = EINVAL;
2393 
2394 	if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
2395 		goto out;
2396 
2397 	if (isuser) {
2398 		err = idmap_get_sidbyuid(get_hdl, id,
2399 		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2400 	} else {
2401 		err = idmap_get_sidbygid(get_hdl, id,
2402 		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2403 	}
2404 	if (err == IDMAP_SUCCESS &&
2405 	    idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
2406 	    status == IDMAP_SUCCESS)
2407 		err = 0;
2408 	else
2409 		err = EINVAL;
2410 out:
2411 	if (get_hdl)
2412 		idmap_get_destroy(get_hdl);
2413 	return (err);
2414 }
2415 
2416 /*
2417  * convert the propname into parameters needed by kernel
2418  * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
2419  * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
2420  */
2421 static int
2422 userquota_propname_decode(const char *propname, boolean_t zoned,
2423     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
2424 {
2425 	zfs_userquota_prop_t type;
2426 	char *cp, *end;
2427 	char *numericsid = NULL;
2428 	boolean_t isuser;
2429 
2430 	domain[0] = '\0';
2431 
2432 	/* Figure out the property type ({user|group}{quota|space}) */
2433 	for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
2434 		if (strncmp(propname, zfs_userquota_prop_prefixes[type],
2435 		    strlen(zfs_userquota_prop_prefixes[type])) == 0)
2436 			break;
2437 	}
2438 	if (type == ZFS_NUM_USERQUOTA_PROPS)
2439 		return (EINVAL);
2440 	*typep = type;
2441 
2442 	isuser = (type == ZFS_PROP_USERQUOTA ||
2443 	    type == ZFS_PROP_USERUSED);
2444 
2445 	cp = strchr(propname, '@') + 1;
2446 
2447 	if (strchr(cp, '@')) {
2448 		/*
2449 		 * It's a SID name (eg "user@domain") that needs to be
2450 		 * turned into S-1-domainID-RID.
2451 		 */
2452 		directory_error_t e;
2453 		if (zoned && getzoneid() == GLOBAL_ZONEID)
2454 			return (ENOENT);
2455 		if (isuser) {
2456 			e = directory_sid_from_user_name(NULL,
2457 			    cp, &numericsid);
2458 		} else {
2459 			e = directory_sid_from_group_name(NULL,
2460 			    cp, &numericsid);
2461 		}
2462 		if (e != NULL) {
2463 			directory_error_free(e);
2464 			return (ENOENT);
2465 		}
2466 		if (numericsid == NULL)
2467 			return (ENOENT);
2468 		cp = numericsid;
2469 		/* will be further decoded below */
2470 	}
2471 
2472 	if (strncmp(cp, "S-1-", 4) == 0) {
2473 		/* It's a numeric SID (eg "S-1-234-567-89") */
2474 		(void) strlcpy(domain, cp, domainlen);
2475 		cp = strrchr(domain, '-');
2476 		*cp = '\0';
2477 		cp++;
2478 
2479 		errno = 0;
2480 		*ridp = strtoull(cp, &end, 10);
2481 		if (numericsid) {
2482 			free(numericsid);
2483 			numericsid = NULL;
2484 		}
2485 		if (errno != 0 || *end != '\0')
2486 			return (EINVAL);
2487 	} else if (!isdigit(*cp)) {
2488 		/*
2489 		 * It's a user/group name (eg "user") that needs to be
2490 		 * turned into a uid/gid
2491 		 */
2492 		if (zoned && getzoneid() == GLOBAL_ZONEID)
2493 			return (ENOENT);
2494 		if (isuser) {
2495 			struct passwd *pw;
2496 			pw = getpwnam(cp);
2497 			if (pw == NULL)
2498 				return (ENOENT);
2499 			*ridp = pw->pw_uid;
2500 		} else {
2501 			struct group *gr;
2502 			gr = getgrnam(cp);
2503 			if (gr == NULL)
2504 				return (ENOENT);
2505 			*ridp = gr->gr_gid;
2506 		}
2507 	} else {
2508 		/* It's a user/group ID (eg "12345"). */
2509 		uid_t id = strtoul(cp, &end, 10);
2510 		idmap_rid_t rid;
2511 		char *mapdomain;
2512 
2513 		if (*end != '\0')
2514 			return (EINVAL);
2515 		if (id > MAXUID) {
2516 			/* It's an ephemeral ID. */
2517 			if (idmap_id_to_numeric_domain_rid(id, isuser,
2518 			    &mapdomain, &rid) != 0)
2519 				return (ENOENT);
2520 			(void) strlcpy(domain, mapdomain, domainlen);
2521 			*ridp = rid;
2522 		} else {
2523 			*ridp = id;
2524 		}
2525 	}
2526 
2527 	ASSERT3P(numericsid, ==, NULL);
2528 	return (0);
2529 }
2530 
2531 static int
2532 zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
2533     uint64_t *propvalue, zfs_userquota_prop_t *typep)
2534 {
2535 	int err;
2536 	zfs_cmd_t zc = { 0 };
2537 
2538 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2539 
2540 	err = userquota_propname_decode(propname,
2541 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
2542 	    typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
2543 	zc.zc_objset_type = *typep;
2544 	if (err)
2545 		return (err);
2546 
2547 	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
2548 	if (err)
2549 		return (err);
2550 
2551 	*propvalue = zc.zc_cookie;
2552 	return (0);
2553 }
2554 
2555 int
2556 zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
2557     uint64_t *propvalue)
2558 {
2559 	zfs_userquota_prop_t type;
2560 
2561 	return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
2562 	    &type));
2563 }
2564 
2565 int
2566 zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
2567     char *propbuf, int proplen, boolean_t literal)
2568 {
2569 	int err;
2570 	uint64_t propvalue;
2571 	zfs_userquota_prop_t type;
2572 
2573 	err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
2574 	    &type);
2575 
2576 	if (err)
2577 		return (err);
2578 
2579 	if (literal) {
2580 		(void) snprintf(propbuf, proplen, "%llu", propvalue);
2581 	} else if (propvalue == 0 &&
2582 	    (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
2583 		(void) strlcpy(propbuf, "none", proplen);
2584 	} else {
2585 		zfs_nicenum(propvalue, propbuf, proplen);
2586 	}
2587 	return (0);
2588 }
2589 
2590 int
2591 zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
2592     uint64_t *propvalue)
2593 {
2594 	int err;
2595 	zfs_cmd_t zc = { 0 };
2596 	const char *snapname;
2597 
2598 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2599 
2600 	snapname = strchr(propname, '@') + 1;
2601 	if (strchr(snapname, '@')) {
2602 		(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
2603 	} else {
2604 		/* snapname is the short name, append it to zhp's fsname */
2605 		char *cp;
2606 
2607 		(void) strlcpy(zc.zc_value, zhp->zfs_name,
2608 		    sizeof (zc.zc_value));
2609 		cp = strchr(zc.zc_value, '@');
2610 		if (cp != NULL)
2611 			*cp = '\0';
2612 		(void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
2613 		(void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
2614 	}
2615 
2616 	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
2617 	if (err)
2618 		return (err);
2619 
2620 	*propvalue = zc.zc_cookie;
2621 	return (0);
2622 }
2623 
2624 int
2625 zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
2626     char *propbuf, int proplen, boolean_t literal)
2627 {
2628 	int err;
2629 	uint64_t propvalue;
2630 
2631 	err = zfs_prop_get_written_int(zhp, propname, &propvalue);
2632 
2633 	if (err)
2634 		return (err);
2635 
2636 	if (literal) {
2637 		(void) snprintf(propbuf, proplen, "%llu", propvalue);
2638 	} else {
2639 		zfs_nicenum(propvalue, propbuf, proplen);
2640 	}
2641 	return (0);
2642 }
2643 
2644 int
2645 zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
2646     uint64_t *usedp)
2647 {
2648 	int err;
2649 	zfs_cmd_t zc = { 0 };
2650 
2651 	(void) strlcpy(zc.zc_name, lastsnap->zfs_name, sizeof (zc.zc_name));
2652 	(void) strlcpy(zc.zc_value, firstsnap->zfs_name, sizeof (zc.zc_value));
2653 
2654 	err = ioctl(lastsnap->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_SNAPS, &zc);
2655 	if (err)
2656 		return (err);
2657 
2658 	*usedp = zc.zc_cookie;
2659 
2660 	return (0);
2661 }
2662 
2663 /*
2664  * Returns the name of the given zfs handle.
2665  */
2666 const char *
2667 zfs_get_name(const zfs_handle_t *zhp)
2668 {
2669 	return (zhp->zfs_name);
2670 }
2671 
2672 /*
2673  * Returns the type of the given zfs handle.
2674  */
2675 zfs_type_t
2676 zfs_get_type(const zfs_handle_t *zhp)
2677 {
2678 	return (zhp->zfs_type);
2679 }
2680 
2681 /*
2682  * Is one dataset name a child dataset of another?
2683  *
2684  * Needs to handle these cases:
2685  * Dataset 1	"a/foo"		"a/foo"		"a/foo"		"a/foo"
2686  * Dataset 2	"a/fo"		"a/foobar"	"a/bar/baz"	"a/foo/bar"
2687  * Descendant?	No.		No.		No.		Yes.
2688  */
2689 static boolean_t
2690 is_descendant(const char *ds1, const char *ds2)
2691 {
2692 	size_t d1len = strlen(ds1);
2693 
2694 	/* ds2 can't be a descendant if it's smaller */
2695 	if (strlen(ds2) < d1len)
2696 		return (B_FALSE);
2697 
2698 	/* otherwise, compare strings and verify that there's a '/' char */
2699 	return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0));
2700 }
2701 
2702 /*
2703  * Given a complete name, return just the portion that refers to the parent.
2704  * Will return -1 if there is no parent (path is just the name of the
2705  * pool).
2706  */
2707 static int
2708 parent_name(const char *path, char *buf, size_t buflen)
2709 {
2710 	char *slashp;
2711 
2712 	(void) strlcpy(buf, path, buflen);
2713 
2714 	if ((slashp = strrchr(buf, '/')) == NULL)
2715 		return (-1);
2716 	*slashp = '\0';
2717 
2718 	return (0);
2719 }
2720 
2721 /*
2722  * If accept_ancestor is false, then check to make sure that the given path has
2723  * a parent, and that it exists.  If accept_ancestor is true, then find the
2724  * closest existing ancestor for the given path.  In prefixlen return the
2725  * length of already existing prefix of the given path.  We also fetch the
2726  * 'zoned' property, which is used to validate property settings when creating
2727  * new datasets.
2728  */
2729 static int
2730 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
2731     boolean_t accept_ancestor, int *prefixlen)
2732 {
2733 	zfs_cmd_t zc = { 0 };
2734 	char parent[ZFS_MAXNAMELEN];
2735 	char *slash;
2736 	zfs_handle_t *zhp;
2737 	char errbuf[1024];
2738 	uint64_t is_zoned;
2739 
2740 	(void) snprintf(errbuf, sizeof (errbuf),
2741 	    dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
2742 
2743 	/* get parent, and check to see if this is just a pool */
2744 	if (parent_name(path, parent, sizeof (parent)) != 0) {
2745 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2746 		    "missing dataset name"));
2747 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2748 	}
2749 
2750 	/* check to see if the pool exists */
2751 	if ((slash = strchr(parent, '/')) == NULL)
2752 		slash = parent + strlen(parent);
2753 	(void) strncpy(zc.zc_name, parent, slash - parent);
2754 	zc.zc_name[slash - parent] = '\0';
2755 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
2756 	    errno == ENOENT) {
2757 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2758 		    "no such pool '%s'"), zc.zc_name);
2759 		return (zfs_error(hdl, EZFS_NOENT, errbuf));
2760 	}
2761 
2762 	/* check to see if the parent dataset exists */
2763 	while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
2764 		if (errno == ENOENT && accept_ancestor) {
2765 			/*
2766 			 * Go deeper to find an ancestor, give up on top level.
2767 			 */
2768 			if (parent_name(parent, parent, sizeof (parent)) != 0) {
2769 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2770 				    "no such pool '%s'"), zc.zc_name);
2771 				return (zfs_error(hdl, EZFS_NOENT, errbuf));
2772 			}
2773 		} else if (errno == ENOENT) {
2774 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2775 			    "parent does not exist"));
2776 			return (zfs_error(hdl, EZFS_NOENT, errbuf));
2777 		} else
2778 			return (zfs_standard_error(hdl, errno, errbuf));
2779 	}
2780 
2781 	is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
2782 	if (zoned != NULL)
2783 		*zoned = is_zoned;
2784 
2785 	/* we are in a non-global zone, but parent is in the global zone */
2786 	if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
2787 		(void) zfs_standard_error(hdl, EPERM, errbuf);
2788 		zfs_close(zhp);
2789 		return (-1);
2790 	}
2791 
2792 	/* make sure parent is a filesystem */
2793 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2794 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2795 		    "parent is not a filesystem"));
2796 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
2797 		zfs_close(zhp);
2798 		return (-1);
2799 	}
2800 
2801 	zfs_close(zhp);
2802 	if (prefixlen != NULL)
2803 		*prefixlen = strlen(parent);
2804 	return (0);
2805 }
2806 
2807 /*
2808  * Finds whether the dataset of the given type(s) exists.
2809  */
2810 boolean_t
2811 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
2812 {
2813 	zfs_handle_t *zhp;
2814 
2815 	if (!zfs_validate_name(hdl, path, types, B_FALSE))
2816 		return (B_FALSE);
2817 
2818 	/*
2819 	 * Try to get stats for the dataset, which will tell us if it exists.
2820 	 */
2821 	if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
2822 		int ds_type = zhp->zfs_type;
2823 
2824 		zfs_close(zhp);
2825 		if (types & ds_type)
2826 			return (B_TRUE);
2827 	}
2828 	return (B_FALSE);
2829 }
2830 
2831 /*
2832  * Given a path to 'target', create all the ancestors between
2833  * the prefixlen portion of the path, and the target itself.
2834  * Fail if the initial prefixlen-ancestor does not already exist.
2835  */
2836 int
2837 create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
2838 {
2839 	zfs_handle_t *h;
2840 	char *cp;
2841 	const char *opname;
2842 
2843 	/* make sure prefix exists */
2844 	cp = target + prefixlen;
2845 	if (*cp != '/') {
2846 		assert(strchr(cp, '/') == NULL);
2847 		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2848 	} else {
2849 		*cp = '\0';
2850 		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2851 		*cp = '/';
2852 	}
2853 	if (h == NULL)
2854 		return (-1);
2855 	zfs_close(h);
2856 
2857 	/*
2858 	 * Attempt to create, mount, and share any ancestor filesystems,
2859 	 * up to the prefixlen-long one.
2860 	 */
2861 	for (cp = target + prefixlen + 1;
2862 	    cp = strchr(cp, '/'); *cp = '/', cp++) {
2863 		char *logstr;
2864 
2865 		*cp = '\0';
2866 
2867 		h = make_dataset_handle(hdl, target);
2868 		if (h) {
2869 			/* it already exists, nothing to do here */
2870 			zfs_close(h);
2871 			continue;
2872 		}
2873 
2874 		logstr = hdl->libzfs_log_str;
2875 		hdl->libzfs_log_str = NULL;
2876 		if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
2877 		    NULL) != 0) {
2878 			hdl->libzfs_log_str = logstr;
2879 			opname = dgettext(TEXT_DOMAIN, "create");
2880 			goto ancestorerr;
2881 		}
2882 
2883 		hdl->libzfs_log_str = logstr;
2884 		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2885 		if (h == NULL) {
2886 			opname = dgettext(TEXT_DOMAIN, "open");
2887 			goto ancestorerr;
2888 		}
2889 
2890 		if (zfs_mount(h, NULL, 0) != 0) {
2891 			opname = dgettext(TEXT_DOMAIN, "mount");
2892 			goto ancestorerr;
2893 		}
2894 
2895 		if (zfs_share(h) != 0) {
2896 			opname = dgettext(TEXT_DOMAIN, "share");
2897 			goto ancestorerr;
2898 		}
2899 
2900 		zfs_close(h);
2901 	}
2902 
2903 	return (0);
2904 
2905 ancestorerr:
2906 	zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2907 	    "failed to %s ancestor '%s'"), opname, target);
2908 	return (-1);
2909 }
2910 
2911 /*
2912  * Creates non-existing ancestors of the given path.
2913  */
2914 int
2915 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
2916 {
2917 	int prefix;
2918 	char *path_copy;
2919 	int rc;
2920 
2921 	if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
2922 		return (-1);
2923 
2924 	if ((path_copy = strdup(path)) != NULL) {
2925 		rc = create_parents(hdl, path_copy, prefix);
2926 		free(path_copy);
2927 	}
2928 	if (path_copy == NULL || rc != 0)
2929 		return (-1);
2930 
2931 	return (0);
2932 }
2933 
2934 /*
2935  * Create a new filesystem or volume.
2936  */
2937 int
2938 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
2939     nvlist_t *props)
2940 {
2941 	zfs_cmd_t zc = { 0 };
2942 	int ret;
2943 	uint64_t size = 0;
2944 	uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
2945 	char errbuf[1024];
2946 	uint64_t zoned;
2947 
2948 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2949 	    "cannot create '%s'"), path);
2950 
2951 	/* validate the path, taking care to note the extended error message */
2952 	if (!zfs_validate_name(hdl, path, type, B_TRUE))
2953 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2954 
2955 	/* validate parents exist */
2956 	if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
2957 		return (-1);
2958 
2959 	/*
2960 	 * The failure modes when creating a dataset of a different type over
2961 	 * one that already exists is a little strange.  In particular, if you
2962 	 * try to create a dataset on top of an existing dataset, the ioctl()
2963 	 * will return ENOENT, not EEXIST.  To prevent this from happening, we
2964 	 * first try to see if the dataset exists.
2965 	 */
2966 	(void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name));
2967 	if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
2968 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2969 		    "dataset already exists"));
2970 		return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2971 	}
2972 
2973 	if (type == ZFS_TYPE_VOLUME)
2974 		zc.zc_objset_type = DMU_OST_ZVOL;
2975 	else
2976 		zc.zc_objset_type = DMU_OST_ZFS;
2977 
2978 	if (props && (props = zfs_valid_proplist(hdl, type, props,
2979 	    zoned, NULL, errbuf)) == 0)
2980 		return (-1);
2981 
2982 	if (type == ZFS_TYPE_VOLUME) {
2983 		/*
2984 		 * If we are creating a volume, the size and block size must
2985 		 * satisfy a few restraints.  First, the blocksize must be a
2986 		 * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
2987 		 * volsize must be a multiple of the block size, and cannot be
2988 		 * zero.
2989 		 */
2990 		if (props == NULL || nvlist_lookup_uint64(props,
2991 		    zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
2992 			nvlist_free(props);
2993 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2994 			    "missing volume size"));
2995 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2996 		}
2997 
2998 		if ((ret = nvlist_lookup_uint64(props,
2999 		    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3000 		    &blocksize)) != 0) {
3001 			if (ret == ENOENT) {
3002 				blocksize = zfs_prop_default_numeric(
3003 				    ZFS_PROP_VOLBLOCKSIZE);
3004 			} else {
3005 				nvlist_free(props);
3006 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3007 				    "missing volume block size"));
3008 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3009 			}
3010 		}
3011 
3012 		if (size == 0) {
3013 			nvlist_free(props);
3014 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3015 			    "volume size cannot be zero"));
3016 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3017 		}
3018 
3019 		if (size % blocksize != 0) {
3020 			nvlist_free(props);
3021 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3022 			    "volume size must be a multiple of volume block "
3023 			    "size"));
3024 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3025 		}
3026 	}
3027 
3028 	if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0)
3029 		return (-1);
3030 	nvlist_free(props);
3031 
3032 	/* create the dataset */
3033 	ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc);
3034 
3035 	zcmd_free_nvlists(&zc);
3036 
3037 	/* check for failure */
3038 	if (ret != 0) {
3039 		char parent[ZFS_MAXNAMELEN];
3040 		(void) parent_name(path, parent, sizeof (parent));
3041 
3042 		switch (errno) {
3043 		case ENOENT:
3044 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3045 			    "no such parent '%s'"), parent);
3046 			return (zfs_error(hdl, EZFS_NOENT, errbuf));
3047 
3048 		case EINVAL:
3049 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3050 			    "parent '%s' is not a filesystem"), parent);
3051 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3052 
3053 		case EDOM:
3054 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3055 			    "volume block size must be power of 2 from "
3056 			    "%u to %uk"),
3057 			    (uint_t)SPA_MINBLOCKSIZE,
3058 			    (uint_t)SPA_MAXBLOCKSIZE >> 10);
3059 
3060 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3061 
3062 		case ENOTSUP:
3063 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3064 			    "pool must be upgraded to set this "
3065 			    "property or value"));
3066 			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
3067 #ifdef _ILP32
3068 		case EOVERFLOW:
3069 			/*
3070 			 * This platform can't address a volume this big.
3071 			 */
3072 			if (type == ZFS_TYPE_VOLUME)
3073 				return (zfs_error(hdl, EZFS_VOLTOOBIG,
3074 				    errbuf));
3075 #endif
3076 			/* FALLTHROUGH */
3077 		default:
3078 			return (zfs_standard_error(hdl, errno, errbuf));
3079 		}
3080 	}
3081 
3082 	return (0);
3083 }
3084 
3085 /*
3086  * Destroys the given dataset.  The caller must make sure that the filesystem
3087  * isn't mounted, and that there are no active dependents.
3088  */
3089 int
3090 zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
3091 {
3092 	zfs_cmd_t zc = { 0 };
3093 
3094 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3095 
3096 	if (ZFS_IS_VOLUME(zhp)) {
3097 		zc.zc_objset_type = DMU_OST_ZVOL;
3098 	} else {
3099 		zc.zc_objset_type = DMU_OST_ZFS;
3100 	}
3101 
3102 	zc.zc_defer_destroy = defer;
3103 	if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) {
3104 		return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3105 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3106 		    zhp->zfs_name));
3107 	}
3108 
3109 	remove_mountpoint(zhp);
3110 
3111 	return (0);
3112 }
3113 
3114 struct destroydata {
3115 	nvlist_t *nvl;
3116 	const char *snapname;
3117 };
3118 
3119 static int
3120 zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
3121 {
3122 	struct destroydata *dd = arg;
3123 	zfs_handle_t *szhp;
3124 	char name[ZFS_MAXNAMELEN];
3125 	int rv = 0;
3126 
3127 	(void) snprintf(name, sizeof (name),
3128 	    "%s@%s", zhp->zfs_name, dd->snapname);
3129 
3130 	szhp = make_dataset_handle(zhp->zfs_hdl, name);
3131 	if (szhp) {
3132 		verify(nvlist_add_boolean(dd->nvl, name) == 0);
3133 		zfs_close(szhp);
3134 	}
3135 
3136 	rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
3137 	zfs_close(zhp);
3138 	return (rv);
3139 }
3140 
3141 /*
3142  * Destroys all snapshots with the given name in zhp & descendants.
3143  */
3144 int
3145 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
3146 {
3147 	int ret;
3148 	struct destroydata dd = { 0 };
3149 
3150 	dd.snapname = snapname;
3151 	verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
3152 	(void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
3153 
3154 	if (nvlist_next_nvpair(dd.nvl, NULL) == NULL) {
3155 		ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3156 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3157 		    zhp->zfs_name, snapname);
3158 	} else {
3159 		ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer);
3160 	}
3161 	nvlist_free(dd.nvl);
3162 	return (ret);
3163 }
3164 
3165 /*
3166  * Destroys all the snapshots named in the nvlist.  They must be underneath
3167  * the zhp (either snapshots of it, or snapshots of its descendants).
3168  */
3169 int
3170 zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
3171 {
3172 	int ret;
3173 	zfs_cmd_t zc = { 0 };
3174 
3175 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3176 	if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, snaps) != 0)
3177 		return (-1);
3178 	zc.zc_defer_destroy = defer;
3179 
3180 	ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS_NVL, &zc);
3181 	if (ret != 0) {
3182 		char errbuf[1024];
3183 
3184 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3185 		    "cannot destroy snapshots in %s"), zc.zc_name);
3186 
3187 		switch (errno) {
3188 		case EEXIST:
3189 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3190 			    "snapshot is cloned"));
3191 			return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf));
3192 
3193 		default:
3194 			return (zfs_standard_error(zhp->zfs_hdl, errno,
3195 			    errbuf));
3196 		}
3197 	}
3198 
3199 	return (0);
3200 }
3201 
3202 /*
3203  * Clones the given dataset.  The target must be of the same type as the source.
3204  */
3205 int
3206 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3207 {
3208 	zfs_cmd_t zc = { 0 };
3209 	char parent[ZFS_MAXNAMELEN];
3210 	int ret;
3211 	char errbuf[1024];
3212 	libzfs_handle_t *hdl = zhp->zfs_hdl;
3213 	zfs_type_t type;
3214 	uint64_t zoned;
3215 
3216 	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3217 
3218 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3219 	    "cannot create '%s'"), target);
3220 
3221 	/* validate the target/clone name */
3222 	if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3223 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3224 
3225 	/* validate parents exist */
3226 	if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3227 		return (-1);
3228 
3229 	(void) parent_name(target, parent, sizeof (parent));
3230 
3231 	/* do the clone */
3232 	if (ZFS_IS_VOLUME(zhp)) {
3233 		zc.zc_objset_type = DMU_OST_ZVOL;
3234 		type = ZFS_TYPE_VOLUME;
3235 	} else {
3236 		zc.zc_objset_type = DMU_OST_ZFS;
3237 		type = ZFS_TYPE_FILESYSTEM;
3238 	}
3239 
3240 	if (props) {
3241 		if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3242 		    zhp, errbuf)) == NULL)
3243 			return (-1);
3244 
3245 		if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
3246 			nvlist_free(props);
3247 			return (-1);
3248 		}
3249 
3250 		nvlist_free(props);
3251 	}
3252 
3253 	(void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
3254 	(void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
3255 	ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_CREATE, &zc);
3256 
3257 	zcmd_free_nvlists(&zc);
3258 
3259 	if (ret != 0) {
3260 		switch (errno) {
3261 
3262 		case ENOENT:
3263 			/*
3264 			 * The parent doesn't exist.  We should have caught this
3265 			 * above, but there may a race condition that has since
3266 			 * destroyed the parent.
3267 			 *
3268 			 * At this point, we don't know whether it's the source
3269 			 * that doesn't exist anymore, or whether the target
3270 			 * dataset doesn't exist.
3271 			 */
3272 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3273 			    "no such parent '%s'"), parent);
3274 			return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3275 
3276 		case EXDEV:
3277 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3278 			    "source and target pools differ"));
3279 			return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
3280 			    errbuf));
3281 
3282 		default:
3283 			return (zfs_standard_error(zhp->zfs_hdl, errno,
3284 			    errbuf));
3285 		}
3286 	}
3287 
3288 	return (ret);
3289 }
3290 
3291 /*
3292  * Promotes the given clone fs to be the clone parent.
3293  */
3294 int
3295 zfs_promote(zfs_handle_t *zhp)
3296 {
3297 	libzfs_handle_t *hdl = zhp->zfs_hdl;
3298 	zfs_cmd_t zc = { 0 };
3299 	char parent[MAXPATHLEN];
3300 	int ret;
3301 	char errbuf[1024];
3302 
3303 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3304 	    "cannot promote '%s'"), zhp->zfs_name);
3305 
3306 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3307 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3308 		    "snapshots can not be promoted"));
3309 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3310 	}
3311 
3312 	(void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent));
3313 	if (parent[0] == '\0') {
3314 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3315 		    "not a cloned filesystem"));
3316 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3317 	}
3318 
3319 	(void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin,
3320 	    sizeof (zc.zc_value));
3321 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3322 	ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
3323 
3324 	if (ret != 0) {
3325 		int save_errno = errno;
3326 
3327 		switch (save_errno) {
3328 		case EEXIST:
3329 			/* There is a conflicting snapshot name. */
3330 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3331 			    "conflicting snapshot '%s' from parent '%s'"),
3332 			    zc.zc_string, parent);
3333 			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3334 
3335 		default:
3336 			return (zfs_standard_error(hdl, save_errno, errbuf));
3337 		}
3338 	}
3339 	return (ret);
3340 }
3341 
3342 /*
3343  * Takes a snapshot of the given dataset.
3344  */
3345 int
3346 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3347     nvlist_t *props)
3348 {
3349 	const char *delim;
3350 	char parent[ZFS_MAXNAMELEN];
3351 	zfs_handle_t *zhp;
3352 	zfs_cmd_t zc = { 0 };
3353 	int ret;
3354 	char errbuf[1024];
3355 
3356 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3357 	    "cannot snapshot '%s'"), path);
3358 
3359 	/* validate the target name */
3360 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
3361 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3362 
3363 	if (props) {
3364 		if ((props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3365 		    props, B_FALSE, NULL, errbuf)) == NULL)
3366 			return (-1);
3367 
3368 		if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
3369 			nvlist_free(props);
3370 			return (-1);
3371 		}
3372 
3373 		nvlist_free(props);
3374 	}
3375 
3376 	/* make sure the parent exists and is of the appropriate type */
3377 	delim = strchr(path, '@');
3378 	(void) strncpy(parent, path, delim - path);
3379 	parent[delim - path] = '\0';
3380 
3381 	if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM |
3382 	    ZFS_TYPE_VOLUME)) == NULL) {
3383 		zcmd_free_nvlists(&zc);
3384 		return (-1);
3385 	}
3386 
3387 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3388 	(void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value));
3389 	if (ZFS_IS_VOLUME(zhp))
3390 		zc.zc_objset_type = DMU_OST_ZVOL;
3391 	else
3392 		zc.zc_objset_type = DMU_OST_ZFS;
3393 	zc.zc_cookie = recursive;
3394 	ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SNAPSHOT, &zc);
3395 
3396 	zcmd_free_nvlists(&zc);
3397 
3398 	/*
3399 	 * if it was recursive, the one that actually failed will be in
3400 	 * zc.zc_name.
3401 	 */
3402 	if (ret != 0) {
3403 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3404 		    "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value);
3405 		(void) zfs_standard_error(hdl, errno, errbuf);
3406 	}
3407 
3408 	zfs_close(zhp);
3409 
3410 	return (ret);
3411 }
3412 
3413 /*
3414  * Destroy any more recent snapshots.  We invoke this callback on any dependents
3415  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3416  * is a dependent and we should just destroy it without checking the transaction
3417  * group.
3418  */
3419 typedef struct rollback_data {
3420 	const char	*cb_target;		/* the snapshot */
3421 	uint64_t	cb_create;		/* creation time reference */
3422 	boolean_t	cb_error;
3423 	boolean_t	cb_dependent;
3424 	boolean_t	cb_force;
3425 } rollback_data_t;
3426 
3427 static int
3428 rollback_destroy(zfs_handle_t *zhp, void *data)
3429 {
3430 	rollback_data_t *cbp = data;
3431 
3432 	if (!cbp->cb_dependent) {
3433 		if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
3434 		    zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
3435 		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
3436 		    cbp->cb_create) {
3437 			char *logstr;
3438 
3439 			cbp->cb_dependent = B_TRUE;
3440 			cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3441 			    rollback_destroy, cbp);
3442 			cbp->cb_dependent = B_FALSE;
3443 
3444 			logstr = zhp->zfs_hdl->libzfs_log_str;
3445 			zhp->zfs_hdl->libzfs_log_str = NULL;
3446 			cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3447 			zhp->zfs_hdl->libzfs_log_str = logstr;
3448 		}
3449 	} else {
3450 		/* We must destroy this clone; first unmount it */
3451 		prop_changelist_t *clp;
3452 
3453 		clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3454 		    cbp->cb_force ? MS_FORCE: 0);
3455 		if (clp == NULL || changelist_prefix(clp) != 0) {
3456 			cbp->cb_error = B_TRUE;
3457 			zfs_close(zhp);
3458 			return (0);
3459 		}
3460 		if (zfs_destroy(zhp, B_FALSE) != 0)
3461 			cbp->cb_error = B_TRUE;
3462 		else
3463 			changelist_remove(clp, zhp->zfs_name);
3464 		(void) changelist_postfix(clp);
3465 		changelist_free(clp);
3466 	}
3467 
3468 	zfs_close(zhp);
3469 	return (0);
3470 }
3471 
3472 /*
3473  * Given a dataset, rollback to a specific snapshot, discarding any
3474  * data changes since then and making it the active dataset.
3475  *
3476  * Any snapshots more recent than the target are destroyed, along with
3477  * their dependents.
3478  */
3479 int
3480 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3481 {
3482 	rollback_data_t cb = { 0 };
3483 	int err;
3484 	zfs_cmd_t zc = { 0 };
3485 	boolean_t restore_resv = 0;
3486 	uint64_t old_volsize, new_volsize;
3487 	zfs_prop_t resv_prop;
3488 
3489 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3490 	    zhp->zfs_type == ZFS_TYPE_VOLUME);
3491 
3492 	/*
3493 	 * Destroy all recent snapshots and its dependends.
3494 	 */
3495 	cb.cb_force = force;
3496 	cb.cb_target = snap->zfs_name;
3497 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3498 	(void) zfs_iter_children(zhp, rollback_destroy, &cb);
3499 
3500 	if (cb.cb_error)
3501 		return (-1);
3502 
3503 	/*
3504 	 * Now that we have verified that the snapshot is the latest,
3505 	 * rollback to the given snapshot.
3506 	 */
3507 
3508 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
3509 		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
3510 			return (-1);
3511 		old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3512 		restore_resv =
3513 		    (old_volsize == zfs_prop_get_int(zhp, resv_prop));
3514 	}
3515 
3516 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3517 
3518 	if (ZFS_IS_VOLUME(zhp))
3519 		zc.zc_objset_type = DMU_OST_ZVOL;
3520 	else
3521 		zc.zc_objset_type = DMU_OST_ZFS;
3522 
3523 	/*
3524 	 * We rely on zfs_iter_children() to verify that there are no
3525 	 * newer snapshots for the given dataset.  Therefore, we can
3526 	 * simply pass the name on to the ioctl() call.  There is still
3527 	 * an unlikely race condition where the user has taken a
3528 	 * snapshot since we verified that this was the most recent.
3529 	 *
3530 	 */
3531 	if ((err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) {
3532 		(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3533 		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
3534 		    zhp->zfs_name);
3535 		return (err);
3536 	}
3537 
3538 	/*
3539 	 * For volumes, if the pre-rollback volsize matched the pre-
3540 	 * rollback reservation and the volsize has changed then set
3541 	 * the reservation property to the post-rollback volsize.
3542 	 * Make a new handle since the rollback closed the dataset.
3543 	 */
3544 	if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3545 	    (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3546 		if (restore_resv) {
3547 			new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3548 			if (old_volsize != new_volsize)
3549 				err = zfs_prop_set_int(zhp, resv_prop,
3550 				    new_volsize);
3551 		}
3552 		zfs_close(zhp);
3553 	}
3554 	return (err);
3555 }
3556 
3557 /*
3558  * Renames the given dataset.
3559  */
3560 int
3561 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
3562     boolean_t force_unmount)
3563 {
3564 	int ret;
3565 	zfs_cmd_t zc = { 0 };
3566 	char *delim;
3567 	prop_changelist_t *cl = NULL;
3568 	zfs_handle_t *zhrp = NULL;
3569 	char *parentname = NULL;
3570 	char parent[ZFS_MAXNAMELEN];
3571 	libzfs_handle_t *hdl = zhp->zfs_hdl;
3572 	char errbuf[1024];
3573 
3574 	/* if we have the same exact name, just return success */
3575 	if (strcmp(zhp->zfs_name, target) == 0)
3576 		return (0);
3577 
3578 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3579 	    "cannot rename to '%s'"), target);
3580 
3581 	/*
3582 	 * Make sure the target name is valid
3583 	 */
3584 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3585 		if ((strchr(target, '@') == NULL) ||
3586 		    *target == '@') {
3587 			/*
3588 			 * Snapshot target name is abbreviated,
3589 			 * reconstruct full dataset name
3590 			 */
3591 			(void) strlcpy(parent, zhp->zfs_name,
3592 			    sizeof (parent));
3593 			delim = strchr(parent, '@');
3594 			if (strchr(target, '@') == NULL)
3595 				*(++delim) = '\0';
3596 			else
3597 				*delim = '\0';
3598 			(void) strlcat(parent, target, sizeof (parent));
3599 			target = parent;
3600 		} else {
3601 			/*
3602 			 * Make sure we're renaming within the same dataset.
3603 			 */
3604 			delim = strchr(target, '@');
3605 			if (strncmp(zhp->zfs_name, target, delim - target)
3606 			    != 0 || zhp->zfs_name[delim - target] != '@') {
3607 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3608 				    "snapshots must be part of same "
3609 				    "dataset"));
3610 				return (zfs_error(hdl, EZFS_CROSSTARGET,
3611 				    errbuf));
3612 			}
3613 		}
3614 		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3615 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3616 	} else {
3617 		if (recursive) {
3618 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3619 			    "recursive rename must be a snapshot"));
3620 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3621 		}
3622 
3623 		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3624 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3625 
3626 		/* validate parents */
3627 		if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0)
3628 			return (-1);
3629 
3630 		/* make sure we're in the same pool */
3631 		verify((delim = strchr(target, '/')) != NULL);
3632 		if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
3633 		    zhp->zfs_name[delim - target] != '/') {
3634 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3635 			    "datasets must be within same pool"));
3636 			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
3637 		}
3638 
3639 		/* new name cannot be a child of the current dataset name */
3640 		if (is_descendant(zhp->zfs_name, target)) {
3641 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3642 			    "New dataset name cannot be a descendant of "
3643 			    "current dataset name"));
3644 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3645 		}
3646 	}
3647 
3648 	(void) snprintf(errbuf, sizeof (errbuf),
3649 	    dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
3650 
3651 	if (getzoneid() == GLOBAL_ZONEID &&
3652 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
3653 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3654 		    "dataset is used in a non-global zone"));
3655 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
3656 	}
3657 
3658 	if (recursive) {
3659 
3660 		parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
3661 		if (parentname == NULL) {
3662 			ret = -1;
3663 			goto error;
3664 		}
3665 		delim = strchr(parentname, '@');
3666 		*delim = '\0';
3667 		zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
3668 		if (zhrp == NULL) {
3669 			ret = -1;
3670 			goto error;
3671 		}
3672 
3673 	} else {
3674 		if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3675 		    force_unmount ? MS_FORCE : 0)) == NULL)
3676 			return (-1);
3677 
3678 		if (changelist_haszonedchild(cl)) {
3679 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3680 			    "child dataset with inherited mountpoint is used "
3681 			    "in a non-global zone"));
3682 			(void) zfs_error(hdl, EZFS_ZONED, errbuf);
3683 			goto error;
3684 		}
3685 
3686 		if ((ret = changelist_prefix(cl)) != 0)
3687 			goto error;
3688 	}
3689 
3690 	if (ZFS_IS_VOLUME(zhp))
3691 		zc.zc_objset_type = DMU_OST_ZVOL;
3692 	else
3693 		zc.zc_objset_type = DMU_OST_ZFS;
3694 
3695 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3696 	(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
3697 
3698 	zc.zc_cookie = recursive;
3699 
3700 	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
3701 		/*
3702 		 * if it was recursive, the one that actually failed will
3703 		 * be in zc.zc_name
3704 		 */
3705 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3706 		    "cannot rename '%s'"), zc.zc_name);
3707 
3708 		if (recursive && errno == EEXIST) {
3709 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3710 			    "a child dataset already has a snapshot "
3711 			    "with the new name"));
3712 			(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3713 		} else {
3714 			(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
3715 		}
3716 
3717 		/*
3718 		 * On failure, we still want to remount any filesystems that
3719 		 * were previously mounted, so we don't alter the system state.
3720 		 */
3721 		if (!recursive)
3722 			(void) changelist_postfix(cl);
3723 	} else {
3724 		if (!recursive) {
3725 			changelist_rename(cl, zfs_get_name(zhp), target);
3726 			ret = changelist_postfix(cl);
3727 		}
3728 	}
3729 
3730 error:
3731 	if (parentname) {
3732 		free(parentname);
3733 	}
3734 	if (zhrp) {
3735 		zfs_close(zhrp);
3736 	}
3737 	if (cl) {
3738 		changelist_free(cl);
3739 	}
3740 	return (ret);
3741 }
3742 
3743 nvlist_t *
3744 zfs_get_user_props(zfs_handle_t *zhp)
3745 {
3746 	return (zhp->zfs_user_props);
3747 }
3748 
3749 nvlist_t *
3750 zfs_get_recvd_props(zfs_handle_t *zhp)
3751 {
3752 	if (zhp->zfs_recvd_props == NULL)
3753 		if (get_recvd_props_ioctl(zhp) != 0)
3754 			return (NULL);
3755 	return (zhp->zfs_recvd_props);
3756 }
3757 
3758 /*
3759  * This function is used by 'zfs list' to determine the exact set of columns to
3760  * display, and their maximum widths.  This does two main things:
3761  *
3762  *      - If this is a list of all properties, then expand the list to include
3763  *        all native properties, and set a flag so that for each dataset we look
3764  *        for new unique user properties and add them to the list.
3765  *
3766  *      - For non fixed-width properties, keep track of the maximum width seen
3767  *        so that we can size the column appropriately. If the user has
3768  *        requested received property values, we also need to compute the width
3769  *        of the RECEIVED column.
3770  */
3771 int
3772 zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
3773 {
3774 	libzfs_handle_t *hdl = zhp->zfs_hdl;
3775 	zprop_list_t *entry;
3776 	zprop_list_t **last, **start;
3777 	nvlist_t *userprops, *propval;
3778 	nvpair_t *elem;
3779 	char *strval;
3780 	char buf[ZFS_MAXPROPLEN];
3781 
3782 	if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
3783 		return (-1);
3784 
3785 	userprops = zfs_get_user_props(zhp);
3786 
3787 	entry = *plp;
3788 	if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
3789 		/*
3790 		 * Go through and add any user properties as necessary.  We
3791 		 * start by incrementing our list pointer to the first
3792 		 * non-native property.
3793 		 */
3794 		start = plp;
3795 		while (*start != NULL) {
3796 			if ((*start)->pl_prop == ZPROP_INVAL)
3797 				break;
3798 			start = &(*start)->pl_next;
3799 		}
3800 
3801 		elem = NULL;
3802 		while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
3803 			/*
3804 			 * See if we've already found this property in our list.
3805 			 */
3806 			for (last = start; *last != NULL;
3807 			    last = &(*last)->pl_next) {
3808 				if (strcmp((*last)->pl_user_prop,
3809 				    nvpair_name(elem)) == 0)
3810 					break;
3811 			}
3812 
3813 			if (*last == NULL) {
3814 				if ((entry = zfs_alloc(hdl,
3815 				    sizeof (zprop_list_t))) == NULL ||
3816 				    ((entry->pl_user_prop = zfs_strdup(hdl,
3817 				    nvpair_name(elem)))) == NULL) {
3818 					free(entry);
3819 					return (-1);
3820 				}
3821 
3822 				entry->pl_prop = ZPROP_INVAL;
3823 				entry->pl_width = strlen(nvpair_name(elem));
3824 				entry->pl_all = B_TRUE;
3825 				*last = entry;
3826 			}
3827 		}
3828 	}
3829 
3830 	/*
3831 	 * Now go through and check the width of any non-fixed columns
3832 	 */
3833 	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
3834 		if (entry->pl_fixed)
3835 			continue;
3836 
3837 		if (entry->pl_prop != ZPROP_INVAL) {
3838 			if (zfs_prop_get(zhp, entry->pl_prop,
3839 			    buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) {
3840 				if (strlen(buf) > entry->pl_width)
3841 					entry->pl_width = strlen(buf);
3842 			}
3843 			if (received && zfs_prop_get_recvd(zhp,
3844 			    zfs_prop_to_name(entry->pl_prop),
3845 			    buf, sizeof (buf), B_FALSE) == 0)
3846 				if (strlen(buf) > entry->pl_recvd_width)
3847 					entry->pl_recvd_width = strlen(buf);
3848 		} else {
3849 			if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop,
3850 			    &propval) == 0) {
3851 				verify(nvlist_lookup_string(propval,
3852 				    ZPROP_VALUE, &strval) == 0);
3853 				if (strlen(strval) > entry->pl_width)
3854 					entry->pl_width = strlen(strval);
3855 			}
3856 			if (received && zfs_prop_get_recvd(zhp,
3857 			    entry->pl_user_prop,
3858 			    buf, sizeof (buf), B_FALSE) == 0)
3859 				if (strlen(buf) > entry->pl_recvd_width)
3860 					entry->pl_recvd_width = strlen(buf);
3861 		}
3862 	}
3863 
3864 	return (0);
3865 }
3866 
3867 int
3868 zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
3869     char *resource, void *export, void *sharetab,
3870     int sharemax, zfs_share_op_t operation)
3871 {
3872 	zfs_cmd_t zc = { 0 };
3873 	int error;
3874 
3875 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3876 	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
3877 	if (resource)
3878 		(void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
3879 	zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
3880 	zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
3881 	zc.zc_share.z_sharetype = operation;
3882 	zc.zc_share.z_sharemax = sharemax;
3883 	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
3884 	return (error);
3885 }
3886 
3887 void
3888 zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
3889 {
3890 	nvpair_t *curr;
3891 
3892 	/*
3893 	 * Keep a reference to the props-table against which we prune the
3894 	 * properties.
3895 	 */
3896 	zhp->zfs_props_table = props;
3897 
3898 	curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
3899 
3900 	while (curr) {
3901 		zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
3902 		nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
3903 
3904 		/*
3905 		 * User properties will result in ZPROP_INVAL, and since we
3906 		 * only know how to prune standard ZFS properties, we always
3907 		 * leave these in the list.  This can also happen if we
3908 		 * encounter an unknown DSL property (when running older
3909 		 * software, for example).
3910 		 */
3911 		if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
3912 			(void) nvlist_remove(zhp->zfs_props,
3913 			    nvpair_name(curr), nvpair_type(curr));
3914 		curr = next;
3915 	}
3916 }
3917 
3918 static int
3919 zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
3920     zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
3921 {
3922 	zfs_cmd_t zc = { 0 };
3923 	nvlist_t *nvlist = NULL;
3924 	int error;
3925 
3926 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3927 	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
3928 	zc.zc_cookie = (uint64_t)cmd;
3929 
3930 	if (cmd == ZFS_SMB_ACL_RENAME) {
3931 		if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
3932 			(void) no_memory(hdl);
3933 			return (NULL);
3934 		}
3935 	}
3936 
3937 	switch (cmd) {
3938 	case ZFS_SMB_ACL_ADD:
3939 	case ZFS_SMB_ACL_REMOVE:
3940 		(void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
3941 		break;
3942 	case ZFS_SMB_ACL_RENAME:
3943 		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
3944 		    resource1) != 0) {
3945 				(void) no_memory(hdl);
3946 				return (-1);
3947 		}
3948 		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
3949 		    resource2) != 0) {
3950 				(void) no_memory(hdl);
3951 				return (-1);
3952 		}
3953 		if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) {
3954 			nvlist_free(nvlist);
3955 			return (-1);
3956 		}
3957 		break;
3958 	case ZFS_SMB_ACL_PURGE:
3959 		break;
3960 	default:
3961 		return (-1);
3962 	}
3963 	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
3964 	if (nvlist)
3965 		nvlist_free(nvlist);
3966 	return (error);
3967 }
3968 
3969 int
3970 zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
3971     char *path, char *resource)
3972 {
3973 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
3974 	    resource, NULL));
3975 }
3976 
3977 int
3978 zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
3979     char *path, char *resource)
3980 {
3981 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
3982 	    resource, NULL));
3983 }
3984 
3985 int
3986 zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
3987 {
3988 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
3989 	    NULL, NULL));
3990 }
3991 
3992 int
3993 zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
3994     char *oldname, char *newname)
3995 {
3996 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
3997 	    oldname, newname));
3998 }
3999 
4000 int
4001 zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4002     zfs_userspace_cb_t func, void *arg)
4003 {
4004 	zfs_cmd_t zc = { 0 };
4005 	int error;
4006 	zfs_useracct_t buf[100];
4007 
4008 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4009 
4010 	zc.zc_objset_type = type;
4011 	zc.zc_nvlist_dst = (uintptr_t)buf;
4012 
4013 	/* CONSTCOND */
4014 	while (1) {
4015 		zfs_useracct_t *zua = buf;
4016 
4017 		zc.zc_nvlist_dst_size = sizeof (buf);
4018 		error = ioctl(zhp->zfs_hdl->libzfs_fd,
4019 		    ZFS_IOC_USERSPACE_MANY, &zc);
4020 		if (error || zc.zc_nvlist_dst_size == 0)
4021 			break;
4022 
4023 		while (zc.zc_nvlist_dst_size > 0) {
4024 			error = func(arg, zua->zu_domain, zua->zu_rid,
4025 			    zua->zu_space);
4026 			if (error != 0)
4027 				return (error);
4028 			zua++;
4029 			zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4030 		}
4031 	}
4032 
4033 	return (error);
4034 }
4035 
4036 int
4037 zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4038     boolean_t recursive, boolean_t temphold, boolean_t enoent_ok,
4039     int cleanup_fd, uint64_t dsobj, uint64_t createtxg)
4040 {
4041 	zfs_cmd_t zc = { 0 };
4042 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4043 
4044 	ASSERT(!recursive || dsobj == 0);
4045 
4046 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4047 	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
4048 	if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string))
4049 	    >= sizeof (zc.zc_string))
4050 		return (zfs_error(hdl, EZFS_TAGTOOLONG, tag));
4051 	zc.zc_cookie = recursive;
4052 	zc.zc_temphold = temphold;
4053 	zc.zc_cleanup_fd = cleanup_fd;
4054 	zc.zc_sendobj = dsobj;
4055 	zc.zc_createtxg = createtxg;
4056 
4057 	if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) {
4058 		char errbuf[ZFS_MAXNAMELEN+32];
4059 
4060 		/*
4061 		 * if it was recursive, the one that actually failed will be in
4062 		 * zc.zc_name.
4063 		 */
4064 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4065 		    "cannot hold '%s@%s'"), zc.zc_name, snapname);
4066 		switch (errno) {
4067 		case E2BIG:
4068 			/*
4069 			 * Temporary tags wind up having the ds object id
4070 			 * prepended. So even if we passed the length check
4071 			 * above, it's still possible for the tag to wind
4072 			 * up being slightly too long.
4073 			 */
4074 			return (zfs_error(hdl, EZFS_TAGTOOLONG, errbuf));
4075 		case ENOTSUP:
4076 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4077 			    "pool must be upgraded"));
4078 			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
4079 		case EINVAL:
4080 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4081 		case EEXIST:
4082 			return (zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf));
4083 		case ENOENT:
4084 			if (enoent_ok)
4085 				return (ENOENT);
4086 			/* FALLTHROUGH */
4087 		default:
4088 			return (zfs_standard_error_fmt(hdl, errno, errbuf));
4089 		}
4090 	}
4091 
4092 	return (0);
4093 }
4094 
4095 int
4096 zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
4097     boolean_t recursive)
4098 {
4099 	zfs_cmd_t zc = { 0 };
4100 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4101 
4102 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4103 	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
4104 	if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string))
4105 	    >= sizeof (zc.zc_string))
4106 		return (zfs_error(hdl, EZFS_TAGTOOLONG, tag));
4107 	zc.zc_cookie = recursive;
4108 
4109 	if (zfs_ioctl(hdl, ZFS_IOC_RELEASE, &zc) != 0) {
4110 		char errbuf[ZFS_MAXNAMELEN+32];
4111 
4112 		/*
4113 		 * if it was recursive, the one that actually failed will be in
4114 		 * zc.zc_name.
4115 		 */
4116 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4117 		    "cannot release '%s' from '%s@%s'"), tag, zc.zc_name,
4118 		    snapname);
4119 		switch (errno) {
4120 		case ESRCH:
4121 			return (zfs_error(hdl, EZFS_REFTAG_RELE, errbuf));
4122 		case ENOTSUP:
4123 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4124 			    "pool must be upgraded"));
4125 			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
4126 		case EINVAL:
4127 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4128 		default:
4129 			return (zfs_standard_error_fmt(hdl, errno, errbuf));
4130 		}
4131 	}
4132 
4133 	return (0);
4134 }
4135 
4136 int
4137 zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
4138 {
4139 	zfs_cmd_t zc = { 0 };
4140 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4141 	int nvsz = 2048;
4142 	void *nvbuf;
4143 	int err = 0;
4144 	char errbuf[ZFS_MAXNAMELEN+32];
4145 
4146 	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4147 	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4148 
4149 tryagain:
4150 
4151 	nvbuf = malloc(nvsz);
4152 	if (nvbuf == NULL) {
4153 		err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
4154 		goto out;
4155 	}
4156 
4157 	zc.zc_nvlist_dst_size = nvsz;
4158 	zc.zc_nvlist_dst = (uintptr_t)nvbuf;
4159 
4160 	(void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
4161 
4162 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
4163 		(void) snprintf(errbuf, sizeof (errbuf),
4164 		    dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
4165 		    zc.zc_name);
4166 		switch (errno) {
4167 		case ENOMEM:
4168 			free(nvbuf);
4169 			nvsz = zc.zc_nvlist_dst_size;
4170 			goto tryagain;
4171 
4172 		case ENOTSUP:
4173 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4174 			    "pool must be upgraded"));
4175 			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4176 			break;
4177 		case EINVAL:
4178 			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4179 			break;
4180 		case ENOENT:
4181 			err = zfs_error(hdl, EZFS_NOENT, errbuf);
4182 			break;
4183 		default:
4184 			err = zfs_standard_error_fmt(hdl, errno, errbuf);
4185 			break;
4186 		}
4187 	} else {
4188 		/* success */
4189 		int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
4190 		if (rc) {
4191 			(void) snprintf(errbuf, sizeof (errbuf), dgettext(
4192 			    TEXT_DOMAIN, "cannot get permissions on '%s'"),
4193 			    zc.zc_name);
4194 			err = zfs_standard_error_fmt(hdl, rc, errbuf);
4195 		}
4196 	}
4197 
4198 	free(nvbuf);
4199 out:
4200 	return (err);
4201 }
4202 
4203 int
4204 zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
4205 {
4206 	zfs_cmd_t zc = { 0 };
4207 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4208 	char *nvbuf;
4209 	char errbuf[ZFS_MAXNAMELEN+32];
4210 	size_t nvsz;
4211 	int err;
4212 
4213 	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4214 	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4215 
4216 	err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
4217 	assert(err == 0);
4218 
4219 	nvbuf = malloc(nvsz);
4220 
4221 	err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
4222 	assert(err == 0);
4223 
4224 	zc.zc_nvlist_src_size = nvsz;
4225 	zc.zc_nvlist_src = (uintptr_t)nvbuf;
4226 	zc.zc_perm_action = un;
4227 
4228 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4229 
4230 	if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
4231 		(void) snprintf(errbuf, sizeof (errbuf),
4232 		    dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
4233 		    zc.zc_name);
4234 		switch (errno) {
4235 		case ENOTSUP:
4236 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4237 			    "pool must be upgraded"));
4238 			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4239 			break;
4240 		case EINVAL:
4241 			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4242 			break;
4243 		case ENOENT:
4244 			err = zfs_error(hdl, EZFS_NOENT, errbuf);
4245 			break;
4246 		default:
4247 			err = zfs_standard_error_fmt(hdl, errno, errbuf);
4248 			break;
4249 		}
4250 	}
4251 
4252 	free(nvbuf);
4253 
4254 	return (err);
4255 }
4256 
4257 int
4258 zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
4259 {
4260 	zfs_cmd_t zc = { 0 };
4261 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4262 	int nvsz = 2048;
4263 	void *nvbuf;
4264 	int err = 0;
4265 	char errbuf[ZFS_MAXNAMELEN+32];
4266 
4267 	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
4268 
4269 tryagain:
4270 
4271 	nvbuf = malloc(nvsz);
4272 	if (nvbuf == NULL) {
4273 		err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
4274 		goto out;
4275 	}
4276 
4277 	zc.zc_nvlist_dst_size = nvsz;
4278 	zc.zc_nvlist_dst = (uintptr_t)nvbuf;
4279 
4280 	(void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
4281 
4282 	if (zfs_ioctl(hdl, ZFS_IOC_GET_HOLDS, &zc) != 0) {
4283 		(void) snprintf(errbuf, sizeof (errbuf),
4284 		    dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
4285 		    zc.zc_name);
4286 		switch (errno) {
4287 		case ENOMEM:
4288 			free(nvbuf);
4289 			nvsz = zc.zc_nvlist_dst_size;
4290 			goto tryagain;
4291 
4292 		case ENOTSUP:
4293 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4294 			    "pool must be upgraded"));
4295 			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4296 			break;
4297 		case EINVAL:
4298 			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4299 			break;
4300 		case ENOENT:
4301 			err = zfs_error(hdl, EZFS_NOENT, errbuf);
4302 			break;
4303 		default:
4304 			err = zfs_standard_error_fmt(hdl, errno, errbuf);
4305 			break;
4306 		}
4307 	} else {
4308 		/* success */
4309 		int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
4310 		if (rc) {
4311 			(void) snprintf(errbuf, sizeof (errbuf),
4312 			    dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
4313 			    zc.zc_name);
4314 			err = zfs_standard_error_fmt(hdl, rc, errbuf);
4315 		}
4316 	}
4317 
4318 	free(nvbuf);
4319 out:
4320 	return (err);
4321 }
4322 
4323 uint64_t
4324 zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
4325 {
4326 	uint64_t numdb;
4327 	uint64_t nblocks, volblocksize;
4328 	int ncopies;
4329 	char *strval;
4330 
4331 	if (nvlist_lookup_string(props,
4332 	    zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
4333 		ncopies = atoi(strval);
4334 	else
4335 		ncopies = 1;
4336 	if (nvlist_lookup_uint64(props,
4337 	    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
4338 	    &volblocksize) != 0)
4339 		volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
4340 	nblocks = volsize/volblocksize;
4341 	/* start with metadnode L0-L6 */
4342 	numdb = 7;
4343 	/* calculate number of indirects */
4344 	while (nblocks > 1) {
4345 		nblocks += DNODES_PER_LEVEL - 1;
4346 		nblocks /= DNODES_PER_LEVEL;
4347 		numdb += nblocks;
4348 	}
4349 	numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1);
4350 	volsize *= ncopies;
4351 	/*
4352 	 * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't
4353 	 * compressed, but in practice they compress down to about
4354 	 * 1100 bytes
4355 	 */
4356 	numdb *= 1ULL << DN_MAX_INDBLKSHIFT;
4357 	volsize += numdb;
4358 	return (volsize);
4359 }
4360