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 https://opensource.org/licenses/CDDL-1.0.
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 2019 Joyent, Inc.
25 * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
26 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
27 * Copyright (c) 2012 Pawel Jakub Dawidek <[email protected]>.
28 * Copyright (c) 2013 Martin Matuska. All rights reserved.
29 * Copyright (c) 2013 Steven Hartland. All rights reserved.
30 * Copyright 2017 Nexenta Systems, Inc.
31 * Copyright 2016 Igor Kozhukhov <[email protected]>
32 * Copyright 2017-2018 RackTop Systems.
33 * Copyright (c) 2019 Datto Inc.
34 * Copyright (c) 2019, loli10K <[email protected]>
35 * Copyright (c) 2021 Matt Fiddaman
36 */
37
38 #include <ctype.h>
39 #include <errno.h>
40 #include <libintl.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <strings.h>
44 #include <unistd.h>
45 #include <stddef.h>
46 #include <zone.h>
47 #include <fcntl.h>
48 #include <sys/mntent.h>
49 #include <sys/mount.h>
50 #include <pwd.h>
51 #include <grp.h>
52 #ifdef HAVE_IDMAP
53 #include <idmap.h>
54 #include <aclutils.h>
55 #include <directory.h>
56 #endif /* HAVE_IDMAP */
57
58 #include <sys/dnode.h>
59 #include <sys/spa.h>
60 #include <sys/zap.h>
61 #include <sys/dsl_crypt.h>
62 #include <libzfs.h>
63 #include <libzutil.h>
64
65 #include "zfs_namecheck.h"
66 #include "zfs_prop.h"
67 #include "libzfs_impl.h"
68 #include "zfs_deleg.h"
69
70 static int userquota_propname_decode(const char *propname, boolean_t zoned,
71 zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
72
73 /*
74 * Given a single type (not a mask of types), return the type in a human
75 * readable form.
76 */
77 const char *
zfs_type_to_name(zfs_type_t type)78 zfs_type_to_name(zfs_type_t type)
79 {
80 switch (type) {
81 case ZFS_TYPE_FILESYSTEM:
82 return (dgettext(TEXT_DOMAIN, "filesystem"));
83 case ZFS_TYPE_SNAPSHOT:
84 return (dgettext(TEXT_DOMAIN, "snapshot"));
85 case ZFS_TYPE_VOLUME:
86 return (dgettext(TEXT_DOMAIN, "volume"));
87 case ZFS_TYPE_POOL:
88 return (dgettext(TEXT_DOMAIN, "pool"));
89 case ZFS_TYPE_BOOKMARK:
90 return (dgettext(TEXT_DOMAIN, "bookmark"));
91 default:
92 assert(!"unhandled zfs_type_t");
93 }
94
95 return (NULL);
96 }
97
98 /*
99 * Validate a ZFS path. This is used even before trying to open the dataset, to
100 * provide a more meaningful error message. We call zfs_error_aux() to
101 * explain exactly why the name was not valid.
102 */
103 int
zfs_validate_name(libzfs_handle_t * hdl,const char * path,int type,boolean_t modifying)104 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
105 boolean_t modifying)
106 {
107 namecheck_err_t why;
108 char what;
109
110 if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
111 if (hdl != NULL)
112 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
113 "snapshot delimiter '@' is not expected here"));
114 return (0);
115 }
116
117 if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
118 if (hdl != NULL)
119 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
120 "missing '@' delimiter in snapshot name"));
121 return (0);
122 }
123
124 if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) {
125 if (hdl != NULL)
126 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
127 "bookmark delimiter '#' is not expected here"));
128 return (0);
129 }
130
131 if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) {
132 if (hdl != NULL)
133 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
134 "missing '#' delimiter in bookmark name"));
135 return (0);
136 }
137
138 if (modifying && strchr(path, '%') != NULL) {
139 if (hdl != NULL)
140 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
141 "invalid character %c in name"), '%');
142 return (0);
143 }
144
145 if (entity_namecheck(path, &why, &what) != 0) {
146 if (hdl != NULL) {
147 switch (why) {
148 case NAME_ERR_TOOLONG:
149 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
150 "name is too long"));
151 break;
152
153 case NAME_ERR_LEADING_SLASH:
154 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
155 "leading slash in name"));
156 break;
157
158 case NAME_ERR_EMPTY_COMPONENT:
159 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
160 "empty component or misplaced '@'"
161 " or '#' delimiter in name"));
162 break;
163
164 case NAME_ERR_TRAILING_SLASH:
165 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
166 "trailing slash in name"));
167 break;
168
169 case NAME_ERR_INVALCHAR:
170 zfs_error_aux(hdl,
171 dgettext(TEXT_DOMAIN, "invalid character "
172 "'%c' in name"), what);
173 break;
174
175 case NAME_ERR_MULTIPLE_DELIMITERS:
176 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
177 "multiple '@' and/or '#' delimiters in "
178 "name"));
179 break;
180
181 case NAME_ERR_NOLETTER:
182 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
183 "pool doesn't begin with a letter"));
184 break;
185
186 case NAME_ERR_RESERVED:
187 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
188 "name is reserved"));
189 break;
190
191 case NAME_ERR_DISKLIKE:
192 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
193 "reserved disk name"));
194 break;
195
196 case NAME_ERR_SELF_REF:
197 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
198 "self reference, '.' is found in name"));
199 break;
200
201 case NAME_ERR_PARENT_REF:
202 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
203 "parent reference, '..' is found in name"));
204 break;
205
206 default:
207 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
208 "(%d) not defined"), why);
209 break;
210 }
211 }
212
213 return (0);
214 }
215
216 return (-1);
217 }
218
219 int
zfs_name_valid(const char * name,zfs_type_t type)220 zfs_name_valid(const char *name, zfs_type_t type)
221 {
222 if (type == ZFS_TYPE_POOL)
223 return (zpool_name_valid(NULL, B_FALSE, name));
224 return (zfs_validate_name(NULL, name, type, B_FALSE));
225 }
226
227 /*
228 * This function takes the raw DSL properties, and filters out the user-defined
229 * properties into a separate nvlist.
230 */
231 static nvlist_t *
process_user_props(zfs_handle_t * zhp,nvlist_t * props)232 process_user_props(zfs_handle_t *zhp, nvlist_t *props)
233 {
234 libzfs_handle_t *hdl = zhp->zfs_hdl;
235 nvpair_t *elem;
236 nvlist_t *nvl;
237
238 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
239 (void) no_memory(hdl);
240 return (NULL);
241 }
242
243 elem = NULL;
244 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
245 if (!zfs_prop_user(nvpair_name(elem)))
246 continue;
247
248 nvlist_t *propval = fnvpair_value_nvlist(elem);
249 if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
250 nvlist_free(nvl);
251 (void) no_memory(hdl);
252 return (NULL);
253 }
254 }
255
256 return (nvl);
257 }
258
259 static zpool_handle_t *
zpool_add_handle(zfs_handle_t * zhp,const char * pool_name)260 zpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
261 {
262 libzfs_handle_t *hdl = zhp->zfs_hdl;
263 zpool_handle_t *zph;
264
265 if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
266 if (hdl->libzfs_pool_handles != NULL)
267 zph->zpool_next = hdl->libzfs_pool_handles;
268 hdl->libzfs_pool_handles = zph;
269 }
270 return (zph);
271 }
272
273 static zpool_handle_t *
zpool_find_handle(zfs_handle_t * zhp,const char * pool_name,int len)274 zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
275 {
276 libzfs_handle_t *hdl = zhp->zfs_hdl;
277 zpool_handle_t *zph = hdl->libzfs_pool_handles;
278
279 while ((zph != NULL) &&
280 (strncmp(pool_name, zpool_get_name(zph), len) != 0))
281 zph = zph->zpool_next;
282 return (zph);
283 }
284
285 /*
286 * Returns a handle to the pool that contains the provided dataset.
287 * If a handle to that pool already exists then that handle is returned.
288 * Otherwise, a new handle is created and added to the list of handles.
289 */
290 static zpool_handle_t *
zpool_handle(zfs_handle_t * zhp)291 zpool_handle(zfs_handle_t *zhp)
292 {
293 char *pool_name;
294 int len;
295 zpool_handle_t *zph;
296
297 len = strcspn(zhp->zfs_name, "/@#") + 1;
298 pool_name = zfs_alloc(zhp->zfs_hdl, len);
299 (void) strlcpy(pool_name, zhp->zfs_name, len);
300
301 zph = zpool_find_handle(zhp, pool_name, len);
302 if (zph == NULL)
303 zph = zpool_add_handle(zhp, pool_name);
304
305 free(pool_name);
306 return (zph);
307 }
308
309 void
zpool_free_handles(libzfs_handle_t * hdl)310 zpool_free_handles(libzfs_handle_t *hdl)
311 {
312 zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
313
314 while (zph != NULL) {
315 next = zph->zpool_next;
316 zpool_close(zph);
317 zph = next;
318 }
319 hdl->libzfs_pool_handles = NULL;
320 }
321
322 /*
323 * Utility function to gather stats (objset and zpl) for the given object.
324 */
325 static int
get_stats_ioctl(zfs_handle_t * zhp,zfs_cmd_t * zc)326 get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc)
327 {
328 libzfs_handle_t *hdl = zhp->zfs_hdl;
329
330 (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
331
332 while (zfs_ioctl(hdl, ZFS_IOC_OBJSET_STATS, zc) != 0) {
333 if (errno == ENOMEM)
334 zcmd_expand_dst_nvlist(hdl, zc);
335 else
336 return (-1);
337 }
338 return (0);
339 }
340
341 /*
342 * Utility function to get the received properties of the given object.
343 */
344 static int
get_recvd_props_ioctl(zfs_handle_t * zhp)345 get_recvd_props_ioctl(zfs_handle_t *zhp)
346 {
347 libzfs_handle_t *hdl = zhp->zfs_hdl;
348 nvlist_t *recvdprops;
349 zfs_cmd_t zc = {"\0"};
350 int err;
351
352 zcmd_alloc_dst_nvlist(hdl, &zc, 0);
353
354 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
355
356 while (zfs_ioctl(hdl, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) {
357 if (errno == ENOMEM)
358 zcmd_expand_dst_nvlist(hdl, &zc);
359 else {
360 zcmd_free_nvlists(&zc);
361 return (-1);
362 }
363 }
364
365 err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops);
366 zcmd_free_nvlists(&zc);
367 if (err != 0)
368 return (-1);
369
370 nvlist_free(zhp->zfs_recvd_props);
371 zhp->zfs_recvd_props = recvdprops;
372
373 return (0);
374 }
375
376 static int
put_stats_zhdl(zfs_handle_t * zhp,zfs_cmd_t * zc)377 put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc)
378 {
379 nvlist_t *allprops, *userprops;
380
381 zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */
382
383 if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
384 return (-1);
385 }
386
387 /*
388 * XXX Why do we store the user props separately, in addition to
389 * storing them in zfs_props?
390 */
391 if ((userprops = process_user_props(zhp, allprops)) == NULL) {
392 nvlist_free(allprops);
393 return (-1);
394 }
395
396 nvlist_free(zhp->zfs_props);
397 nvlist_free(zhp->zfs_user_props);
398
399 zhp->zfs_props = allprops;
400 zhp->zfs_user_props = userprops;
401
402 return (0);
403 }
404
405 static int
get_stats(zfs_handle_t * zhp)406 get_stats(zfs_handle_t *zhp)
407 {
408 int rc = 0;
409 zfs_cmd_t zc = {"\0"};
410
411 zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0);
412
413 if (get_stats_ioctl(zhp, &zc) != 0)
414 rc = -1;
415 else if (put_stats_zhdl(zhp, &zc) != 0)
416 rc = -1;
417 zcmd_free_nvlists(&zc);
418 return (rc);
419 }
420
421 /*
422 * Refresh the properties currently stored in the handle.
423 */
424 void
zfs_refresh_properties(zfs_handle_t * zhp)425 zfs_refresh_properties(zfs_handle_t *zhp)
426 {
427 (void) get_stats(zhp);
428 }
429
430 /*
431 * Makes a handle from the given dataset name. Used by zfs_open() and
432 * zfs_iter_* to create child handles on the fly.
433 */
434 static int
make_dataset_handle_common(zfs_handle_t * zhp,zfs_cmd_t * zc)435 make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
436 {
437 if (put_stats_zhdl(zhp, zc) != 0)
438 return (-1);
439
440 /*
441 * We've managed to open the dataset and gather statistics. Determine
442 * the high-level type.
443 */
444 if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) {
445 zhp->zfs_head_type = ZFS_TYPE_VOLUME;
446 } else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) {
447 zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
448 } else if (zhp->zfs_dmustats.dds_type == DMU_OST_OTHER) {
449 errno = EINVAL;
450 return (-1);
451 } else if (zhp->zfs_dmustats.dds_inconsistent) {
452 errno = EBUSY;
453 return (-1);
454 } else {
455 abort();
456 }
457
458 if (zhp->zfs_dmustats.dds_is_snapshot)
459 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
460 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
461 zhp->zfs_type = ZFS_TYPE_VOLUME;
462 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
463 zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
464 else
465 abort(); /* we should never see any other types */
466
467 if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL)
468 return (-1);
469
470 return (0);
471 }
472
473 zfs_handle_t *
make_dataset_handle(libzfs_handle_t * hdl,const char * path)474 make_dataset_handle(libzfs_handle_t *hdl, const char *path)
475 {
476 zfs_cmd_t zc = {"\0"};
477
478 zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));
479
480 if (zhp == NULL)
481 return (NULL);
482
483 zhp->zfs_hdl = hdl;
484 (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
485 zcmd_alloc_dst_nvlist(hdl, &zc, 0);
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 *
make_dataset_handle_zc(libzfs_handle_t * hdl,zfs_cmd_t * zc)501 make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
502 {
503 zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));
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 *
make_dataset_simple_handle_zc(zfs_handle_t * pzhp,zfs_cmd_t * zc)518 make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc)
519 {
520 zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));
521
522 if (zhp == NULL)
523 return (NULL);
524
525 zhp->zfs_hdl = pzhp->zfs_hdl;
526 (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
527 zhp->zfs_head_type = pzhp->zfs_type;
528 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
529 zhp->zpool_hdl = zpool_handle(zhp);
530
531 if (zc->zc_objset_stats.dds_creation_txg != 0) {
532 /* structure assignment */
533 zhp->zfs_dmustats = zc->zc_objset_stats;
534 } else {
535 if (get_stats_ioctl(zhp, zc) == -1) {
536 zcmd_free_nvlists(zc);
537 free(zhp);
538 return (NULL);
539 }
540 if (make_dataset_handle_common(zhp, zc) == -1) {
541 zcmd_free_nvlists(zc);
542 free(zhp);
543 return (NULL);
544 }
545 }
546
547 if (zhp->zfs_dmustats.dds_is_snapshot ||
548 strchr(zc->zc_name, '@') != NULL)
549 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
550 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
551 zhp->zfs_type = ZFS_TYPE_VOLUME;
552 else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
553 zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
554
555 return (zhp);
556 }
557
558 zfs_handle_t *
zfs_handle_dup(zfs_handle_t * zhp_orig)559 zfs_handle_dup(zfs_handle_t *zhp_orig)
560 {
561 zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));
562
563 if (zhp == NULL)
564 return (NULL);
565
566 zhp->zfs_hdl = zhp_orig->zfs_hdl;
567 zhp->zpool_hdl = zhp_orig->zpool_hdl;
568 (void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name,
569 sizeof (zhp->zfs_name));
570 zhp->zfs_type = zhp_orig->zfs_type;
571 zhp->zfs_head_type = zhp_orig->zfs_head_type;
572 zhp->zfs_dmustats = zhp_orig->zfs_dmustats;
573 if (zhp_orig->zfs_props != NULL) {
574 if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
575 (void) no_memory(zhp->zfs_hdl);
576 zfs_close(zhp);
577 return (NULL);
578 }
579 }
580 if (zhp_orig->zfs_user_props != NULL) {
581 if (nvlist_dup(zhp_orig->zfs_user_props,
582 &zhp->zfs_user_props, 0) != 0) {
583 (void) no_memory(zhp->zfs_hdl);
584 zfs_close(zhp);
585 return (NULL);
586 }
587 }
588 if (zhp_orig->zfs_recvd_props != NULL) {
589 if (nvlist_dup(zhp_orig->zfs_recvd_props,
590 &zhp->zfs_recvd_props, 0)) {
591 (void) no_memory(zhp->zfs_hdl);
592 zfs_close(zhp);
593 return (NULL);
594 }
595 }
596 zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck;
597 if (zhp_orig->zfs_mntopts != NULL) {
598 zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl,
599 zhp_orig->zfs_mntopts);
600 }
601 zhp->zfs_props_table = zhp_orig->zfs_props_table;
602 return (zhp);
603 }
604
605 boolean_t
zfs_bookmark_exists(const char * path)606 zfs_bookmark_exists(const char *path)
607 {
608 nvlist_t *bmarks;
609 nvlist_t *props;
610 char fsname[ZFS_MAX_DATASET_NAME_LEN];
611 char *bmark_name;
612 char *pound;
613 int err;
614 boolean_t rv;
615
616 (void) strlcpy(fsname, path, sizeof (fsname));
617 pound = strchr(fsname, '#');
618 if (pound == NULL)
619 return (B_FALSE);
620
621 *pound = '\0';
622 bmark_name = pound + 1;
623 props = fnvlist_alloc();
624 err = lzc_get_bookmarks(fsname, props, &bmarks);
625 nvlist_free(props);
626 if (err != 0) {
627 nvlist_free(bmarks);
628 return (B_FALSE);
629 }
630
631 rv = nvlist_exists(bmarks, bmark_name);
632 nvlist_free(bmarks);
633 return (rv);
634 }
635
636 zfs_handle_t *
make_bookmark_handle(zfs_handle_t * parent,const char * path,nvlist_t * bmark_props)637 make_bookmark_handle(zfs_handle_t *parent, const char *path,
638 nvlist_t *bmark_props)
639 {
640 zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));
641
642 if (zhp == NULL)
643 return (NULL);
644
645 /* Fill in the name. */
646 zhp->zfs_hdl = parent->zfs_hdl;
647 (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
648
649 /* Set the property lists. */
650 if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
651 free(zhp);
652 return (NULL);
653 }
654
655 /* Set the types. */
656 zhp->zfs_head_type = parent->zfs_head_type;
657 zhp->zfs_type = ZFS_TYPE_BOOKMARK;
658
659 if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) {
660 nvlist_free(zhp->zfs_props);
661 free(zhp);
662 return (NULL);
663 }
664
665 return (zhp);
666 }
667
668 struct zfs_open_bookmarks_cb_data {
669 const char *path;
670 zfs_handle_t *zhp;
671 };
672
673 static int
zfs_open_bookmarks_cb(zfs_handle_t * zhp,void * data)674 zfs_open_bookmarks_cb(zfs_handle_t *zhp, void *data)
675 {
676 struct zfs_open_bookmarks_cb_data *dp = data;
677
678 /*
679 * Is it the one we are looking for?
680 */
681 if (strcmp(dp->path, zfs_get_name(zhp)) == 0) {
682 /*
683 * We found it. Save it and let the caller know we are done.
684 */
685 dp->zhp = zhp;
686 return (EEXIST);
687 }
688
689 /*
690 * Not found. Close the handle and ask for another one.
691 */
692 zfs_close(zhp);
693 return (0);
694 }
695
696 /*
697 * Opens the given snapshot, bookmark, filesystem, or volume. The 'types'
698 * argument is a mask of acceptable types. The function will print an
699 * appropriate error message and return NULL if it can't be opened.
700 */
701 zfs_handle_t *
zfs_open(libzfs_handle_t * hdl,const char * path,int types)702 zfs_open(libzfs_handle_t *hdl, const char *path, int types)
703 {
704 zfs_handle_t *zhp;
705 char errbuf[ERRBUFLEN];
706 char *bookp;
707
708 (void) snprintf(errbuf, sizeof (errbuf),
709 dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
710
711 /*
712 * Validate the name before we even try to open it.
713 */
714 if (!zfs_validate_name(hdl, path, types, B_FALSE)) {
715 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
716 errno = EINVAL;
717 return (NULL);
718 }
719
720 /*
721 * Bookmarks needs to be handled separately.
722 */
723 bookp = strchr(path, '#');
724 if (bookp == NULL) {
725 /*
726 * Try to get stats for the dataset, which will tell us if it
727 * exists.
728 */
729 errno = 0;
730 if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
731 (void) zfs_standard_error(hdl, errno, errbuf);
732 return (NULL);
733 }
734 } else {
735 char dsname[ZFS_MAX_DATASET_NAME_LEN];
736 zfs_handle_t *pzhp;
737 struct zfs_open_bookmarks_cb_data cb_data = {path, NULL};
738
739 /*
740 * We need to cut out '#' and everything after '#'
741 * to get the parent dataset name only.
742 */
743 assert(bookp - path < sizeof (dsname));
744 (void) strlcpy(dsname, path,
745 MIN(sizeof (dsname), bookp - path + 1));
746
747 /*
748 * Create handle for the parent dataset.
749 */
750 errno = 0;
751 if ((pzhp = make_dataset_handle(hdl, dsname)) == NULL) {
752 (void) zfs_standard_error(hdl, errno, errbuf);
753 return (NULL);
754 }
755
756 /*
757 * Iterate bookmarks to find the right one.
758 */
759 errno = 0;
760 if ((zfs_iter_bookmarks_v2(pzhp, 0, zfs_open_bookmarks_cb,
761 &cb_data) == 0) && (cb_data.zhp == NULL)) {
762 (void) zfs_error(hdl, EZFS_NOENT, errbuf);
763 zfs_close(pzhp);
764 errno = ENOENT;
765 return (NULL);
766 }
767 if (cb_data.zhp == NULL) {
768 (void) zfs_standard_error(hdl, errno, errbuf);
769 zfs_close(pzhp);
770 return (NULL);
771 }
772 zhp = cb_data.zhp;
773
774 /*
775 * Cleanup.
776 */
777 zfs_close(pzhp);
778 }
779
780 if (!(types & zhp->zfs_type)) {
781 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
782 zfs_close(zhp);
783 errno = EINVAL;
784 return (NULL);
785 }
786
787 return (zhp);
788 }
789
790 /*
791 * Release a ZFS handle. Nothing to do but free the associated memory.
792 */
793 void
zfs_close(zfs_handle_t * zhp)794 zfs_close(zfs_handle_t *zhp)
795 {
796 if (zhp->zfs_mntopts)
797 free(zhp->zfs_mntopts);
798 nvlist_free(zhp->zfs_props);
799 nvlist_free(zhp->zfs_user_props);
800 nvlist_free(zhp->zfs_recvd_props);
801 free(zhp);
802 }
803
804 typedef struct mnttab_node {
805 struct mnttab mtn_mt;
806 avl_node_t mtn_node;
807 } mnttab_node_t;
808
809 static int
libzfs_mnttab_cache_compare(const void * arg1,const void * arg2)810 libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
811 {
812 const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
813 const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
814 int rv;
815
816 rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
817
818 return (TREE_ISIGN(rv));
819 }
820
821 void
libzfs_mnttab_init(libzfs_handle_t * hdl)822 libzfs_mnttab_init(libzfs_handle_t *hdl)
823 {
824 pthread_mutex_init(&hdl->libzfs_mnttab_cache_lock, NULL);
825 assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
826 avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
827 sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
828 }
829
830 static int
libzfs_mnttab_update(libzfs_handle_t * hdl)831 libzfs_mnttab_update(libzfs_handle_t *hdl)
832 {
833 FILE *mnttab;
834 struct mnttab entry;
835
836 if ((mnttab = fopen(MNTTAB, "re")) == NULL)
837 return (ENOENT);
838
839 while (getmntent(mnttab, &entry) == 0) {
840 mnttab_node_t *mtn;
841 avl_index_t where;
842
843 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
844 continue;
845
846 mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
847 mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
848 mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
849 mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
850 mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
851
852 /* Exclude duplicate mounts */
853 if (avl_find(&hdl->libzfs_mnttab_cache, mtn, &where) != NULL) {
854 free(mtn->mtn_mt.mnt_special);
855 free(mtn->mtn_mt.mnt_mountp);
856 free(mtn->mtn_mt.mnt_fstype);
857 free(mtn->mtn_mt.mnt_mntopts);
858 free(mtn);
859 continue;
860 }
861
862 avl_add(&hdl->libzfs_mnttab_cache, mtn);
863 }
864
865 (void) fclose(mnttab);
866 return (0);
867 }
868
869 void
libzfs_mnttab_fini(libzfs_handle_t * hdl)870 libzfs_mnttab_fini(libzfs_handle_t *hdl)
871 {
872 void *cookie = NULL;
873 mnttab_node_t *mtn;
874
875 while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))
876 != NULL) {
877 free(mtn->mtn_mt.mnt_special);
878 free(mtn->mtn_mt.mnt_mountp);
879 free(mtn->mtn_mt.mnt_fstype);
880 free(mtn->mtn_mt.mnt_mntopts);
881 free(mtn);
882 }
883 avl_destroy(&hdl->libzfs_mnttab_cache);
884 (void) pthread_mutex_destroy(&hdl->libzfs_mnttab_cache_lock);
885 }
886
887 void
libzfs_mnttab_cache(libzfs_handle_t * hdl,boolean_t enable)888 libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
889 {
890 hdl->libzfs_mnttab_enable = enable;
891 }
892
893 int
libzfs_mnttab_find(libzfs_handle_t * hdl,const char * fsname,struct mnttab * entry)894 libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
895 struct mnttab *entry)
896 {
897 FILE *mnttab;
898 mnttab_node_t find;
899 mnttab_node_t *mtn;
900 int ret = ENOENT;
901
902 if (!hdl->libzfs_mnttab_enable) {
903 struct mnttab srch = { 0 };
904
905 if (avl_numnodes(&hdl->libzfs_mnttab_cache))
906 libzfs_mnttab_fini(hdl);
907
908 if ((mnttab = fopen(MNTTAB, "re")) == NULL)
909 return (ENOENT);
910
911 srch.mnt_special = (char *)fsname;
912 srch.mnt_fstype = (char *)MNTTYPE_ZFS;
913 ret = getmntany(mnttab, entry, &srch) ? ENOENT : 0;
914 (void) fclose(mnttab);
915 return (ret);
916 }
917
918 pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
919 if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) {
920 int error;
921
922 if ((error = libzfs_mnttab_update(hdl)) != 0) {
923 pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
924 return (error);
925 }
926 }
927
928 find.mtn_mt.mnt_special = (char *)fsname;
929 mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
930 if (mtn) {
931 *entry = mtn->mtn_mt;
932 ret = 0;
933 }
934 pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
935 return (ret);
936 }
937
938 void
libzfs_mnttab_add(libzfs_handle_t * hdl,const char * special,const char * mountp,const char * mntopts)939 libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
940 const char *mountp, const char *mntopts)
941 {
942 mnttab_node_t *mtn;
943
944 pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
945 if (avl_numnodes(&hdl->libzfs_mnttab_cache) != 0) {
946 mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
947 mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
948 mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
949 mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
950 mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
951 /*
952 * Another thread may have already added this entry
953 * via libzfs_mnttab_update. If so we should skip it.
954 */
955 if (avl_find(&hdl->libzfs_mnttab_cache, mtn, NULL) != NULL) {
956 free(mtn->mtn_mt.mnt_special);
957 free(mtn->mtn_mt.mnt_mountp);
958 free(mtn->mtn_mt.mnt_fstype);
959 free(mtn->mtn_mt.mnt_mntopts);
960 free(mtn);
961 } else {
962 avl_add(&hdl->libzfs_mnttab_cache, mtn);
963 }
964 }
965 pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
966 }
967
968 void
libzfs_mnttab_remove(libzfs_handle_t * hdl,const char * fsname)969 libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
970 {
971 mnttab_node_t find;
972 mnttab_node_t *ret;
973
974 pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
975 find.mtn_mt.mnt_special = (char *)fsname;
976 if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))
977 != NULL) {
978 avl_remove(&hdl->libzfs_mnttab_cache, ret);
979 free(ret->mtn_mt.mnt_special);
980 free(ret->mtn_mt.mnt_mountp);
981 free(ret->mtn_mt.mnt_fstype);
982 free(ret->mtn_mt.mnt_mntopts);
983 free(ret);
984 }
985 pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
986 }
987
988 int
zfs_spa_version(zfs_handle_t * zhp,int * spa_version)989 zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
990 {
991 zpool_handle_t *zpool_handle = zhp->zpool_hdl;
992
993 if (zpool_handle == NULL)
994 return (-1);
995
996 *spa_version = zpool_get_prop_int(zpool_handle,
997 ZPOOL_PROP_VERSION, NULL);
998 return (0);
999 }
1000
1001 /*
1002 * The choice of reservation property depends on the SPA version.
1003 */
1004 static int
zfs_which_resv_prop(zfs_handle_t * zhp,zfs_prop_t * resv_prop)1005 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
1006 {
1007 int spa_version;
1008
1009 if (zfs_spa_version(zhp, &spa_version) < 0)
1010 return (-1);
1011
1012 if (spa_version >= SPA_VERSION_REFRESERVATION)
1013 *resv_prop = ZFS_PROP_REFRESERVATION;
1014 else
1015 *resv_prop = ZFS_PROP_RESERVATION;
1016
1017 return (0);
1018 }
1019
1020 /*
1021 * Given an nvlist of properties to set, validates that they are correct, and
1022 * parses any numeric properties (index, boolean, etc) if they are specified as
1023 * strings.
1024 */
1025 nvlist_t *
zfs_valid_proplist(libzfs_handle_t * hdl,zfs_type_t type,nvlist_t * nvl,uint64_t zoned,zfs_handle_t * zhp,zpool_handle_t * zpool_hdl,boolean_t key_params_ok,const char * errbuf)1026 zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
1027 uint64_t zoned, zfs_handle_t *zhp, zpool_handle_t *zpool_hdl,
1028 boolean_t key_params_ok, const char *errbuf)
1029 {
1030 nvpair_t *elem;
1031 uint64_t intval;
1032 const char *strval;
1033 zfs_prop_t prop;
1034 nvlist_t *ret;
1035 int chosen_normal = -1;
1036 int chosen_utf = -1;
1037 int set_maxbs = 0;
1038
1039 if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
1040 (void) no_memory(hdl);
1041 return (NULL);
1042 }
1043
1044 /*
1045 * Make sure this property is valid and applies to this type.
1046 */
1047
1048 elem = NULL;
1049 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
1050 const char *propname = nvpair_name(elem);
1051
1052 prop = zfs_name_to_prop(propname);
1053 if (prop == ZPROP_USERPROP && zfs_prop_user(propname)) {
1054 /*
1055 * This is a user property: make sure it's a
1056 * string, and that it's less than ZAP_MAXNAMELEN.
1057 */
1058 if (nvpair_type(elem) != DATA_TYPE_STRING) {
1059 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1060 "'%s' must be a string"), propname);
1061 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1062 goto error;
1063 }
1064
1065 if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
1066 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1067 "property name '%s' is too long"),
1068 propname);
1069 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1070 goto error;
1071 }
1072
1073 (void) nvpair_value_string(elem, &strval);
1074 if (nvlist_add_string(ret, propname, strval) != 0) {
1075 (void) no_memory(hdl);
1076 goto error;
1077 }
1078 continue;
1079 }
1080
1081 /*
1082 * Currently, only user properties can be modified on
1083 * snapshots.
1084 */
1085 if (type == ZFS_TYPE_SNAPSHOT) {
1086 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1087 "this property can not be modified for snapshots"));
1088 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
1089 goto error;
1090 }
1091
1092 if (prop == ZPROP_USERPROP && zfs_prop_userquota(propname)) {
1093 zfs_userquota_prop_t uqtype;
1094 char *newpropname = NULL;
1095 char domain[128];
1096 uint64_t rid;
1097 uint64_t valary[3];
1098 int rc;
1099
1100 if (userquota_propname_decode(propname, zoned,
1101 &uqtype, domain, sizeof (domain), &rid) != 0) {
1102 zfs_error_aux(hdl,
1103 dgettext(TEXT_DOMAIN,
1104 "'%s' has an invalid user/group name"),
1105 propname);
1106 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1107 goto error;
1108 }
1109
1110 if (uqtype != ZFS_PROP_USERQUOTA &&
1111 uqtype != ZFS_PROP_GROUPQUOTA &&
1112 uqtype != ZFS_PROP_USEROBJQUOTA &&
1113 uqtype != ZFS_PROP_GROUPOBJQUOTA &&
1114 uqtype != ZFS_PROP_PROJECTQUOTA &&
1115 uqtype != ZFS_PROP_PROJECTOBJQUOTA) {
1116 zfs_error_aux(hdl,
1117 dgettext(TEXT_DOMAIN, "'%s' is readonly"),
1118 propname);
1119 (void) zfs_error(hdl, EZFS_PROPREADONLY,
1120 errbuf);
1121 goto error;
1122 }
1123
1124 if (nvpair_type(elem) == DATA_TYPE_STRING) {
1125 (void) nvpair_value_string(elem, &strval);
1126 if (strcmp(strval, "none") == 0) {
1127 intval = 0;
1128 } else if (zfs_nicestrtonum(hdl,
1129 strval, &intval) != 0) {
1130 (void) zfs_error(hdl,
1131 EZFS_BADPROP, errbuf);
1132 goto error;
1133 }
1134 } else if (nvpair_type(elem) ==
1135 DATA_TYPE_UINT64) {
1136 (void) nvpair_value_uint64(elem, &intval);
1137 if (intval == 0) {
1138 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1139 "use 'none' to disable "
1140 "{user|group|project}quota"));
1141 goto error;
1142 }
1143 } else {
1144 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1145 "'%s' must be a number"), propname);
1146 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1147 goto error;
1148 }
1149
1150 /*
1151 * Encode the prop name as
1152 * userquota@<hex-rid>-domain, to make it easy
1153 * for the kernel to decode.
1154 */
1155 rc = asprintf(&newpropname, "%s%llx-%s",
1156 zfs_userquota_prop_prefixes[uqtype],
1157 (longlong_t)rid, domain);
1158 if (rc == -1 || newpropname == NULL) {
1159 (void) no_memory(hdl);
1160 goto error;
1161 }
1162
1163 valary[0] = uqtype;
1164 valary[1] = rid;
1165 valary[2] = intval;
1166 if (nvlist_add_uint64_array(ret, newpropname,
1167 valary, 3) != 0) {
1168 free(newpropname);
1169 (void) no_memory(hdl);
1170 goto error;
1171 }
1172 free(newpropname);
1173 continue;
1174 } else if (prop == ZPROP_USERPROP &&
1175 zfs_prop_written(propname)) {
1176 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1177 "'%s' is readonly"),
1178 propname);
1179 (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
1180 goto error;
1181 }
1182
1183 if (prop == ZPROP_INVAL) {
1184 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1185 "invalid property '%s'"), propname);
1186 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1187 goto error;
1188 }
1189
1190 if (!zfs_prop_valid_for_type(prop, type, B_FALSE)) {
1191 zfs_error_aux(hdl,
1192 dgettext(TEXT_DOMAIN, "'%s' does not "
1193 "apply to datasets of this type"), propname);
1194 (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
1195 goto error;
1196 }
1197
1198 if (zfs_prop_readonly(prop) &&
1199 !(zfs_prop_setonce(prop) && zhp == NULL) &&
1200 !(zfs_prop_encryption_key_param(prop) && key_params_ok)) {
1201 zfs_error_aux(hdl,
1202 dgettext(TEXT_DOMAIN, "'%s' is readonly"),
1203 propname);
1204 (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
1205 goto error;
1206 }
1207
1208 if (zprop_parse_value(hdl, elem, prop, type, ret,
1209 &strval, &intval, errbuf) != 0)
1210 goto error;
1211
1212 /*
1213 * Perform some additional checks for specific properties.
1214 */
1215 switch (prop) {
1216 case ZFS_PROP_VERSION:
1217 {
1218 int version;
1219
1220 if (zhp == NULL)
1221 break;
1222 version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
1223 if (intval < version) {
1224 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1225 "Can not downgrade; already at version %u"),
1226 version);
1227 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1228 goto error;
1229 }
1230 break;
1231 }
1232
1233 case ZFS_PROP_VOLBLOCKSIZE:
1234 case ZFS_PROP_RECORDSIZE:
1235 {
1236 int maxbs = SPA_MAXBLOCKSIZE;
1237 char buf[64];
1238
1239 if (zpool_hdl != NULL) {
1240 maxbs = zpool_get_prop_int(zpool_hdl,
1241 ZPOOL_PROP_MAXBLOCKSIZE, NULL);
1242 }
1243 /*
1244 * The value must be a power of two between
1245 * SPA_MINBLOCKSIZE and maxbs.
1246 */
1247 if (intval < SPA_MINBLOCKSIZE ||
1248 intval > maxbs || !ISP2(intval)) {
1249 zfs_nicebytes(maxbs, buf, sizeof (buf));
1250 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1251 "'%s' must be power of 2 from 512B "
1252 "to %s"), propname, buf);
1253 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1254 goto error;
1255 }
1256 /* save the ZFS_PROP_RECORDSIZE during create op */
1257 if (zpool_hdl == NULL && prop == ZFS_PROP_RECORDSIZE) {
1258 set_maxbs = intval;
1259 }
1260 break;
1261 }
1262
1263 case ZFS_PROP_SPECIAL_SMALL_BLOCKS:
1264 {
1265 int maxbs =
1266 set_maxbs == 0 ? SPA_OLD_MAXBLOCKSIZE : set_maxbs;
1267 char buf[64];
1268
1269 if (zpool_hdl != NULL) {
1270 char state[64] = "";
1271
1272 maxbs = zpool_get_prop_int(zpool_hdl,
1273 ZPOOL_PROP_MAXBLOCKSIZE, NULL);
1274
1275 /*
1276 * Issue a warning but do not fail so that
1277 * tests for settable properties succeed.
1278 */
1279 if (zpool_prop_get_feature(zpool_hdl,
1280 "feature@allocation_classes", state,
1281 sizeof (state)) != 0 ||
1282 strcmp(state, ZFS_FEATURE_ACTIVE) != 0) {
1283 (void) fprintf(stderr, gettext(
1284 "%s: property requires a special "
1285 "device in the pool\n"), propname);
1286 }
1287 }
1288 if (intval != 0 &&
1289 (intval < SPA_MINBLOCKSIZE ||
1290 intval > maxbs || !ISP2(intval))) {
1291 zfs_nicebytes(maxbs, buf, sizeof (buf));
1292 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1293 "invalid '%s=%llu' property: must be zero "
1294 "or a power of 2 from 512B to %s"),
1295 propname, (unsigned long long)intval, buf);
1296 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1297 goto error;
1298 }
1299 break;
1300 }
1301
1302 case ZFS_PROP_MLSLABEL:
1303 {
1304 #ifdef HAVE_MLSLABEL
1305 /*
1306 * Verify the mlslabel string and convert to
1307 * internal hex label string.
1308 */
1309
1310 m_label_t *new_sl;
1311 char *hex = NULL; /* internal label string */
1312
1313 /* Default value is already OK. */
1314 if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
1315 break;
1316
1317 /* Verify the label can be converted to binary form */
1318 if (((new_sl = m_label_alloc(MAC_LABEL)) == NULL) ||
1319 (str_to_label(strval, &new_sl, MAC_LABEL,
1320 L_NO_CORRECTION, NULL) == -1)) {
1321 goto badlabel;
1322 }
1323
1324 /* Now translate to hex internal label string */
1325 if (label_to_str(new_sl, &hex, M_INTERNAL,
1326 DEF_NAMES) != 0) {
1327 if (hex)
1328 free(hex);
1329 goto badlabel;
1330 }
1331 m_label_free(new_sl);
1332
1333 /* If string is already in internal form, we're done. */
1334 if (strcmp(strval, hex) == 0) {
1335 free(hex);
1336 break;
1337 }
1338
1339 /* Replace the label string with the internal form. */
1340 (void) nvlist_remove(ret, zfs_prop_to_name(prop),
1341 DATA_TYPE_STRING);
1342 fnvlist_add_string(ret, zfs_prop_to_name(prop), hex);
1343 free(hex);
1344
1345 break;
1346
1347 badlabel:
1348 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1349 "invalid mlslabel '%s'"), strval);
1350 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1351 m_label_free(new_sl); /* OK if null */
1352 goto error;
1353 #else
1354 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1355 "mlslabels are unsupported"));
1356 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1357 goto error;
1358 #endif /* HAVE_MLSLABEL */
1359 }
1360
1361 case ZFS_PROP_MOUNTPOINT:
1362 {
1363 namecheck_err_t why;
1364
1365 if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
1366 strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
1367 break;
1368
1369 if (mountpoint_namecheck(strval, &why)) {
1370 switch (why) {
1371 case NAME_ERR_LEADING_SLASH:
1372 zfs_error_aux(hdl,
1373 dgettext(TEXT_DOMAIN,
1374 "'%s' must be an absolute path, "
1375 "'none', or 'legacy'"), propname);
1376 break;
1377 case NAME_ERR_TOOLONG:
1378 zfs_error_aux(hdl,
1379 dgettext(TEXT_DOMAIN,
1380 "component of '%s' is too long"),
1381 propname);
1382 break;
1383
1384 default:
1385 zfs_error_aux(hdl,
1386 dgettext(TEXT_DOMAIN,
1387 "(%d) not defined"),
1388 why);
1389 break;
1390 }
1391 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1392 goto error;
1393 }
1394 zfs_fallthrough;
1395 }
1396
1397 case ZFS_PROP_SHARESMB:
1398 case ZFS_PROP_SHARENFS:
1399 /*
1400 * For the mountpoint and sharenfs or sharesmb
1401 * properties, check if it can be set in a
1402 * global/non-global zone based on
1403 * the zoned property value:
1404 *
1405 * global zone non-global zone
1406 * --------------------------------------------------
1407 * zoned=on mountpoint (no) mountpoint (yes)
1408 * sharenfs (no) sharenfs (no)
1409 * sharesmb (no) sharesmb (no)
1410 *
1411 * zoned=off mountpoint (yes) N/A
1412 * sharenfs (yes)
1413 * sharesmb (yes)
1414 */
1415 if (zoned) {
1416 if (getzoneid() == GLOBAL_ZONEID) {
1417 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1418 "'%s' cannot be set on "
1419 "dataset in a non-global zone"),
1420 propname);
1421 (void) zfs_error(hdl, EZFS_ZONED,
1422 errbuf);
1423 goto error;
1424 } else if (prop == ZFS_PROP_SHARENFS ||
1425 prop == ZFS_PROP_SHARESMB) {
1426 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1427 "'%s' cannot be set in "
1428 "a non-global zone"), propname);
1429 (void) zfs_error(hdl, EZFS_ZONED,
1430 errbuf);
1431 goto error;
1432 }
1433 } else if (getzoneid() != GLOBAL_ZONEID) {
1434 /*
1435 * If zoned property is 'off', this must be in
1436 * a global zone. If not, something is wrong.
1437 */
1438 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1439 "'%s' cannot be set while dataset "
1440 "'zoned' property is set"), propname);
1441 (void) zfs_error(hdl, EZFS_ZONED, errbuf);
1442 goto error;
1443 }
1444
1445 /*
1446 * At this point, it is legitimate to set the
1447 * property. Now we want to make sure that the
1448 * property value is valid if it is sharenfs.
1449 */
1450 if ((prop == ZFS_PROP_SHARENFS ||
1451 prop == ZFS_PROP_SHARESMB) &&
1452 strcmp(strval, "on") != 0 &&
1453 strcmp(strval, "off") != 0) {
1454 enum sa_protocol proto;
1455
1456 if (prop == ZFS_PROP_SHARESMB)
1457 proto = SA_PROTOCOL_SMB;
1458 else
1459 proto = SA_PROTOCOL_NFS;
1460
1461 if (sa_validate_shareopts(strval, proto) !=
1462 SA_OK) {
1463 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1464 "'%s' cannot be set to invalid "
1465 "options"), propname);
1466 (void) zfs_error(hdl, EZFS_BADPROP,
1467 errbuf);
1468 goto error;
1469 }
1470 }
1471
1472 break;
1473
1474 case ZFS_PROP_KEYLOCATION:
1475 if (!zfs_prop_valid_keylocation(strval, B_FALSE)) {
1476 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1477 "invalid keylocation"));
1478 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1479 goto error;
1480 }
1481
1482 if (zhp != NULL) {
1483 uint64_t crypt =
1484 zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION);
1485
1486 if (crypt == ZIO_CRYPT_OFF &&
1487 strcmp(strval, "none") != 0) {
1488 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1489 "keylocation must be 'none' "
1490 "for unencrypted datasets"));
1491 (void) zfs_error(hdl, EZFS_BADPROP,
1492 errbuf);
1493 goto error;
1494 } else if (crypt != ZIO_CRYPT_OFF &&
1495 strcmp(strval, "none") == 0) {
1496 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1497 "keylocation must not be 'none' "
1498 "for encrypted datasets"));
1499 (void) zfs_error(hdl, EZFS_BADPROP,
1500 errbuf);
1501 goto error;
1502 }
1503 }
1504 break;
1505
1506 case ZFS_PROP_PBKDF2_ITERS:
1507 if (intval < MIN_PBKDF2_ITERATIONS) {
1508 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1509 "minimum pbkdf2 iterations is %u"),
1510 MIN_PBKDF2_ITERATIONS);
1511 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1512 goto error;
1513 }
1514 break;
1515
1516 case ZFS_PROP_UTF8ONLY:
1517 chosen_utf = (int)intval;
1518 break;
1519
1520 case ZFS_PROP_NORMALIZE:
1521 chosen_normal = (int)intval;
1522 break;
1523
1524 default:
1525 break;
1526 }
1527
1528 /*
1529 * For changes to existing volumes, we have some additional
1530 * checks to enforce.
1531 */
1532 if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1533 uint64_t blocksize = zfs_prop_get_int(zhp,
1534 ZFS_PROP_VOLBLOCKSIZE);
1535 char buf[64];
1536
1537 switch (prop) {
1538 case ZFS_PROP_VOLSIZE:
1539 if (intval % blocksize != 0) {
1540 zfs_nicebytes(blocksize, buf,
1541 sizeof (buf));
1542 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1543 "'%s' must be a multiple of "
1544 "volume block size (%s)"),
1545 propname, buf);
1546 (void) zfs_error(hdl, EZFS_BADPROP,
1547 errbuf);
1548 goto error;
1549 }
1550
1551 if (intval == 0) {
1552 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1553 "'%s' cannot be zero"),
1554 propname);
1555 (void) zfs_error(hdl, EZFS_BADPROP,
1556 errbuf);
1557 goto error;
1558 }
1559 break;
1560
1561 default:
1562 break;
1563 }
1564 }
1565
1566 /* check encryption properties */
1567 if (zhp != NULL) {
1568 int64_t crypt = zfs_prop_get_int(zhp,
1569 ZFS_PROP_ENCRYPTION);
1570
1571 switch (prop) {
1572 case ZFS_PROP_COPIES:
1573 if (crypt != ZIO_CRYPT_OFF && intval > 2) {
1574 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1575 "encrypted datasets cannot have "
1576 "3 copies"));
1577 (void) zfs_error(hdl, EZFS_BADPROP,
1578 errbuf);
1579 goto error;
1580 }
1581 break;
1582 default:
1583 break;
1584 }
1585 }
1586 }
1587
1588 /*
1589 * If normalization was chosen, but no UTF8 choice was made,
1590 * enforce rejection of non-UTF8 names.
1591 *
1592 * If normalization was chosen, but rejecting non-UTF8 names
1593 * was explicitly not chosen, it is an error.
1594 *
1595 * If utf8only was turned off, but the parent has normalization,
1596 * turn off normalization.
1597 */
1598 if (chosen_normal > 0 && chosen_utf < 0) {
1599 if (nvlist_add_uint64(ret,
1600 zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
1601 (void) no_memory(hdl);
1602 goto error;
1603 }
1604 } else if (chosen_normal > 0 && chosen_utf == 0) {
1605 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1606 "'%s' must be set 'on' if normalization chosen"),
1607 zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
1608 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1609 goto error;
1610 } else if (chosen_normal < 0 && chosen_utf == 0) {
1611 if (nvlist_add_uint64(ret,
1612 zfs_prop_to_name(ZFS_PROP_NORMALIZE), 0) != 0) {
1613 (void) no_memory(hdl);
1614 goto error;
1615 }
1616 }
1617 return (ret);
1618
1619 error:
1620 nvlist_free(ret);
1621 return (NULL);
1622 }
1623
1624 static int
zfs_add_synthetic_resv(zfs_handle_t * zhp,nvlist_t * nvl)1625 zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1626 {
1627 uint64_t old_volsize;
1628 uint64_t new_volsize;
1629 uint64_t old_reservation;
1630 uint64_t new_reservation;
1631 zfs_prop_t resv_prop;
1632 nvlist_t *props;
1633 zpool_handle_t *zph = zpool_handle(zhp);
1634
1635 /*
1636 * If this is an existing volume, and someone is setting the volsize,
1637 * make sure that it matches the reservation, or add it if necessary.
1638 */
1639 old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1640 if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
1641 return (-1);
1642 old_reservation = zfs_prop_get_int(zhp, resv_prop);
1643
1644 props = fnvlist_alloc();
1645 fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
1646 zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
1647
1648 if ((zvol_volsize_to_reservation(zph, old_volsize, props) !=
1649 old_reservation) || nvlist_exists(nvl,
1650 zfs_prop_to_name(resv_prop))) {
1651 fnvlist_free(props);
1652 return (0);
1653 }
1654 if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1655 &new_volsize) != 0) {
1656 fnvlist_free(props);
1657 return (-1);
1658 }
1659 new_reservation = zvol_volsize_to_reservation(zph, new_volsize, props);
1660 fnvlist_free(props);
1661
1662 if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
1663 new_reservation) != 0) {
1664 (void) no_memory(zhp->zfs_hdl);
1665 return (-1);
1666 }
1667 return (1);
1668 }
1669
1670 /*
1671 * Helper for 'zfs {set|clone} refreservation=auto'. Must be called after
1672 * zfs_valid_proplist(), as it is what sets the UINT64_MAX sentinel value.
1673 * Return codes must match zfs_add_synthetic_resv().
1674 */
1675 static int
zfs_fix_auto_resv(zfs_handle_t * zhp,nvlist_t * nvl)1676 zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1677 {
1678 uint64_t volsize;
1679 uint64_t resvsize;
1680 zfs_prop_t prop;
1681 nvlist_t *props;
1682
1683 if (!ZFS_IS_VOLUME(zhp)) {
1684 return (0);
1685 }
1686
1687 if (zfs_which_resv_prop(zhp, &prop) != 0) {
1688 return (-1);
1689 }
1690
1691 if (prop != ZFS_PROP_REFRESERVATION) {
1692 return (0);
1693 }
1694
1695 if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(prop), &resvsize) != 0) {
1696 /* No value being set, so it can't be "auto" */
1697 return (0);
1698 }
1699 if (resvsize != UINT64_MAX) {
1700 /* Being set to a value other than "auto" */
1701 return (0);
1702 }
1703
1704 props = fnvlist_alloc();
1705
1706 fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
1707 zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
1708
1709 if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1710 &volsize) != 0) {
1711 volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1712 }
1713
1714 resvsize = zvol_volsize_to_reservation(zpool_handle(zhp), volsize,
1715 props);
1716 fnvlist_free(props);
1717
1718 (void) nvlist_remove_all(nvl, zfs_prop_to_name(prop));
1719 if (nvlist_add_uint64(nvl, zfs_prop_to_name(prop), resvsize) != 0) {
1720 (void) no_memory(zhp->zfs_hdl);
1721 return (-1);
1722 }
1723 return (1);
1724 }
1725
1726 static boolean_t
zfs_is_namespace_prop(zfs_prop_t prop)1727 zfs_is_namespace_prop(zfs_prop_t prop)
1728 {
1729 switch (prop) {
1730
1731 case ZFS_PROP_ATIME:
1732 case ZFS_PROP_RELATIME:
1733 case ZFS_PROP_DEVICES:
1734 case ZFS_PROP_EXEC:
1735 case ZFS_PROP_SETUID:
1736 case ZFS_PROP_READONLY:
1737 case ZFS_PROP_XATTR:
1738 case ZFS_PROP_NBMAND:
1739 return (B_TRUE);
1740
1741 default:
1742 return (B_FALSE);
1743 }
1744 }
1745
1746 /*
1747 * Given a property name and value, set the property for the given dataset.
1748 */
1749 int
zfs_prop_set(zfs_handle_t * zhp,const char * propname,const char * propval)1750 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1751 {
1752 int ret = -1;
1753 char errbuf[ERRBUFLEN];
1754 libzfs_handle_t *hdl = zhp->zfs_hdl;
1755 nvlist_t *nvl = NULL;
1756
1757 (void) snprintf(errbuf, sizeof (errbuf),
1758 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1759 zhp->zfs_name);
1760
1761 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1762 nvlist_add_string(nvl, propname, propval) != 0) {
1763 (void) no_memory(hdl);
1764 goto error;
1765 }
1766
1767 ret = zfs_prop_set_list(zhp, nvl);
1768
1769 error:
1770 nvlist_free(nvl);
1771 return (ret);
1772 }
1773
1774 /*
1775 * Given an nvlist of property names and values, set the properties for the
1776 * given dataset.
1777 */
1778 int
zfs_prop_set_list(zfs_handle_t * zhp,nvlist_t * props)1779 zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
1780 {
1781 return (zfs_prop_set_list_flags(zhp, props, 0));
1782 }
1783
1784 /*
1785 * Given an nvlist of property names, values and flags, set the properties
1786 * for the given dataset. If ZFS_SET_NOMOUNT is set, it allows to update
1787 * mountpoint, sharenfs and sharesmb properties without (un/re)mounting
1788 * and (un/re)sharing the dataset.
1789 */
1790 int
zfs_prop_set_list_flags(zfs_handle_t * zhp,nvlist_t * props,int flags)1791 zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
1792 {
1793 zfs_cmd_t zc = {"\0"};
1794 int ret = -1;
1795 prop_changelist_t **cls = NULL;
1796 int cl_idx;
1797 char errbuf[ERRBUFLEN];
1798 libzfs_handle_t *hdl = zhp->zfs_hdl;
1799 nvlist_t *nvl;
1800 int nvl_len = 0;
1801 int added_resv = 0;
1802 zfs_prop_t prop;
1803 boolean_t nsprop = B_FALSE;
1804 nvpair_t *elem;
1805
1806 (void) snprintf(errbuf, sizeof (errbuf),
1807 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1808 zhp->zfs_name);
1809
1810 if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
1811 zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl,
1812 B_FALSE, errbuf)) == NULL)
1813 goto error;
1814
1815 /*
1816 * We have to check for any extra properties which need to be added
1817 * before computing the length of the nvlist.
1818 */
1819 for (elem = nvlist_next_nvpair(nvl, NULL);
1820 elem != NULL;
1821 elem = nvlist_next_nvpair(nvl, elem)) {
1822 if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
1823 (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
1824 goto error;
1825 }
1826 }
1827
1828 if (added_resv != 1 &&
1829 (added_resv = zfs_fix_auto_resv(zhp, nvl)) == -1) {
1830 goto error;
1831 }
1832
1833 /*
1834 * Check how many properties we're setting and allocate an array to
1835 * store changelist pointers for postfix().
1836 */
1837 for (elem = nvlist_next_nvpair(nvl, NULL);
1838 elem != NULL;
1839 elem = nvlist_next_nvpair(nvl, elem))
1840 nvl_len++;
1841 if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
1842 goto error;
1843
1844 cl_idx = 0;
1845 for (elem = nvlist_next_nvpair(nvl, NULL);
1846 elem != NULL;
1847 elem = nvlist_next_nvpair(nvl, elem)) {
1848
1849 prop = zfs_name_to_prop(nvpair_name(elem));
1850 nsprop |= zfs_is_namespace_prop(prop);
1851
1852 assert(cl_idx < nvl_len);
1853 /*
1854 * We don't want to unmount & remount the dataset when changing
1855 * its canmount property to 'on' or 'noauto'. We only use
1856 * the changelist logic to unmount when setting canmount=off.
1857 */
1858 if (prop != ZFS_PROP_CANMOUNT ||
1859 (fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
1860 zfs_is_mounted(zhp, NULL))) {
1861 cls[cl_idx] = changelist_gather(zhp, prop,
1862 ((flags & ZFS_SET_NOMOUNT) ?
1863 CL_GATHER_DONT_UNMOUNT : 0), 0);
1864 if (cls[cl_idx] == NULL)
1865 goto error;
1866 }
1867
1868 if (prop == ZFS_PROP_MOUNTPOINT &&
1869 changelist_haszonedchild(cls[cl_idx])) {
1870 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1871 "child dataset with inherited mountpoint is used "
1872 "in a non-global zone"));
1873 ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1874 goto error;
1875 }
1876
1877 if (cls[cl_idx] != NULL &&
1878 (ret = changelist_prefix(cls[cl_idx])) != 0)
1879 goto error;
1880
1881 cl_idx++;
1882 }
1883 assert(cl_idx == nvl_len);
1884
1885 /*
1886 * Execute the corresponding ioctl() to set this list of properties.
1887 */
1888 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1889
1890 zcmd_write_src_nvlist(hdl, &zc, nvl);
1891 zcmd_alloc_dst_nvlist(hdl, &zc, 0);
1892
1893 ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1894
1895 if (ret != 0) {
1896 if (zc.zc_nvlist_dst_filled == B_FALSE) {
1897 (void) zfs_standard_error(hdl, errno, errbuf);
1898 goto error;
1899 }
1900
1901 /* Get the list of unset properties back and report them. */
1902 nvlist_t *errorprops = NULL;
1903 if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
1904 goto error;
1905 for (nvpair_t *elem = nvlist_next_nvpair(errorprops, NULL);
1906 elem != NULL;
1907 elem = nvlist_next_nvpair(errorprops, elem)) {
1908 prop = zfs_name_to_prop(nvpair_name(elem));
1909 zfs_setprop_error(hdl, prop, errno, errbuf);
1910 }
1911 nvlist_free(errorprops);
1912
1913 if (added_resv && errno == ENOSPC) {
1914 /* clean up the volsize property we tried to set */
1915 uint64_t old_volsize = zfs_prop_get_int(zhp,
1916 ZFS_PROP_VOLSIZE);
1917 nvlist_free(nvl);
1918 nvl = NULL;
1919 zcmd_free_nvlists(&zc);
1920
1921 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
1922 goto error;
1923 if (nvlist_add_uint64(nvl,
1924 zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1925 old_volsize) != 0)
1926 goto error;
1927 zcmd_write_src_nvlist(hdl, &zc, nvl);
1928 (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1929 }
1930 } else {
1931 for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
1932 if (cls[cl_idx] != NULL) {
1933 int clp_err = changelist_postfix(cls[cl_idx]);
1934 if (clp_err != 0)
1935 ret = clp_err;
1936 }
1937 }
1938
1939 if (ret == 0) {
1940 /*
1941 * Refresh the statistics so the new property
1942 * value is reflected.
1943 */
1944 (void) get_stats(zhp);
1945
1946 /*
1947 * Remount the filesystem to propagate the change
1948 * if one of the options handled by the generic
1949 * Linux namespace layer has been modified.
1950 */
1951 if (nsprop && zfs_is_mounted(zhp, NULL))
1952 ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
1953 }
1954 }
1955
1956 error:
1957 nvlist_free(nvl);
1958 zcmd_free_nvlists(&zc);
1959 if (cls != NULL) {
1960 for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
1961 if (cls[cl_idx] != NULL)
1962 changelist_free(cls[cl_idx]);
1963 }
1964 free(cls);
1965 }
1966 return (ret);
1967 }
1968
1969 /*
1970 * Given a property, inherit the value from the parent dataset, or if received
1971 * is TRUE, revert to the received value, if any.
1972 */
1973 int
zfs_prop_inherit(zfs_handle_t * zhp,const char * propname,boolean_t received)1974 zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
1975 {
1976 zfs_cmd_t zc = {"\0"};
1977 int ret;
1978 prop_changelist_t *cl;
1979 libzfs_handle_t *hdl = zhp->zfs_hdl;
1980 char errbuf[ERRBUFLEN];
1981 zfs_prop_t prop;
1982
1983 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1984 "cannot inherit %s for '%s'"), propname, zhp->zfs_name);
1985
1986 zc.zc_cookie = received;
1987 if ((prop = zfs_name_to_prop(propname)) == ZPROP_USERPROP) {
1988 /*
1989 * For user properties, the amount of work we have to do is very
1990 * small, so just do it here.
1991 */
1992 if (!zfs_prop_user(propname)) {
1993 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1994 "invalid property"));
1995 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
1996 }
1997
1998 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1999 (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
2000
2001 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0)
2002 return (zfs_standard_error(hdl, errno, errbuf));
2003
2004 (void) get_stats(zhp);
2005 return (0);
2006 }
2007
2008 /*
2009 * Verify that this property is inheritable.
2010 */
2011 if (zfs_prop_readonly(prop))
2012 return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf));
2013
2014 if (!zfs_prop_inheritable(prop) && !received)
2015 return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
2016
2017 /*
2018 * Check to see if the value applies to this type
2019 */
2020 if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE))
2021 return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
2022
2023 /*
2024 * Normalize the name, to get rid of shorthand abbreviations.
2025 */
2026 propname = zfs_prop_to_name(prop);
2027 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2028 (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
2029
2030 if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID &&
2031 zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
2032 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2033 "dataset is used in a non-global zone"));
2034 return (zfs_error(hdl, EZFS_ZONED, errbuf));
2035 }
2036
2037 /*
2038 * Determine datasets which will be affected by this change, if any.
2039 */
2040 if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
2041 return (-1);
2042
2043 if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
2044 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2045 "child dataset with inherited mountpoint is used "
2046 "in a non-global zone"));
2047 ret = zfs_error(hdl, EZFS_ZONED, errbuf);
2048 goto error;
2049 }
2050
2051 if ((ret = changelist_prefix(cl)) != 0)
2052 goto error;
2053
2054 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0) {
2055 changelist_free(cl);
2056 return (zfs_standard_error(hdl, errno, errbuf));
2057 } else {
2058
2059 if ((ret = changelist_postfix(cl)) != 0)
2060 goto error;
2061
2062 /*
2063 * Refresh the statistics so the new property is reflected.
2064 */
2065 (void) get_stats(zhp);
2066
2067 /*
2068 * Remount the filesystem to propagate the change
2069 * if one of the options handled by the generic
2070 * Linux namespace layer has been modified.
2071 */
2072 if (zfs_is_namespace_prop(prop) &&
2073 zfs_is_mounted(zhp, NULL))
2074 ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
2075 }
2076
2077 error:
2078 changelist_free(cl);
2079 return (ret);
2080 }
2081
2082 /*
2083 * True DSL properties are stored in an nvlist. The following two functions
2084 * extract them appropriately.
2085 */
2086 uint64_t
getprop_uint64(zfs_handle_t * zhp,zfs_prop_t prop,const char ** source)2087 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, const char **source)
2088 {
2089 nvlist_t *nv;
2090 uint64_t value;
2091
2092 *source = NULL;
2093 if (nvlist_lookup_nvlist(zhp->zfs_props,
2094 zfs_prop_to_name(prop), &nv) == 0) {
2095 value = fnvlist_lookup_uint64(nv, ZPROP_VALUE);
2096 (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
2097 } else {
2098 verify(!zhp->zfs_props_table ||
2099 zhp->zfs_props_table[prop] == B_TRUE);
2100 value = zfs_prop_default_numeric(prop);
2101 *source = "";
2102 }
2103
2104 return (value);
2105 }
2106
2107 static const char *
getprop_string(zfs_handle_t * zhp,zfs_prop_t prop,const char ** source)2108 getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, const char **source)
2109 {
2110 nvlist_t *nv;
2111 const char *value;
2112
2113 *source = NULL;
2114 if (nvlist_lookup_nvlist(zhp->zfs_props,
2115 zfs_prop_to_name(prop), &nv) == 0) {
2116 value = fnvlist_lookup_string(nv, ZPROP_VALUE);
2117 (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
2118 } else {
2119 verify(!zhp->zfs_props_table ||
2120 zhp->zfs_props_table[prop] == B_TRUE);
2121 value = zfs_prop_default_string(prop);
2122 *source = "";
2123 }
2124
2125 return (value);
2126 }
2127
2128 static boolean_t
zfs_is_recvd_props_mode(zfs_handle_t * zhp)2129 zfs_is_recvd_props_mode(zfs_handle_t *zhp)
2130 {
2131 return (zhp->zfs_props != NULL &&
2132 zhp->zfs_props == zhp->zfs_recvd_props);
2133 }
2134
2135 static void
zfs_set_recvd_props_mode(zfs_handle_t * zhp,uintptr_t * cookie)2136 zfs_set_recvd_props_mode(zfs_handle_t *zhp, uintptr_t *cookie)
2137 {
2138 *cookie = (uintptr_t)zhp->zfs_props;
2139 zhp->zfs_props = zhp->zfs_recvd_props;
2140 }
2141
2142 static void
zfs_unset_recvd_props_mode(zfs_handle_t * zhp,uintptr_t * cookie)2143 zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uintptr_t *cookie)
2144 {
2145 zhp->zfs_props = (nvlist_t *)*cookie;
2146 *cookie = 0;
2147 }
2148
2149 /*
2150 * Internal function for getting a numeric property. Both zfs_prop_get() and
2151 * zfs_prop_get_int() are built using this interface.
2152 *
2153 * Certain properties can be overridden using 'mount -o'. In this case, scan
2154 * the contents of the /proc/self/mounts entry, searching for the
2155 * appropriate options. If they differ from the on-disk values, report the
2156 * current values and mark the source "temporary".
2157 */
2158 static int
get_numeric_property(zfs_handle_t * zhp,zfs_prop_t prop,zprop_source_t * src,const char ** source,uint64_t * val)2159 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
2160 const char **source, uint64_t *val)
2161 {
2162 zfs_cmd_t zc = {"\0"};
2163 nvlist_t *zplprops = NULL;
2164 struct mnttab mnt;
2165 const char *mntopt_on = NULL;
2166 const char *mntopt_off = NULL;
2167 boolean_t received = zfs_is_recvd_props_mode(zhp);
2168
2169 *source = NULL;
2170
2171 /*
2172 * If the property is being fetched for a snapshot, check whether
2173 * the property is valid for the snapshot's head dataset type.
2174 */
2175 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT &&
2176 !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE)) {
2177 *val = zfs_prop_default_numeric(prop);
2178 return (-1);
2179 }
2180
2181 switch (prop) {
2182 case ZFS_PROP_ATIME:
2183 mntopt_on = MNTOPT_ATIME;
2184 mntopt_off = MNTOPT_NOATIME;
2185 break;
2186
2187 case ZFS_PROP_RELATIME:
2188 mntopt_on = MNTOPT_RELATIME;
2189 mntopt_off = MNTOPT_NORELATIME;
2190 break;
2191
2192 case ZFS_PROP_DEVICES:
2193 mntopt_on = MNTOPT_DEVICES;
2194 mntopt_off = MNTOPT_NODEVICES;
2195 break;
2196
2197 case ZFS_PROP_EXEC:
2198 mntopt_on = MNTOPT_EXEC;
2199 mntopt_off = MNTOPT_NOEXEC;
2200 break;
2201
2202 case ZFS_PROP_READONLY:
2203 mntopt_on = MNTOPT_RO;
2204 mntopt_off = MNTOPT_RW;
2205 break;
2206
2207 case ZFS_PROP_SETUID:
2208 mntopt_on = MNTOPT_SETUID;
2209 mntopt_off = MNTOPT_NOSETUID;
2210 break;
2211
2212 case ZFS_PROP_XATTR:
2213 mntopt_on = MNTOPT_XATTR;
2214 mntopt_off = MNTOPT_NOXATTR;
2215 break;
2216
2217 case ZFS_PROP_NBMAND:
2218 mntopt_on = MNTOPT_NBMAND;
2219 mntopt_off = MNTOPT_NONBMAND;
2220 break;
2221
2222 default:
2223 break;
2224 }
2225
2226 /*
2227 * Because looking up the mount options is potentially expensive
2228 * (iterating over all of /proc/self/mounts), we defer its
2229 * calculation until we're looking up a property which requires
2230 * its presence.
2231 */
2232 if (!zhp->zfs_mntcheck &&
2233 (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
2234 libzfs_handle_t *hdl = zhp->zfs_hdl;
2235 struct mnttab entry;
2236
2237 if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0)
2238 zhp->zfs_mntopts = zfs_strdup(hdl,
2239 entry.mnt_mntopts);
2240
2241 zhp->zfs_mntcheck = B_TRUE;
2242 }
2243
2244 if (zhp->zfs_mntopts == NULL)
2245 mnt.mnt_mntopts = (char *)"";
2246 else
2247 mnt.mnt_mntopts = zhp->zfs_mntopts;
2248
2249 switch (prop) {
2250 case ZFS_PROP_ATIME:
2251 case ZFS_PROP_RELATIME:
2252 case ZFS_PROP_DEVICES:
2253 case ZFS_PROP_EXEC:
2254 case ZFS_PROP_READONLY:
2255 case ZFS_PROP_SETUID:
2256 #ifndef __FreeBSD__
2257 case ZFS_PROP_XATTR:
2258 #endif
2259 case ZFS_PROP_NBMAND:
2260 *val = getprop_uint64(zhp, prop, source);
2261
2262 if (received)
2263 break;
2264
2265 if (hasmntopt(&mnt, mntopt_on) && !*val) {
2266 *val = B_TRUE;
2267 if (src)
2268 *src = ZPROP_SRC_TEMPORARY;
2269 } else if (hasmntopt(&mnt, mntopt_off) && *val) {
2270 *val = B_FALSE;
2271 if (src)
2272 *src = ZPROP_SRC_TEMPORARY;
2273 }
2274 break;
2275
2276 case ZFS_PROP_CANMOUNT:
2277 case ZFS_PROP_VOLSIZE:
2278 case ZFS_PROP_QUOTA:
2279 case ZFS_PROP_REFQUOTA:
2280 case ZFS_PROP_RESERVATION:
2281 case ZFS_PROP_REFRESERVATION:
2282 case ZFS_PROP_FILESYSTEM_LIMIT:
2283 case ZFS_PROP_SNAPSHOT_LIMIT:
2284 case ZFS_PROP_FILESYSTEM_COUNT:
2285 case ZFS_PROP_SNAPSHOT_COUNT:
2286 *val = getprop_uint64(zhp, prop, source);
2287
2288 if (*source == NULL) {
2289 /* not default, must be local */
2290 *source = zhp->zfs_name;
2291 }
2292 break;
2293
2294 case ZFS_PROP_MOUNTED:
2295 *val = (zhp->zfs_mntopts != NULL);
2296 break;
2297
2298 case ZFS_PROP_NUMCLONES:
2299 *val = zhp->zfs_dmustats.dds_num_clones;
2300 break;
2301
2302 case ZFS_PROP_VERSION:
2303 case ZFS_PROP_NORMALIZE:
2304 case ZFS_PROP_UTF8ONLY:
2305 case ZFS_PROP_CASE:
2306 zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0);
2307
2308 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2309 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
2310 zcmd_free_nvlists(&zc);
2311 if (prop == ZFS_PROP_VERSION &&
2312 zhp->zfs_type == ZFS_TYPE_VOLUME)
2313 *val = zfs_prop_default_numeric(prop);
2314 return (-1);
2315 }
2316 if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
2317 nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
2318 val) != 0) {
2319 zcmd_free_nvlists(&zc);
2320 return (-1);
2321 }
2322 nvlist_free(zplprops);
2323 zcmd_free_nvlists(&zc);
2324 break;
2325
2326 case ZFS_PROP_INCONSISTENT:
2327 *val = zhp->zfs_dmustats.dds_inconsistent;
2328 break;
2329
2330 case ZFS_PROP_REDACTED:
2331 *val = zhp->zfs_dmustats.dds_redacted;
2332 break;
2333
2334 case ZFS_PROP_GUID:
2335 if (zhp->zfs_dmustats.dds_guid != 0)
2336 *val = zhp->zfs_dmustats.dds_guid;
2337 else
2338 *val = getprop_uint64(zhp, prop, source);
2339 break;
2340
2341 case ZFS_PROP_CREATETXG:
2342 /*
2343 * We can directly read createtxg property from zfs
2344 * handle for Filesystem, Snapshot and ZVOL types.
2345 */
2346 if (((zhp->zfs_type == ZFS_TYPE_FILESYSTEM) ||
2347 (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) ||
2348 (zhp->zfs_type == ZFS_TYPE_VOLUME)) &&
2349 (zhp->zfs_dmustats.dds_creation_txg != 0)) {
2350 *val = zhp->zfs_dmustats.dds_creation_txg;
2351 break;
2352 } else {
2353 *val = getprop_uint64(zhp, prop, source);
2354 }
2355 zfs_fallthrough;
2356 default:
2357 switch (zfs_prop_get_type(prop)) {
2358 case PROP_TYPE_NUMBER:
2359 case PROP_TYPE_INDEX:
2360 *val = getprop_uint64(zhp, prop, source);
2361 /*
2362 * If we tried to use a default value for a
2363 * readonly property, it means that it was not
2364 * present. Note this only applies to "truly"
2365 * readonly properties, not set-once properties
2366 * like volblocksize.
2367 */
2368 if (zfs_prop_readonly(prop) &&
2369 !zfs_prop_setonce(prop) &&
2370 *source != NULL && (*source)[0] == '\0') {
2371 *source = NULL;
2372 return (-1);
2373 }
2374 break;
2375
2376 case PROP_TYPE_STRING:
2377 default:
2378 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2379 "cannot get non-numeric property"));
2380 return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
2381 dgettext(TEXT_DOMAIN, "internal error")));
2382 }
2383 }
2384
2385 return (0);
2386 }
2387
2388 /*
2389 * Calculate the source type, given the raw source string.
2390 */
2391 static void
get_source(zfs_handle_t * zhp,zprop_source_t * srctype,const char * source,char * statbuf,size_t statlen)2392 get_source(zfs_handle_t *zhp, zprop_source_t *srctype, const char *source,
2393 char *statbuf, size_t statlen)
2394 {
2395 if (statbuf == NULL ||
2396 srctype == NULL || *srctype == ZPROP_SRC_TEMPORARY) {
2397 return;
2398 }
2399
2400 if (source == NULL) {
2401 *srctype = ZPROP_SRC_NONE;
2402 } else if (source[0] == '\0') {
2403 *srctype = ZPROP_SRC_DEFAULT;
2404 } else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) {
2405 *srctype = ZPROP_SRC_RECEIVED;
2406 } else {
2407 if (strcmp(source, zhp->zfs_name) == 0) {
2408 *srctype = ZPROP_SRC_LOCAL;
2409 } else {
2410 (void) strlcpy(statbuf, source, statlen);
2411 *srctype = ZPROP_SRC_INHERITED;
2412 }
2413 }
2414
2415 }
2416
2417 int
zfs_prop_get_recvd(zfs_handle_t * zhp,const char * propname,char * propbuf,size_t proplen,boolean_t literal)2418 zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
2419 size_t proplen, boolean_t literal)
2420 {
2421 zfs_prop_t prop;
2422 int err = 0;
2423
2424 if (zhp->zfs_recvd_props == NULL)
2425 if (get_recvd_props_ioctl(zhp) != 0)
2426 return (-1);
2427
2428 prop = zfs_name_to_prop(propname);
2429
2430 if (prop != ZPROP_USERPROP) {
2431 uintptr_t cookie;
2432 if (!nvlist_exists(zhp->zfs_recvd_props, propname))
2433 return (-1);
2434 zfs_set_recvd_props_mode(zhp, &cookie);
2435 err = zfs_prop_get(zhp, prop, propbuf, proplen,
2436 NULL, NULL, 0, literal);
2437 zfs_unset_recvd_props_mode(zhp, &cookie);
2438 } else {
2439 nvlist_t *propval;
2440 const char *recvdval;
2441 if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
2442 propname, &propval) != 0)
2443 return (-1);
2444 recvdval = fnvlist_lookup_string(propval, ZPROP_VALUE);
2445 (void) strlcpy(propbuf, recvdval, proplen);
2446 }
2447
2448 return (err == 0 ? 0 : -1);
2449 }
2450
2451 static int
get_clones_string(zfs_handle_t * zhp,char * propbuf,size_t proplen)2452 get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
2453 {
2454 nvlist_t *value;
2455 nvpair_t *pair;
2456
2457 value = zfs_get_clones_nvl(zhp);
2458 if (value == NULL || nvlist_empty(value))
2459 return (-1);
2460
2461 propbuf[0] = '\0';
2462 for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
2463 pair = nvlist_next_nvpair(value, pair)) {
2464 if (propbuf[0] != '\0')
2465 (void) strlcat(propbuf, ",", proplen);
2466 (void) strlcat(propbuf, nvpair_name(pair), proplen);
2467 }
2468
2469 return (0);
2470 }
2471
2472 struct get_clones_arg {
2473 uint64_t numclones;
2474 nvlist_t *value;
2475 const char *origin;
2476 char buf[ZFS_MAX_DATASET_NAME_LEN];
2477 };
2478
2479 static int
get_clones_cb(zfs_handle_t * zhp,void * arg)2480 get_clones_cb(zfs_handle_t *zhp, void *arg)
2481 {
2482 struct get_clones_arg *gca = arg;
2483
2484 if (gca->numclones == 0) {
2485 zfs_close(zhp);
2486 return (0);
2487 }
2488
2489 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
2490 NULL, NULL, 0, B_TRUE) != 0)
2491 goto out;
2492 if (strcmp(gca->buf, gca->origin) == 0) {
2493 fnvlist_add_boolean(gca->value, zfs_get_name(zhp));
2494 gca->numclones--;
2495 }
2496
2497 out:
2498 (void) zfs_iter_children_v2(zhp, 0, get_clones_cb, gca);
2499 zfs_close(zhp);
2500 return (0);
2501 }
2502
2503 nvlist_t *
zfs_get_clones_nvl(zfs_handle_t * zhp)2504 zfs_get_clones_nvl(zfs_handle_t *zhp)
2505 {
2506 nvlist_t *nv, *value;
2507
2508 if (nvlist_lookup_nvlist(zhp->zfs_props,
2509 zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
2510 struct get_clones_arg gca;
2511
2512 /*
2513 * if this is a snapshot, then the kernel wasn't able
2514 * to get the clones. Do it by slowly iterating.
2515 */
2516 if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
2517 return (NULL);
2518 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
2519 return (NULL);
2520 if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
2521 nvlist_free(nv);
2522 return (NULL);
2523 }
2524
2525 gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
2526 gca.value = value;
2527 gca.origin = zhp->zfs_name;
2528
2529 if (gca.numclones != 0) {
2530 zfs_handle_t *root;
2531 char pool[ZFS_MAX_DATASET_NAME_LEN];
2532 char *cp = pool;
2533
2534 /* get the pool name */
2535 (void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
2536 (void) strsep(&cp, "/@");
2537 root = zfs_open(zhp->zfs_hdl, pool,
2538 ZFS_TYPE_FILESYSTEM);
2539 if (root == NULL) {
2540 nvlist_free(nv);
2541 nvlist_free(value);
2542 return (NULL);
2543 }
2544
2545 (void) get_clones_cb(root, &gca);
2546 }
2547
2548 if (gca.numclones != 0 ||
2549 nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
2550 nvlist_add_nvlist(zhp->zfs_props,
2551 zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
2552 nvlist_free(nv);
2553 nvlist_free(value);
2554 return (NULL);
2555 }
2556 nvlist_free(nv);
2557 nvlist_free(value);
2558 nv = fnvlist_lookup_nvlist(zhp->zfs_props,
2559 zfs_prop_to_name(ZFS_PROP_CLONES));
2560 }
2561
2562 return (fnvlist_lookup_nvlist(nv, ZPROP_VALUE));
2563 }
2564
2565 static int
get_rsnaps_string(zfs_handle_t * zhp,char * propbuf,size_t proplen)2566 get_rsnaps_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
2567 {
2568 nvlist_t *value;
2569 uint64_t *snaps;
2570 uint_t nsnaps;
2571
2572 if (nvlist_lookup_nvlist(zhp->zfs_props,
2573 zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS), &value) != 0)
2574 return (-1);
2575 if (nvlist_lookup_uint64_array(value, ZPROP_VALUE, &snaps,
2576 &nsnaps) != 0)
2577 return (-1);
2578 if (nsnaps == 0) {
2579 /* There's no redaction snapshots; pass a special value back */
2580 (void) snprintf(propbuf, proplen, "none");
2581 return (0);
2582 }
2583 propbuf[0] = '\0';
2584 for (int i = 0; i < nsnaps; i++) {
2585 char buf[128];
2586 if (propbuf[0] != '\0')
2587 (void) strlcat(propbuf, ",", proplen);
2588 (void) snprintf(buf, sizeof (buf), "%llu",
2589 (u_longlong_t)snaps[i]);
2590 (void) strlcat(propbuf, buf, proplen);
2591 }
2592
2593 return (0);
2594 }
2595
2596 /*
2597 * Accepts a property and value and checks that the value
2598 * matches the one found by the channel program. If they are
2599 * not equal, print both of them.
2600 */
2601 static void
zcp_check(zfs_handle_t * zhp,zfs_prop_t prop,uint64_t intval,const char * strval)2602 zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
2603 const char *strval)
2604 {
2605 if (!zhp->zfs_hdl->libzfs_prop_debug)
2606 return;
2607 int error;
2608 char *poolname = zhp->zpool_hdl->zpool_name;
2609 const char *prop_name = zfs_prop_to_name(prop);
2610 const char *program =
2611 "args = ...\n"
2612 "ds = args['dataset']\n"
2613 "prop = args['property']\n"
2614 "value, setpoint = zfs.get_prop(ds, prop)\n"
2615 "return {value=value, setpoint=setpoint}\n";
2616 nvlist_t *outnvl;
2617 nvlist_t *retnvl;
2618 nvlist_t *argnvl = fnvlist_alloc();
2619
2620 fnvlist_add_string(argnvl, "dataset", zhp->zfs_name);
2621 fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop));
2622
2623 error = lzc_channel_program_nosync(poolname, program,
2624 10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl);
2625
2626 if (error == 0) {
2627 retnvl = fnvlist_lookup_nvlist(outnvl, "return");
2628 if (zfs_prop_get_type(prop) == PROP_TYPE_NUMBER) {
2629 int64_t ans;
2630 error = nvlist_lookup_int64(retnvl, "value", &ans);
2631 if (error != 0) {
2632 (void) fprintf(stderr, "%s: zcp check error: "
2633 "%u\n", prop_name, error);
2634 return;
2635 }
2636 if (ans != intval) {
2637 (void) fprintf(stderr, "%s: zfs found %llu, "
2638 "but zcp found %llu\n", prop_name,
2639 (u_longlong_t)intval, (u_longlong_t)ans);
2640 }
2641 } else {
2642 const char *str_ans;
2643 error = nvlist_lookup_string(retnvl, "value", &str_ans);
2644 if (error != 0) {
2645 (void) fprintf(stderr, "%s: zcp check error: "
2646 "%u\n", prop_name, error);
2647 return;
2648 }
2649 if (strcmp(strval, str_ans) != 0) {
2650 (void) fprintf(stderr,
2651 "%s: zfs found '%s', but zcp found '%s'\n",
2652 prop_name, strval, str_ans);
2653 }
2654 }
2655 } else {
2656 (void) fprintf(stderr, "%s: zcp check failed, channel program "
2657 "error: %u\n", prop_name, error);
2658 }
2659 nvlist_free(argnvl);
2660 nvlist_free(outnvl);
2661 }
2662
2663 /*
2664 * Retrieve a property from the given object. If 'literal' is specified, then
2665 * numbers are left as exact values. Otherwise, numbers are converted to a
2666 * human-readable form.
2667 *
2668 * Returns 0 on success, or -1 on error.
2669 */
2670 int
zfs_prop_get(zfs_handle_t * zhp,zfs_prop_t prop,char * propbuf,size_t proplen,zprop_source_t * src,char * statbuf,size_t statlen,boolean_t literal)2671 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
2672 zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
2673 {
2674 const char *source = NULL;
2675 uint64_t val;
2676 const char *str;
2677 const char *strval;
2678 boolean_t received = zfs_is_recvd_props_mode(zhp);
2679
2680 /*
2681 * Check to see if this property applies to our object
2682 */
2683 if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE))
2684 return (-1);
2685
2686 if (received && zfs_prop_readonly(prop))
2687 return (-1);
2688
2689 if (src)
2690 *src = ZPROP_SRC_NONE;
2691
2692 switch (prop) {
2693 case ZFS_PROP_CREATION:
2694 /*
2695 * 'creation' is a time_t stored in the statistics. We convert
2696 * this into a string unless 'literal' is specified.
2697 */
2698 {
2699 val = getprop_uint64(zhp, prop, &source);
2700 time_t time = (time_t)val;
2701 struct tm t;
2702
2703 if (literal ||
2704 localtime_r(&time, &t) == NULL ||
2705 strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
2706 &t) == 0)
2707 (void) snprintf(propbuf, proplen, "%llu",
2708 (u_longlong_t)val);
2709 }
2710 zcp_check(zhp, prop, val, NULL);
2711 break;
2712
2713 case ZFS_PROP_MOUNTPOINT:
2714 /*
2715 * Getting the precise mountpoint can be tricky.
2716 *
2717 * - for 'none' or 'legacy', return those values.
2718 * - for inherited mountpoints, we want to take everything
2719 * after our ancestor and append it to the inherited value.
2720 *
2721 * If the pool has an alternate root, we want to prepend that
2722 * root to any values we return.
2723 */
2724
2725 str = getprop_string(zhp, prop, &source);
2726
2727 if (str[0] == '/') {
2728 char buf[MAXPATHLEN];
2729 char *root = buf;
2730 const char *relpath;
2731
2732 /*
2733 * If we inherit the mountpoint, even from a dataset
2734 * with a received value, the source will be the path of
2735 * the dataset we inherit from. If source is
2736 * ZPROP_SOURCE_VAL_RECVD, the received value is not
2737 * inherited.
2738 */
2739 if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2740 relpath = "";
2741 } else {
2742 relpath = zhp->zfs_name + strlen(source);
2743 if (relpath[0] == '/')
2744 relpath++;
2745 }
2746
2747 if ((zpool_get_prop(zhp->zpool_hdl,
2748 ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
2749 B_FALSE)) || (strcmp(root, "-") == 0))
2750 root[0] = '\0';
2751 /*
2752 * Special case an alternate root of '/'. This will
2753 * avoid having multiple leading slashes in the
2754 * mountpoint path.
2755 */
2756 if (strcmp(root, "/") == 0)
2757 root++;
2758
2759 /*
2760 * If the mountpoint is '/' then skip over this
2761 * if we are obtaining either an alternate root or
2762 * an inherited mountpoint.
2763 */
2764 if (str[1] == '\0' && (root[0] != '\0' ||
2765 relpath[0] != '\0'))
2766 str++;
2767
2768 if (relpath[0] == '\0')
2769 (void) snprintf(propbuf, proplen, "%s%s",
2770 root, str);
2771 else
2772 (void) snprintf(propbuf, proplen, "%s%s%s%s",
2773 root, str, relpath[0] == '@' ? "" : "/",
2774 relpath);
2775 } else {
2776 /* 'legacy' or 'none' */
2777 (void) strlcpy(propbuf, str, proplen);
2778 }
2779 zcp_check(zhp, prop, 0, propbuf);
2780 break;
2781
2782 case ZFS_PROP_ORIGIN:
2783 if (*zhp->zfs_dmustats.dds_origin != '\0') {
2784 str = (char *)&zhp->zfs_dmustats.dds_origin;
2785 } else {
2786 str = getprop_string(zhp, prop, &source);
2787 }
2788 if (str == NULL || *str == '\0')
2789 str = zfs_prop_default_string(prop);
2790 if (str == NULL)
2791 return (-1);
2792 (void) strlcpy(propbuf, str, proplen);
2793 zcp_check(zhp, prop, 0, str);
2794 break;
2795
2796 case ZFS_PROP_REDACT_SNAPS:
2797 if (get_rsnaps_string(zhp, propbuf, proplen) != 0)
2798 return (-1);
2799 break;
2800
2801 case ZFS_PROP_CLONES:
2802 if (get_clones_string(zhp, propbuf, proplen) != 0)
2803 return (-1);
2804 break;
2805
2806 case ZFS_PROP_QUOTA:
2807 case ZFS_PROP_REFQUOTA:
2808 case ZFS_PROP_RESERVATION:
2809 case ZFS_PROP_REFRESERVATION:
2810
2811 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2812 return (-1);
2813 /*
2814 * If quota or reservation is 0, we translate this into 'none'
2815 * (unless literal is set), and indicate that it's the default
2816 * value. Otherwise, we print the number nicely and indicate
2817 * that its set locally.
2818 */
2819 if (val == 0) {
2820 if (literal)
2821 (void) strlcpy(propbuf, "0", proplen);
2822 else
2823 (void) strlcpy(propbuf, "none", proplen);
2824 } else {
2825 if (literal)
2826 (void) snprintf(propbuf, proplen, "%llu",
2827 (u_longlong_t)val);
2828 else
2829 zfs_nicebytes(val, propbuf, proplen);
2830 }
2831 zcp_check(zhp, prop, val, NULL);
2832 break;
2833
2834 case ZFS_PROP_FILESYSTEM_LIMIT:
2835 case ZFS_PROP_SNAPSHOT_LIMIT:
2836 case ZFS_PROP_FILESYSTEM_COUNT:
2837 case ZFS_PROP_SNAPSHOT_COUNT:
2838
2839 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2840 return (-1);
2841
2842 /*
2843 * If limit is UINT64_MAX, we translate this into 'none', and
2844 * indicate that it's the default value. Otherwise, we print
2845 * the number nicely and indicate that it's set locally.
2846 */
2847 if (val == UINT64_MAX) {
2848 (void) strlcpy(propbuf, "none", proplen);
2849 } else if (literal) {
2850 (void) snprintf(propbuf, proplen, "%llu",
2851 (u_longlong_t)val);
2852 } else {
2853 zfs_nicenum(val, propbuf, proplen);
2854 }
2855
2856 zcp_check(zhp, prop, val, NULL);
2857 break;
2858
2859 case ZFS_PROP_REFRATIO:
2860 case ZFS_PROP_COMPRESSRATIO:
2861 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2862 return (-1);
2863 if (literal)
2864 (void) snprintf(propbuf, proplen, "%llu.%02llu",
2865 (u_longlong_t)(val / 100),
2866 (u_longlong_t)(val % 100));
2867 else
2868 (void) snprintf(propbuf, proplen, "%llu.%02llux",
2869 (u_longlong_t)(val / 100),
2870 (u_longlong_t)(val % 100));
2871 zcp_check(zhp, prop, val, NULL);
2872 break;
2873
2874 case ZFS_PROP_TYPE:
2875 switch (zhp->zfs_type) {
2876 case ZFS_TYPE_FILESYSTEM:
2877 str = "filesystem";
2878 break;
2879 case ZFS_TYPE_VOLUME:
2880 str = "volume";
2881 break;
2882 case ZFS_TYPE_SNAPSHOT:
2883 str = "snapshot";
2884 break;
2885 case ZFS_TYPE_BOOKMARK:
2886 str = "bookmark";
2887 break;
2888 default:
2889 abort();
2890 }
2891 (void) snprintf(propbuf, proplen, "%s", str);
2892 zcp_check(zhp, prop, 0, propbuf);
2893 break;
2894
2895 case ZFS_PROP_MOUNTED:
2896 /*
2897 * The 'mounted' property is a pseudo-property that described
2898 * whether the filesystem is currently mounted. Even though
2899 * it's a boolean value, the typical values of "on" and "off"
2900 * don't make sense, so we translate to "yes" and "no".
2901 */
2902 if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
2903 src, &source, &val) != 0)
2904 return (-1);
2905 if (val)
2906 (void) strlcpy(propbuf, "yes", proplen);
2907 else
2908 (void) strlcpy(propbuf, "no", proplen);
2909 break;
2910
2911 case ZFS_PROP_NAME:
2912 /*
2913 * The 'name' property is a pseudo-property derived from the
2914 * dataset name. It is presented as a real property to simplify
2915 * consumers.
2916 */
2917 (void) strlcpy(propbuf, zhp->zfs_name, proplen);
2918 zcp_check(zhp, prop, 0, propbuf);
2919 break;
2920
2921 case ZFS_PROP_MLSLABEL:
2922 {
2923 #ifdef HAVE_MLSLABEL
2924 m_label_t *new_sl = NULL;
2925 char *ascii = NULL; /* human readable label */
2926
2927 (void) strlcpy(propbuf,
2928 getprop_string(zhp, prop, &source), proplen);
2929
2930 if (literal || (strcasecmp(propbuf,
2931 ZFS_MLSLABEL_DEFAULT) == 0))
2932 break;
2933
2934 /*
2935 * Try to translate the internal hex string to
2936 * human-readable output. If there are any
2937 * problems just use the hex string.
2938 */
2939
2940 if (str_to_label(propbuf, &new_sl, MAC_LABEL,
2941 L_NO_CORRECTION, NULL) == -1) {
2942 m_label_free(new_sl);
2943 break;
2944 }
2945
2946 if (label_to_str(new_sl, &ascii, M_LABEL,
2947 DEF_NAMES) != 0) {
2948 if (ascii)
2949 free(ascii);
2950 m_label_free(new_sl);
2951 break;
2952 }
2953 m_label_free(new_sl);
2954
2955 (void) strlcpy(propbuf, ascii, proplen);
2956 free(ascii);
2957 #else
2958 (void) strlcpy(propbuf,
2959 getprop_string(zhp, prop, &source), proplen);
2960 #endif /* HAVE_MLSLABEL */
2961 }
2962 break;
2963
2964 case ZFS_PROP_GUID:
2965 case ZFS_PROP_KEY_GUID:
2966 case ZFS_PROP_IVSET_GUID:
2967 case ZFS_PROP_CREATETXG:
2968 case ZFS_PROP_OBJSETID:
2969 case ZFS_PROP_PBKDF2_ITERS:
2970 /*
2971 * These properties are stored as numbers, but they are
2972 * identifiers or counters.
2973 * We don't want them to be pretty printed, because pretty
2974 * printing truncates their values making them useless.
2975 */
2976 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2977 return (-1);
2978 (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
2979 zcp_check(zhp, prop, val, NULL);
2980 break;
2981
2982 case ZFS_PROP_REFERENCED:
2983 case ZFS_PROP_AVAILABLE:
2984 case ZFS_PROP_USED:
2985 case ZFS_PROP_USEDSNAP:
2986 case ZFS_PROP_USEDDS:
2987 case ZFS_PROP_USEDREFRESERV:
2988 case ZFS_PROP_USEDCHILD:
2989 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2990 return (-1);
2991 if (literal) {
2992 (void) snprintf(propbuf, proplen, "%llu",
2993 (u_longlong_t)val);
2994 } else {
2995 zfs_nicebytes(val, propbuf, proplen);
2996 }
2997 zcp_check(zhp, prop, val, NULL);
2998 break;
2999
3000 case ZFS_PROP_SNAPSHOTS_CHANGED:
3001 {
3002 if ((get_numeric_property(zhp, prop, src, &source,
3003 &val) != 0) || val == 0) {
3004 return (-1);
3005 }
3006
3007 time_t time = (time_t)val;
3008 struct tm t;
3009
3010 if (literal ||
3011 localtime_r(&time, &t) == NULL ||
3012 strftime(propbuf, proplen, "%a %b %e %k:%M:%S %Y",
3013 &t) == 0)
3014 (void) snprintf(propbuf, proplen, "%llu",
3015 (u_longlong_t)val);
3016 }
3017 zcp_check(zhp, prop, val, NULL);
3018 break;
3019
3020 default:
3021 switch (zfs_prop_get_type(prop)) {
3022 case PROP_TYPE_NUMBER:
3023 if (get_numeric_property(zhp, prop, src,
3024 &source, &val) != 0) {
3025 return (-1);
3026 }
3027
3028 if (literal) {
3029 (void) snprintf(propbuf, proplen, "%llu",
3030 (u_longlong_t)val);
3031 } else {
3032 zfs_nicenum(val, propbuf, proplen);
3033 }
3034 zcp_check(zhp, prop, val, NULL);
3035 break;
3036
3037 case PROP_TYPE_STRING:
3038 str = getprop_string(zhp, prop, &source);
3039 if (str == NULL)
3040 return (-1);
3041
3042 (void) strlcpy(propbuf, str, proplen);
3043 zcp_check(zhp, prop, 0, str);
3044 break;
3045
3046 case PROP_TYPE_INDEX:
3047 if (get_numeric_property(zhp, prop, src,
3048 &source, &val) != 0)
3049 return (-1);
3050 if (zfs_prop_index_to_string(prop, val, &strval) != 0)
3051 return (-1);
3052
3053 (void) strlcpy(propbuf, strval, proplen);
3054 zcp_check(zhp, prop, 0, strval);
3055 break;
3056
3057 default:
3058 abort();
3059 }
3060 }
3061
3062 get_source(zhp, src, source, statbuf, statlen);
3063
3064 return (0);
3065 }
3066
3067 /*
3068 * Utility function to get the given numeric property. Does no validation that
3069 * the given property is the appropriate type; should only be used with
3070 * hard-coded property types.
3071 */
3072 uint64_t
zfs_prop_get_int(zfs_handle_t * zhp,zfs_prop_t prop)3073 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
3074 {
3075 const char *source;
3076 uint64_t val = 0;
3077
3078 (void) get_numeric_property(zhp, prop, NULL, &source, &val);
3079
3080 return (val);
3081 }
3082
3083 static int
zfs_prop_set_int(zfs_handle_t * zhp,zfs_prop_t prop,uint64_t val)3084 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
3085 {
3086 char buf[64];
3087
3088 (void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
3089 return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
3090 }
3091
3092 /*
3093 * Similar to zfs_prop_get(), but returns the value as an integer.
3094 */
3095 int
zfs_prop_get_numeric(zfs_handle_t * zhp,zfs_prop_t prop,uint64_t * value,zprop_source_t * src,char * statbuf,size_t statlen)3096 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
3097 zprop_source_t *src, char *statbuf, size_t statlen)
3098 {
3099 const char *source;
3100
3101 /*
3102 * Check to see if this property applies to our object
3103 */
3104 if (!zfs_prop_valid_for_type(prop, zhp->zfs_type, B_FALSE)) {
3105 return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
3106 dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
3107 zfs_prop_to_name(prop)));
3108 }
3109
3110 if (src)
3111 *src = ZPROP_SRC_NONE;
3112
3113 if (get_numeric_property(zhp, prop, src, &source, value) != 0)
3114 return (-1);
3115
3116 get_source(zhp, src, source, statbuf, statlen);
3117
3118 return (0);
3119 }
3120
3121 #ifdef HAVE_IDMAP
3122 static int
idmap_id_to_numeric_domain_rid(uid_t id,boolean_t isuser,char ** domainp,idmap_rid_t * ridp)3123 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
3124 char **domainp, idmap_rid_t *ridp)
3125 {
3126 idmap_get_handle_t *get_hdl = NULL;
3127 idmap_stat status;
3128 int err = EINVAL;
3129
3130 if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
3131 goto out;
3132
3133 if (isuser) {
3134 err = idmap_get_sidbyuid(get_hdl, id,
3135 IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
3136 } else {
3137 err = idmap_get_sidbygid(get_hdl, id,
3138 IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
3139 }
3140 if (err == IDMAP_SUCCESS &&
3141 idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
3142 status == IDMAP_SUCCESS)
3143 err = 0;
3144 else
3145 err = EINVAL;
3146 out:
3147 if (get_hdl)
3148 idmap_get_destroy(get_hdl);
3149 return (err);
3150 }
3151 #endif /* HAVE_IDMAP */
3152
3153 /*
3154 * convert the propname into parameters needed by kernel
3155 * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
3156 * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
3157 * Eg: groupquota@staff -> ZFS_PROP_GROUPQUOTA, "", 1234
3158 * Eg: groupused@staff -> ZFS_PROP_GROUPUSED, "", 1234
3159 * Eg: projectquota@123 -> ZFS_PROP_PROJECTQUOTA, "", 123
3160 * Eg: projectused@789 -> ZFS_PROP_PROJECTUSED, "", 789
3161 */
3162 static int
userquota_propname_decode(const char * propname,boolean_t zoned,zfs_userquota_prop_t * typep,char * domain,int domainlen,uint64_t * ridp)3163 userquota_propname_decode(const char *propname, boolean_t zoned,
3164 zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
3165 {
3166 zfs_userquota_prop_t type;
3167 char *cp;
3168 boolean_t isuser;
3169 boolean_t isgroup;
3170 boolean_t isproject;
3171 struct passwd *pw;
3172 struct group *gr;
3173
3174 domain[0] = '\0';
3175
3176 /* Figure out the property type ({user|group|project}{quota|space}) */
3177 for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
3178 if (strncmp(propname, zfs_userquota_prop_prefixes[type],
3179 strlen(zfs_userquota_prop_prefixes[type])) == 0)
3180 break;
3181 }
3182 if (type == ZFS_NUM_USERQUOTA_PROPS)
3183 return (EINVAL);
3184 *typep = type;
3185
3186 isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED ||
3187 type == ZFS_PROP_USEROBJQUOTA ||
3188 type == ZFS_PROP_USEROBJUSED);
3189 isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED ||
3190 type == ZFS_PROP_GROUPOBJQUOTA ||
3191 type == ZFS_PROP_GROUPOBJUSED);
3192 isproject = (type == ZFS_PROP_PROJECTQUOTA ||
3193 type == ZFS_PROP_PROJECTUSED || type == ZFS_PROP_PROJECTOBJQUOTA ||
3194 type == ZFS_PROP_PROJECTOBJUSED);
3195
3196 cp = strchr(propname, '@') + 1;
3197
3198 if (isuser && (pw = getpwnam(cp)) != NULL) {
3199 if (zoned && getzoneid() == GLOBAL_ZONEID)
3200 return (ENOENT);
3201 *ridp = pw->pw_uid;
3202 } else if (isgroup && (gr = getgrnam(cp)) != NULL) {
3203 if (zoned && getzoneid() == GLOBAL_ZONEID)
3204 return (ENOENT);
3205 *ridp = gr->gr_gid;
3206 } else if (!isproject && strchr(cp, '@')) {
3207 #ifdef HAVE_IDMAP
3208 /*
3209 * It's a SID name (eg "user@domain") that needs to be
3210 * turned into S-1-domainID-RID.
3211 */
3212 directory_error_t e;
3213 char *numericsid = NULL;
3214 char *end;
3215
3216 if (zoned && getzoneid() == GLOBAL_ZONEID)
3217 return (ENOENT);
3218 if (isuser) {
3219 e = directory_sid_from_user_name(NULL,
3220 cp, &numericsid);
3221 } else {
3222 e = directory_sid_from_group_name(NULL,
3223 cp, &numericsid);
3224 }
3225 if (e != NULL) {
3226 directory_error_free(e);
3227 return (ENOENT);
3228 }
3229 if (numericsid == NULL)
3230 return (ENOENT);
3231 cp = numericsid;
3232 (void) strlcpy(domain, cp, domainlen);
3233 cp = strrchr(domain, '-');
3234 *cp = '\0';
3235 cp++;
3236
3237 errno = 0;
3238 *ridp = strtoull(cp, &end, 10);
3239 free(numericsid);
3240
3241 if (errno != 0 || *end != '\0')
3242 return (EINVAL);
3243 #else
3244 (void) domainlen;
3245 return (ENOSYS);
3246 #endif /* HAVE_IDMAP */
3247 } else {
3248 /* It's a user/group/project ID (eg "12345"). */
3249 uid_t id;
3250 char *end;
3251 id = strtoul(cp, &end, 10);
3252 if (*end != '\0')
3253 return (EINVAL);
3254 if (id > MAXUID && !isproject) {
3255 #ifdef HAVE_IDMAP
3256 /* It's an ephemeral ID. */
3257 idmap_rid_t rid;
3258 char *mapdomain;
3259
3260 if (idmap_id_to_numeric_domain_rid(id, isuser,
3261 &mapdomain, &rid) != 0)
3262 return (ENOENT);
3263 (void) strlcpy(domain, mapdomain, domainlen);
3264 *ridp = rid;
3265 #else
3266 return (ENOSYS);
3267 #endif /* HAVE_IDMAP */
3268 } else {
3269 *ridp = id;
3270 }
3271 }
3272
3273 return (0);
3274 }
3275
3276 static int
zfs_prop_get_userquota_common(zfs_handle_t * zhp,const char * propname,uint64_t * propvalue,zfs_userquota_prop_t * typep)3277 zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
3278 uint64_t *propvalue, zfs_userquota_prop_t *typep)
3279 {
3280 int err;
3281 zfs_cmd_t zc = {"\0"};
3282
3283 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3284
3285 err = userquota_propname_decode(propname,
3286 zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
3287 typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
3288 zc.zc_objset_type = *typep;
3289 if (err)
3290 return (err);
3291
3292 err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_USERSPACE_ONE, &zc);
3293 if (err)
3294 return (err);
3295
3296 *propvalue = zc.zc_cookie;
3297 return (0);
3298 }
3299
3300 int
zfs_prop_get_userquota_int(zfs_handle_t * zhp,const char * propname,uint64_t * propvalue)3301 zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
3302 uint64_t *propvalue)
3303 {
3304 zfs_userquota_prop_t type;
3305
3306 return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
3307 &type));
3308 }
3309
3310 int
zfs_prop_get_userquota(zfs_handle_t * zhp,const char * propname,char * propbuf,int proplen,boolean_t literal)3311 zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
3312 char *propbuf, int proplen, boolean_t literal)
3313 {
3314 int err;
3315 uint64_t propvalue;
3316 zfs_userquota_prop_t type;
3317
3318 err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
3319 &type);
3320
3321 if (err)
3322 return (err);
3323
3324 if (literal) {
3325 (void) snprintf(propbuf, proplen, "%llu",
3326 (u_longlong_t)propvalue);
3327 } else if (propvalue == 0 &&
3328 (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA ||
3329 type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA ||
3330 type == ZFS_PROP_PROJECTQUOTA ||
3331 type == ZFS_PROP_PROJECTOBJQUOTA)) {
3332 (void) strlcpy(propbuf, "none", proplen);
3333 } else if (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA ||
3334 type == ZFS_PROP_USERUSED || type == ZFS_PROP_GROUPUSED ||
3335 type == ZFS_PROP_PROJECTUSED || type == ZFS_PROP_PROJECTQUOTA) {
3336 zfs_nicebytes(propvalue, propbuf, proplen);
3337 } else {
3338 zfs_nicenum(propvalue, propbuf, proplen);
3339 }
3340 return (0);
3341 }
3342
3343 /*
3344 * propname must start with "written@" or "written#".
3345 */
3346 int
zfs_prop_get_written_int(zfs_handle_t * zhp,const char * propname,uint64_t * propvalue)3347 zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
3348 uint64_t *propvalue)
3349 {
3350 int err;
3351 zfs_cmd_t zc = {"\0"};
3352 const char *snapname;
3353
3354 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3355
3356 assert(zfs_prop_written(propname));
3357 snapname = propname + strlen("written@");
3358 if (strchr(snapname, '@') != NULL || strchr(snapname, '#') != NULL) {
3359 /* full snapshot or bookmark name specified */
3360 (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
3361 } else {
3362 /* snapname is the short name, append it to zhp's fsname */
3363 char *cp;
3364
3365 (void) strlcpy(zc.zc_value, zhp->zfs_name,
3366 sizeof (zc.zc_value));
3367 cp = strchr(zc.zc_value, '@');
3368 if (cp != NULL)
3369 *cp = '\0';
3370 (void) strlcat(zc.zc_value, snapname - 1, sizeof (zc.zc_value));
3371 }
3372
3373 err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SPACE_WRITTEN, &zc);
3374 if (err)
3375 return (err);
3376
3377 *propvalue = zc.zc_cookie;
3378 return (0);
3379 }
3380
3381 int
zfs_prop_get_written(zfs_handle_t * zhp,const char * propname,char * propbuf,int proplen,boolean_t literal)3382 zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
3383 char *propbuf, int proplen, boolean_t literal)
3384 {
3385 int err;
3386 uint64_t propvalue;
3387
3388 err = zfs_prop_get_written_int(zhp, propname, &propvalue);
3389
3390 if (err)
3391 return (err);
3392
3393 if (literal) {
3394 (void) snprintf(propbuf, proplen, "%llu",
3395 (u_longlong_t)propvalue);
3396 } else {
3397 zfs_nicebytes(propvalue, propbuf, proplen);
3398 }
3399
3400 return (0);
3401 }
3402
3403 /*
3404 * Returns the name of the given zfs handle.
3405 */
3406 const char *
zfs_get_name(const zfs_handle_t * zhp)3407 zfs_get_name(const zfs_handle_t *zhp)
3408 {
3409 return (zhp->zfs_name);
3410 }
3411
3412 /*
3413 * Returns the name of the parent pool for the given zfs handle.
3414 */
3415 const char *
zfs_get_pool_name(const zfs_handle_t * zhp)3416 zfs_get_pool_name(const zfs_handle_t *zhp)
3417 {
3418 return (zhp->zpool_hdl->zpool_name);
3419 }
3420
3421 /*
3422 * Returns the type of the given zfs handle.
3423 */
3424 zfs_type_t
zfs_get_type(const zfs_handle_t * zhp)3425 zfs_get_type(const zfs_handle_t *zhp)
3426 {
3427 return (zhp->zfs_type);
3428 }
3429
3430 /*
3431 * Returns the type of the given zfs handle,
3432 * or, if a snapshot, the type of the snapshotted dataset.
3433 */
3434 zfs_type_t
zfs_get_underlying_type(const zfs_handle_t * zhp)3435 zfs_get_underlying_type(const zfs_handle_t *zhp)
3436 {
3437 return (zhp->zfs_head_type);
3438 }
3439
3440 /*
3441 * Is one dataset name a child dataset of another?
3442 *
3443 * Needs to handle these cases:
3444 * Dataset 1 "a/foo" "a/foo" "a/foo" "a/foo"
3445 * Dataset 2 "a/fo" "a/foobar" "a/bar/baz" "a/foo/bar"
3446 * Descendant? No. No. No. Yes.
3447 */
3448 static boolean_t
is_descendant(const char * ds1,const char * ds2)3449 is_descendant(const char *ds1, const char *ds2)
3450 {
3451 size_t d1len = strlen(ds1);
3452
3453 /* ds2 can't be a descendant if it's smaller */
3454 if (strlen(ds2) < d1len)
3455 return (B_FALSE);
3456
3457 /* otherwise, compare strings and verify that there's a '/' char */
3458 return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0));
3459 }
3460
3461 /*
3462 * Given a complete name, return just the portion that refers to the parent.
3463 * Will return -1 if there is no parent (path is just the name of the
3464 * pool).
3465 */
3466 static int
parent_name(const char * path,char * buf,size_t buflen)3467 parent_name(const char *path, char *buf, size_t buflen)
3468 {
3469 char *slashp;
3470
3471 (void) strlcpy(buf, path, buflen);
3472
3473 if ((slashp = strrchr(buf, '/')) == NULL)
3474 return (-1);
3475 *slashp = '\0';
3476
3477 return (0);
3478 }
3479
3480 int
zfs_parent_name(zfs_handle_t * zhp,char * buf,size_t buflen)3481 zfs_parent_name(zfs_handle_t *zhp, char *buf, size_t buflen)
3482 {
3483 return (parent_name(zfs_get_name(zhp), buf, buflen));
3484 }
3485
3486 /*
3487 * If accept_ancestor is false, then check to make sure that the given path has
3488 * a parent, and that it exists. If accept_ancestor is true, then find the
3489 * closest existing ancestor for the given path. In prefixlen return the
3490 * length of already existing prefix of the given path. We also fetch the
3491 * 'zoned' property, which is used to validate property settings when creating
3492 * new datasets.
3493 */
3494 static int
check_parents(libzfs_handle_t * hdl,const char * path,uint64_t * zoned,boolean_t accept_ancestor,int * prefixlen)3495 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
3496 boolean_t accept_ancestor, int *prefixlen)
3497 {
3498 zfs_cmd_t zc = {"\0"};
3499 char parent[ZFS_MAX_DATASET_NAME_LEN];
3500 char *slash;
3501 zfs_handle_t *zhp;
3502 char errbuf[ERRBUFLEN];
3503 uint64_t is_zoned;
3504
3505 (void) snprintf(errbuf, sizeof (errbuf),
3506 dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
3507
3508 /* get parent, and check to see if this is just a pool */
3509 if (parent_name(path, parent, sizeof (parent)) != 0) {
3510 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3511 "missing dataset name"));
3512 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3513 }
3514
3515 /* check to see if the pool exists */
3516 if ((slash = strchr(parent, '/')) == NULL)
3517 slash = parent + strlen(parent);
3518 (void) strlcpy(zc.zc_name, parent,
3519 MIN(sizeof (zc.zc_name), slash - parent + 1));
3520 if (zfs_ioctl(hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
3521 errno == ENOENT) {
3522 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3523 "no such pool '%s'"), zc.zc_name);
3524 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3525 }
3526
3527 /* check to see if the parent dataset exists */
3528 while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
3529 if (errno == ENOENT && accept_ancestor) {
3530 /*
3531 * Go deeper to find an ancestor, give up on top level.
3532 */
3533 if (parent_name(parent, parent, sizeof (parent)) != 0) {
3534 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3535 "no such pool '%s'"), zc.zc_name);
3536 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3537 }
3538 } else if (errno == ENOENT) {
3539 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3540 "parent does not exist"));
3541 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3542 } else
3543 return (zfs_standard_error(hdl, errno, errbuf));
3544 }
3545
3546 is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
3547 if (zoned != NULL)
3548 *zoned = is_zoned;
3549
3550 /* we are in a non-global zone, but parent is in the global zone */
3551 if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
3552 (void) zfs_standard_error(hdl, EPERM, errbuf);
3553 zfs_close(zhp);
3554 return (-1);
3555 }
3556
3557 /* make sure parent is a filesystem */
3558 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
3559 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3560 "parent is not a filesystem"));
3561 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
3562 zfs_close(zhp);
3563 return (-1);
3564 }
3565
3566 zfs_close(zhp);
3567 if (prefixlen != NULL)
3568 *prefixlen = strlen(parent);
3569 return (0);
3570 }
3571
3572 /*
3573 * Finds whether the dataset of the given type(s) exists.
3574 */
3575 boolean_t
zfs_dataset_exists(libzfs_handle_t * hdl,const char * path,zfs_type_t types)3576 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
3577 {
3578 zfs_handle_t *zhp;
3579
3580 if (!zfs_validate_name(hdl, path, types, B_FALSE))
3581 return (B_FALSE);
3582
3583 /*
3584 * Try to get stats for the dataset, which will tell us if it exists.
3585 */
3586 if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
3587 int ds_type = zhp->zfs_type;
3588
3589 zfs_close(zhp);
3590 if (types & ds_type)
3591 return (B_TRUE);
3592 }
3593 return (B_FALSE);
3594 }
3595
3596 /*
3597 * Given a path to 'target', create all the ancestors between
3598 * the prefixlen portion of the path, and the target itself.
3599 * Fail if the initial prefixlen-ancestor does not already exist.
3600 */
3601 int
create_parents(libzfs_handle_t * hdl,char * target,int prefixlen)3602 create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
3603 {
3604 zfs_handle_t *h;
3605 char *cp;
3606 const char *opname;
3607
3608 /* make sure prefix exists */
3609 cp = target + prefixlen;
3610 if (*cp != '/') {
3611 assert(strchr(cp, '/') == NULL);
3612 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3613 } else {
3614 *cp = '\0';
3615 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3616 *cp = '/';
3617 }
3618 if (h == NULL)
3619 return (-1);
3620 zfs_close(h);
3621
3622 /*
3623 * Attempt to create, mount, and share any ancestor filesystems,
3624 * up to the prefixlen-long one.
3625 */
3626 for (cp = target + prefixlen + 1;
3627 (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) {
3628
3629 *cp = '\0';
3630
3631 h = make_dataset_handle(hdl, target);
3632 if (h) {
3633 /* it already exists, nothing to do here */
3634 zfs_close(h);
3635 continue;
3636 }
3637
3638 if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
3639 NULL) != 0) {
3640 opname = dgettext(TEXT_DOMAIN, "create");
3641 goto ancestorerr;
3642 }
3643
3644 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3645 if (h == NULL) {
3646 opname = dgettext(TEXT_DOMAIN, "open");
3647 goto ancestorerr;
3648 }
3649
3650 if (zfs_mount(h, NULL, 0) != 0) {
3651 opname = dgettext(TEXT_DOMAIN, "mount");
3652 goto ancestorerr;
3653 }
3654
3655 if (zfs_share(h, NULL) != 0) {
3656 opname = dgettext(TEXT_DOMAIN, "share");
3657 goto ancestorerr;
3658 }
3659
3660 zfs_close(h);
3661 }
3662 zfs_commit_shares(NULL);
3663
3664 return (0);
3665
3666 ancestorerr:
3667 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3668 "failed to %s ancestor '%s'"), opname, target);
3669 return (-1);
3670 }
3671
3672 /*
3673 * Creates non-existing ancestors of the given path.
3674 */
3675 int
zfs_create_ancestors(libzfs_handle_t * hdl,const char * path)3676 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
3677 {
3678 int prefix;
3679 char *path_copy;
3680 char errbuf[ERRBUFLEN];
3681 int rc = 0;
3682
3683 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3684 "cannot create '%s'"), path);
3685
3686 /*
3687 * Check that we are not passing the nesting limit
3688 * before we start creating any ancestors.
3689 */
3690 if (dataset_nestcheck(path) != 0) {
3691 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3692 "maximum name nesting depth exceeded"));
3693 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3694 }
3695
3696 if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
3697 return (-1);
3698
3699 if ((path_copy = strdup(path)) != NULL) {
3700 rc = create_parents(hdl, path_copy, prefix);
3701 free(path_copy);
3702 }
3703 if (path_copy == NULL || rc != 0)
3704 return (-1);
3705
3706 return (0);
3707 }
3708
3709 /*
3710 * Create a new filesystem or volume.
3711 */
3712 int
zfs_create(libzfs_handle_t * hdl,const char * path,zfs_type_t type,nvlist_t * props)3713 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
3714 nvlist_t *props)
3715 {
3716 int ret;
3717 uint64_t size = 0;
3718 uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
3719 uint64_t zoned;
3720 enum lzc_dataset_type ost;
3721 zpool_handle_t *zpool_handle;
3722 uint8_t *wkeydata = NULL;
3723 uint_t wkeylen = 0;
3724 char errbuf[ERRBUFLEN];
3725 char parent[ZFS_MAX_DATASET_NAME_LEN];
3726
3727 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3728 "cannot create '%s'"), path);
3729
3730 /* validate the path, taking care to note the extended error message */
3731 if (!zfs_validate_name(hdl, path, type, B_TRUE))
3732 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3733
3734 if (dataset_nestcheck(path) != 0) {
3735 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3736 "maximum name nesting depth exceeded"));
3737 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3738 }
3739
3740 /* validate parents exist */
3741 if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
3742 return (-1);
3743
3744 /*
3745 * The failure modes when creating a dataset of a different type over
3746 * one that already exists is a little strange. In particular, if you
3747 * try to create a dataset on top of an existing dataset, the ioctl()
3748 * will return ENOENT, not EEXIST. To prevent this from happening, we
3749 * first try to see if the dataset exists.
3750 */
3751 if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
3752 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3753 "dataset already exists"));
3754 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3755 }
3756
3757 if (type == ZFS_TYPE_VOLUME)
3758 ost = LZC_DATSET_TYPE_ZVOL;
3759 else
3760 ost = LZC_DATSET_TYPE_ZFS;
3761
3762 /* open zpool handle for prop validation */
3763 char pool_path[ZFS_MAX_DATASET_NAME_LEN];
3764 (void) strlcpy(pool_path, path, sizeof (pool_path));
3765
3766 /* truncate pool_path at first slash */
3767 char *p = strchr(pool_path, '/');
3768 if (p != NULL)
3769 *p = '\0';
3770
3771 if ((zpool_handle = zpool_open(hdl, pool_path)) == NULL)
3772 return (-1);
3773
3774 if (props && (props = zfs_valid_proplist(hdl, type, props,
3775 zoned, NULL, zpool_handle, B_TRUE, errbuf)) == 0) {
3776 zpool_close(zpool_handle);
3777 return (-1);
3778 }
3779 zpool_close(zpool_handle);
3780
3781 if (type == ZFS_TYPE_VOLUME) {
3782 /*
3783 * If we are creating a volume, the size and block size must
3784 * satisfy a few restraints. First, the blocksize must be a
3785 * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the
3786 * volsize must be a multiple of the block size, and cannot be
3787 * zero.
3788 */
3789 if (props == NULL || nvlist_lookup_uint64(props,
3790 zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
3791 nvlist_free(props);
3792 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3793 "missing volume size"));
3794 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3795 }
3796
3797 if ((ret = nvlist_lookup_uint64(props,
3798 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3799 &blocksize)) != 0) {
3800 if (ret == ENOENT) {
3801 blocksize = zfs_prop_default_numeric(
3802 ZFS_PROP_VOLBLOCKSIZE);
3803 } else {
3804 nvlist_free(props);
3805 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3806 "missing volume block size"));
3807 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3808 }
3809 }
3810
3811 if (size == 0) {
3812 nvlist_free(props);
3813 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3814 "volume size cannot be zero"));
3815 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3816 }
3817
3818 if (size % blocksize != 0) {
3819 nvlist_free(props);
3820 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3821 "volume size must be a multiple of volume block "
3822 "size"));
3823 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3824 }
3825 }
3826
3827 (void) parent_name(path, parent, sizeof (parent));
3828 if (zfs_crypto_create(hdl, parent, props, NULL, B_TRUE,
3829 &wkeydata, &wkeylen) != 0) {
3830 nvlist_free(props);
3831 return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf));
3832 }
3833
3834 /* create the dataset */
3835 ret = lzc_create(path, ost, props, wkeydata, wkeylen);
3836 nvlist_free(props);
3837 if (wkeydata != NULL)
3838 free(wkeydata);
3839
3840 /* check for failure */
3841 if (ret != 0) {
3842 switch (errno) {
3843 case ENOENT:
3844 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3845 "no such parent '%s'"), parent);
3846 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3847
3848 case ENOTSUP:
3849 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3850 "pool must be upgraded to set this "
3851 "property or value"));
3852 return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
3853
3854 case EACCES:
3855 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3856 "encryption root's key is not loaded "
3857 "or provided"));
3858 return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf));
3859
3860 case ERANGE:
3861 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3862 "invalid property value(s) specified"));
3863 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3864 #ifdef _ILP32
3865 case EOVERFLOW:
3866 /*
3867 * This platform can't address a volume this big.
3868 */
3869 if (type == ZFS_TYPE_VOLUME)
3870 return (zfs_error(hdl, EZFS_VOLTOOBIG,
3871 errbuf));
3872 zfs_fallthrough;
3873 #endif
3874 default:
3875 return (zfs_standard_error(hdl, errno, errbuf));
3876 }
3877 }
3878
3879 return (0);
3880 }
3881
3882 /*
3883 * Destroys the given dataset. The caller must make sure that the filesystem
3884 * isn't mounted, and that there are no active dependents. If the file system
3885 * does not exist this function does nothing.
3886 */
3887 int
zfs_destroy(zfs_handle_t * zhp,boolean_t defer)3888 zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
3889 {
3890 int error;
3891
3892 if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT && defer)
3893 return (EINVAL);
3894
3895 if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
3896 nvlist_t *nv = fnvlist_alloc();
3897 fnvlist_add_boolean(nv, zhp->zfs_name);
3898 error = lzc_destroy_bookmarks(nv, NULL);
3899 fnvlist_free(nv);
3900 if (error != 0) {
3901 return (zfs_standard_error_fmt(zhp->zfs_hdl, error,
3902 dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3903 zhp->zfs_name));
3904 }
3905 return (0);
3906 }
3907
3908 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3909 nvlist_t *nv = fnvlist_alloc();
3910 fnvlist_add_boolean(nv, zhp->zfs_name);
3911 error = lzc_destroy_snaps(nv, defer, NULL);
3912 fnvlist_free(nv);
3913 } else {
3914 error = lzc_destroy(zhp->zfs_name);
3915 }
3916
3917 if (error != 0 && error != ENOENT) {
3918 return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3919 dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3920 zhp->zfs_name));
3921 }
3922
3923 remove_mountpoint(zhp);
3924
3925 return (0);
3926 }
3927
3928 struct destroydata {
3929 nvlist_t *nvl;
3930 const char *snapname;
3931 };
3932
3933 static int
zfs_check_snap_cb(zfs_handle_t * zhp,void * arg)3934 zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
3935 {
3936 struct destroydata *dd = arg;
3937 char name[ZFS_MAX_DATASET_NAME_LEN];
3938 int rv = 0;
3939
3940 if (snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name,
3941 dd->snapname) >= sizeof (name))
3942 return (EINVAL);
3943
3944 if (lzc_exists(name))
3945 fnvlist_add_boolean(dd->nvl, name);
3946
3947 rv = zfs_iter_filesystems_v2(zhp, 0, zfs_check_snap_cb, dd);
3948 zfs_close(zhp);
3949 return (rv);
3950 }
3951
3952 /*
3953 * Destroys all snapshots with the given name in zhp & descendants.
3954 */
3955 int
zfs_destroy_snaps(zfs_handle_t * zhp,char * snapname,boolean_t defer)3956 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
3957 {
3958 int ret;
3959 struct destroydata dd = { 0 };
3960
3961 dd.snapname = snapname;
3962 dd.nvl = fnvlist_alloc();
3963 (void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
3964
3965 if (nvlist_empty(dd.nvl)) {
3966 ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3967 dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3968 zhp->zfs_name, snapname);
3969 } else {
3970 ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer);
3971 }
3972 fnvlist_free(dd.nvl);
3973 return (ret);
3974 }
3975
3976 /*
3977 * Destroys all the snapshots named in the nvlist.
3978 */
3979 int
zfs_destroy_snaps_nvl(libzfs_handle_t * hdl,nvlist_t * snaps,boolean_t defer)3980 zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
3981 {
3982 nvlist_t *errlist = NULL;
3983 nvpair_t *pair;
3984
3985 int ret = zfs_destroy_snaps_nvl_os(hdl, snaps);
3986 if (ret != 0)
3987 return (ret);
3988
3989 ret = lzc_destroy_snaps(snaps, defer, &errlist);
3990
3991 if (ret == 0) {
3992 nvlist_free(errlist);
3993 return (0);
3994 }
3995
3996 if (nvlist_empty(errlist)) {
3997 char errbuf[ERRBUFLEN];
3998 (void) snprintf(errbuf, sizeof (errbuf),
3999 dgettext(TEXT_DOMAIN, "cannot destroy snapshots"));
4000
4001 ret = zfs_standard_error(hdl, ret, errbuf);
4002 }
4003 for (pair = nvlist_next_nvpair(errlist, NULL);
4004 pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
4005 char errbuf[ERRBUFLEN];
4006 (void) snprintf(errbuf, sizeof (errbuf),
4007 dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
4008 nvpair_name(pair));
4009
4010 switch (fnvpair_value_int32(pair)) {
4011 case EEXIST:
4012 zfs_error_aux(hdl,
4013 dgettext(TEXT_DOMAIN, "snapshot is cloned"));
4014 ret = zfs_error(hdl, EZFS_EXISTS, errbuf);
4015 break;
4016 default:
4017 ret = zfs_standard_error(hdl, errno, errbuf);
4018 break;
4019 }
4020 }
4021
4022 nvlist_free(errlist);
4023 return (ret);
4024 }
4025
4026 /*
4027 * Clones the given dataset. The target must be of the same type as the source.
4028 */
4029 int
zfs_clone(zfs_handle_t * zhp,const char * target,nvlist_t * props)4030 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
4031 {
4032 char parent[ZFS_MAX_DATASET_NAME_LEN];
4033 int ret;
4034 char errbuf[ERRBUFLEN];
4035 libzfs_handle_t *hdl = zhp->zfs_hdl;
4036 uint64_t zoned;
4037
4038 assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
4039
4040 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4041 "cannot create '%s'"), target);
4042
4043 /* validate the target/clone name */
4044 if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
4045 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4046
4047 /* validate parents exist */
4048 if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
4049 return (-1);
4050
4051 (void) parent_name(target, parent, sizeof (parent));
4052
4053 /* do the clone */
4054
4055 if (props) {
4056 zfs_type_t type = ZFS_TYPE_FILESYSTEM;
4057
4058 if (ZFS_IS_VOLUME(zhp))
4059 type = ZFS_TYPE_VOLUME;
4060 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
4061 zhp, zhp->zpool_hdl, B_TRUE, errbuf)) == NULL)
4062 return (-1);
4063 if (zfs_fix_auto_resv(zhp, props) == -1) {
4064 nvlist_free(props);
4065 return (-1);
4066 }
4067 }
4068
4069 if (zfs_crypto_clone_check(hdl, zhp, parent, props) != 0) {
4070 nvlist_free(props);
4071 return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf));
4072 }
4073
4074 ret = lzc_clone(target, zhp->zfs_name, props);
4075 nvlist_free(props);
4076
4077 if (ret != 0) {
4078 switch (errno) {
4079
4080 case ENOENT:
4081 /*
4082 * The parent doesn't exist. We should have caught this
4083 * above, but there may a race condition that has since
4084 * destroyed the parent.
4085 *
4086 * At this point, we don't know whether it's the source
4087 * that doesn't exist anymore, or whether the target
4088 * dataset doesn't exist.
4089 */
4090 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
4091 "no such parent '%s'"), parent);
4092 return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
4093
4094 case EXDEV:
4095 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
4096 "source and target pools differ"));
4097 return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
4098 errbuf));
4099
4100 default:
4101 return (zfs_standard_error(zhp->zfs_hdl, errno,
4102 errbuf));
4103 }
4104 }
4105
4106 return (ret);
4107 }
4108
4109 /*
4110 * Promotes the given clone fs to be the clone parent.
4111 */
4112 int
zfs_promote(zfs_handle_t * zhp)4113 zfs_promote(zfs_handle_t *zhp)
4114 {
4115 libzfs_handle_t *hdl = zhp->zfs_hdl;
4116 char snapname[ZFS_MAX_DATASET_NAME_LEN];
4117 int ret;
4118 char errbuf[ERRBUFLEN];
4119
4120 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4121 "cannot promote '%s'"), zhp->zfs_name);
4122
4123 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
4124 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4125 "snapshots can not be promoted"));
4126 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4127 }
4128
4129 if (zhp->zfs_dmustats.dds_origin[0] == '\0') {
4130 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4131 "not a cloned filesystem"));
4132 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4133 }
4134
4135 if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
4136 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4137
4138 ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
4139
4140 if (ret != 0) {
4141 switch (ret) {
4142 case EACCES:
4143 /*
4144 * Promoting encrypted dataset outside its
4145 * encryption root.
4146 */
4147 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4148 "cannot promote dataset outside its "
4149 "encryption root"));
4150 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
4151
4152 case EEXIST:
4153 /* There is a conflicting snapshot name. */
4154 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4155 "conflicting snapshot '%s' from parent '%s'"),
4156 snapname, zhp->zfs_dmustats.dds_origin);
4157 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
4158
4159 default:
4160 return (zfs_standard_error(hdl, ret, errbuf));
4161 }
4162 }
4163 return (ret);
4164 }
4165
4166 typedef struct snapdata {
4167 nvlist_t *sd_nvl;
4168 const char *sd_snapname;
4169 } snapdata_t;
4170
4171 static int
zfs_snapshot_cb(zfs_handle_t * zhp,void * arg)4172 zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
4173 {
4174 snapdata_t *sd = arg;
4175 char name[ZFS_MAX_DATASET_NAME_LEN];
4176 int rv = 0;
4177
4178 if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
4179 if (snprintf(name, sizeof (name), "%s@%s", zfs_get_name(zhp),
4180 sd->sd_snapname) >= sizeof (name))
4181 return (EINVAL);
4182
4183 fnvlist_add_boolean(sd->sd_nvl, name);
4184
4185 rv = zfs_iter_filesystems_v2(zhp, 0, zfs_snapshot_cb, sd);
4186 }
4187 zfs_close(zhp);
4188
4189 return (rv);
4190 }
4191
4192 /*
4193 * Creates snapshots. The keys in the snaps nvlist are the snapshots to be
4194 * created.
4195 */
4196 int
zfs_snapshot_nvl(libzfs_handle_t * hdl,nvlist_t * snaps,nvlist_t * props)4197 zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
4198 {
4199 int ret;
4200 char errbuf[ERRBUFLEN];
4201 nvpair_t *elem;
4202 nvlist_t *errors;
4203 zpool_handle_t *zpool_hdl;
4204 char pool[ZFS_MAX_DATASET_NAME_LEN];
4205
4206 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4207 "cannot create snapshots "));
4208
4209 elem = NULL;
4210 while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
4211 const char *snapname = nvpair_name(elem);
4212
4213 /* validate the target name */
4214 if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
4215 B_TRUE)) {
4216 (void) snprintf(errbuf, sizeof (errbuf),
4217 dgettext(TEXT_DOMAIN,
4218 "cannot create snapshot '%s'"), snapname);
4219 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4220 }
4221 }
4222
4223 /*
4224 * get pool handle for prop validation. assumes all snaps are in the
4225 * same pool, as does lzc_snapshot (below).
4226 */
4227 elem = nvlist_next_nvpair(snaps, NULL);
4228 if (elem == NULL)
4229 return (-1);
4230 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
4231 pool[strcspn(pool, "/@")] = '\0';
4232 zpool_hdl = zpool_open(hdl, pool);
4233 if (zpool_hdl == NULL)
4234 return (-1);
4235
4236 if (props != NULL &&
4237 (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
4238 props, B_FALSE, NULL, zpool_hdl, B_FALSE, errbuf)) == NULL) {
4239 zpool_close(zpool_hdl);
4240 return (-1);
4241 }
4242 zpool_close(zpool_hdl);
4243
4244 ret = lzc_snapshot(snaps, props, &errors);
4245
4246 if (ret != 0) {
4247 boolean_t printed = B_FALSE;
4248 for (elem = nvlist_next_nvpair(errors, NULL);
4249 elem != NULL;
4250 elem = nvlist_next_nvpair(errors, elem)) {
4251 (void) snprintf(errbuf, sizeof (errbuf),
4252 dgettext(TEXT_DOMAIN,
4253 "cannot create snapshot '%s'"), nvpair_name(elem));
4254 (void) zfs_standard_error(hdl,
4255 fnvpair_value_int32(elem), errbuf);
4256 printed = B_TRUE;
4257 }
4258 if (!printed) {
4259 switch (ret) {
4260 case EXDEV:
4261 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4262 "multiple snapshots of same "
4263 "fs not allowed"));
4264 (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
4265
4266 break;
4267 default:
4268 (void) zfs_standard_error(hdl, ret, errbuf);
4269 }
4270 }
4271 }
4272
4273 nvlist_free(props);
4274 nvlist_free(errors);
4275 return (ret);
4276 }
4277
4278 int
zfs_snapshot(libzfs_handle_t * hdl,const char * path,boolean_t recursive,nvlist_t * props)4279 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
4280 nvlist_t *props)
4281 {
4282 int ret;
4283 snapdata_t sd = { 0 };
4284 char fsname[ZFS_MAX_DATASET_NAME_LEN];
4285 char *cp;
4286 zfs_handle_t *zhp;
4287 char errbuf[ERRBUFLEN];
4288
4289 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4290 "cannot snapshot %s"), path);
4291
4292 if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
4293 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4294
4295 (void) strlcpy(fsname, path, sizeof (fsname));
4296 cp = strchr(fsname, '@');
4297 *cp = '\0';
4298 sd.sd_snapname = cp + 1;
4299
4300 if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
4301 ZFS_TYPE_VOLUME)) == NULL) {
4302 return (-1);
4303 }
4304
4305 sd.sd_nvl = fnvlist_alloc();
4306 if (recursive) {
4307 (void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
4308 } else {
4309 fnvlist_add_boolean(sd.sd_nvl, path);
4310 }
4311
4312 ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
4313 fnvlist_free(sd.sd_nvl);
4314 zfs_close(zhp);
4315 return (ret);
4316 }
4317
4318 /*
4319 * Destroy any more recent snapshots. We invoke this callback on any dependents
4320 * of the snapshot first. If the 'cb_dependent' member is non-zero, then this
4321 * is a dependent and we should just destroy it without checking the transaction
4322 * group.
4323 */
4324 typedef struct rollback_data {
4325 const char *cb_target; /* the snapshot */
4326 uint64_t cb_create; /* creation time reference */
4327 boolean_t cb_error;
4328 boolean_t cb_force;
4329 } rollback_data_t;
4330
4331 static int
rollback_destroy_dependent(zfs_handle_t * zhp,void * data)4332 rollback_destroy_dependent(zfs_handle_t *zhp, void *data)
4333 {
4334 rollback_data_t *cbp = data;
4335 prop_changelist_t *clp;
4336
4337 /* We must destroy this clone; first unmount it */
4338 clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
4339 cbp->cb_force ? MS_FORCE: 0);
4340 if (clp == NULL || changelist_prefix(clp) != 0) {
4341 cbp->cb_error = B_TRUE;
4342 zfs_close(zhp);
4343 return (0);
4344 }
4345 if (zfs_destroy(zhp, B_FALSE) != 0)
4346 cbp->cb_error = B_TRUE;
4347 else
4348 changelist_remove(clp, zhp->zfs_name);
4349 (void) changelist_postfix(clp);
4350 changelist_free(clp);
4351
4352 zfs_close(zhp);
4353 return (0);
4354 }
4355
4356 static int
rollback_destroy(zfs_handle_t * zhp,void * data)4357 rollback_destroy(zfs_handle_t *zhp, void *data)
4358 {
4359 rollback_data_t *cbp = data;
4360
4361 if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
4362 cbp->cb_error |= zfs_iter_dependents_v2(zhp, 0, B_FALSE,
4363 rollback_destroy_dependent, cbp);
4364
4365 cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
4366 }
4367
4368 zfs_close(zhp);
4369 return (0);
4370 }
4371
4372 /*
4373 * Given a dataset, rollback to a specific snapshot, discarding any
4374 * data changes since then and making it the active dataset.
4375 *
4376 * Any snapshots and bookmarks more recent than the target are
4377 * destroyed, along with their dependents (i.e. clones).
4378 */
4379 int
zfs_rollback(zfs_handle_t * zhp,zfs_handle_t * snap,boolean_t force)4380 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
4381 {
4382 rollback_data_t cb = { 0 };
4383 int err;
4384 boolean_t restore_resv = 0;
4385 uint64_t old_volsize = 0, new_volsize;
4386 zfs_prop_t resv_prop = { 0 };
4387 uint64_t min_txg = 0;
4388
4389 assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
4390 zhp->zfs_type == ZFS_TYPE_VOLUME);
4391
4392 /*
4393 * Destroy all recent snapshots and their dependents.
4394 */
4395 cb.cb_force = force;
4396 cb.cb_target = snap->zfs_name;
4397 cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
4398
4399 if (cb.cb_create > 0)
4400 min_txg = cb.cb_create;
4401
4402 (void) zfs_iter_snapshots_v2(zhp, 0, rollback_destroy, &cb,
4403 min_txg, 0);
4404
4405 (void) zfs_iter_bookmarks_v2(zhp, 0, rollback_destroy, &cb);
4406
4407 if (cb.cb_error)
4408 return (-1);
4409
4410 /*
4411 * Now that we have verified that the snapshot is the latest,
4412 * rollback to the given snapshot.
4413 */
4414
4415 if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
4416 if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
4417 return (-1);
4418 old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
4419 restore_resv =
4420 (old_volsize == zfs_prop_get_int(zhp, resv_prop));
4421 }
4422
4423 /*
4424 * Pass both the filesystem and the wanted snapshot names,
4425 * we would get an error back if the snapshot is destroyed or
4426 * a new snapshot is created before this request is processed.
4427 */
4428 err = lzc_rollback_to(zhp->zfs_name, snap->zfs_name);
4429 if (err != 0) {
4430 char errbuf[ERRBUFLEN];
4431
4432 (void) snprintf(errbuf, sizeof (errbuf),
4433 dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
4434 zhp->zfs_name);
4435 switch (err) {
4436 case EEXIST:
4437 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
4438 "there is a snapshot or bookmark more recent "
4439 "than '%s'"), snap->zfs_name);
4440 (void) zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf);
4441 break;
4442 case ESRCH:
4443 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
4444 "'%s' is not found among snapshots of '%s'"),
4445 snap->zfs_name, zhp->zfs_name);
4446 (void) zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf);
4447 break;
4448 case EINVAL:
4449 (void) zfs_error(zhp->zfs_hdl, EZFS_BADTYPE, errbuf);
4450 break;
4451 default:
4452 (void) zfs_standard_error(zhp->zfs_hdl, err, errbuf);
4453 }
4454 return (err);
4455 }
4456
4457 /*
4458 * For volumes, if the pre-rollback volsize matched the pre-
4459 * rollback reservation and the volsize has changed then set
4460 * the reservation property to the post-rollback volsize.
4461 * Make a new handle since the rollback closed the dataset.
4462 */
4463 if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
4464 (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
4465 if (restore_resv) {
4466 new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
4467 if (old_volsize != new_volsize)
4468 err = zfs_prop_set_int(zhp, resv_prop,
4469 new_volsize);
4470 }
4471 zfs_close(zhp);
4472 }
4473 return (err);
4474 }
4475
4476 /*
4477 * Renames the given dataset.
4478 */
4479 int
zfs_rename(zfs_handle_t * zhp,const char * target,renameflags_t flags)4480 zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
4481 {
4482 int ret = 0;
4483 zfs_cmd_t zc = {"\0"};
4484 char *delim;
4485 prop_changelist_t *cl = NULL;
4486 char parent[ZFS_MAX_DATASET_NAME_LEN];
4487 char property[ZFS_MAXPROPLEN];
4488 libzfs_handle_t *hdl = zhp->zfs_hdl;
4489 char errbuf[ERRBUFLEN];
4490
4491 /* if we have the same exact name, just return success */
4492 if (strcmp(zhp->zfs_name, target) == 0)
4493 return (0);
4494
4495 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4496 "cannot rename to '%s'"), target);
4497
4498 /* make sure source name is valid */
4499 if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
4500 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4501
4502 /*
4503 * Make sure the target name is valid
4504 */
4505 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
4506 if ((strchr(target, '@') == NULL) ||
4507 *target == '@') {
4508 /*
4509 * Snapshot target name is abbreviated,
4510 * reconstruct full dataset name
4511 */
4512 (void) strlcpy(parent, zhp->zfs_name,
4513 sizeof (parent));
4514 delim = strchr(parent, '@');
4515 if (strchr(target, '@') == NULL)
4516 *(++delim) = '\0';
4517 else
4518 *delim = '\0';
4519 (void) strlcat(parent, target, sizeof (parent));
4520 target = parent;
4521 } else {
4522 /*
4523 * Make sure we're renaming within the same dataset.
4524 */
4525 delim = strchr(target, '@');
4526 if (strncmp(zhp->zfs_name, target, delim - target)
4527 != 0 || zhp->zfs_name[delim - target] != '@') {
4528 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4529 "snapshots must be part of same "
4530 "dataset"));
4531 return (zfs_error(hdl, EZFS_CROSSTARGET,
4532 errbuf));
4533 }
4534 }
4535
4536 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
4537 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4538 } else {
4539 if (flags.recursive) {
4540 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4541 "recursive rename must be a snapshot"));
4542 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4543 }
4544
4545 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
4546 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4547
4548 /* validate parents */
4549 if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0)
4550 return (-1);
4551
4552 /* make sure we're in the same pool */
4553 verify((delim = strchr(target, '/')) != NULL);
4554 if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
4555 zhp->zfs_name[delim - target] != '/') {
4556 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4557 "datasets must be within same pool"));
4558 return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
4559 }
4560
4561 /* new name cannot be a child of the current dataset name */
4562 if (is_descendant(zhp->zfs_name, target)) {
4563 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4564 "New dataset name cannot be a descendant of "
4565 "current dataset name"));
4566 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4567 }
4568 }
4569
4570 (void) snprintf(errbuf, sizeof (errbuf),
4571 dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
4572
4573 if (getzoneid() == GLOBAL_ZONEID &&
4574 zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
4575 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4576 "dataset is used in a non-global zone"));
4577 return (zfs_error(hdl, EZFS_ZONED, errbuf));
4578 }
4579
4580 /*
4581 * Avoid unmounting file systems with mountpoint property set to
4582 * 'legacy' or 'none' even if -u option is not given.
4583 */
4584 if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
4585 !flags.recursive && !flags.nounmount &&
4586 zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
4587 sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
4588 (strcmp(property, "legacy") == 0 ||
4589 strcmp(property, "none") == 0)) {
4590 flags.nounmount = B_TRUE;
4591 }
4592 if (flags.recursive) {
4593 char *parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
4594 delim = strchr(parentname, '@');
4595 *delim = '\0';
4596 zfs_handle_t *zhrp = zfs_open(zhp->zfs_hdl, parentname,
4597 ZFS_TYPE_DATASET);
4598 free(parentname);
4599 if (zhrp == NULL) {
4600 ret = -1;
4601 goto error;
4602 }
4603 zfs_close(zhrp);
4604 } else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) {
4605 if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
4606 flags.nounmount ? CL_GATHER_DONT_UNMOUNT :
4607 CL_GATHER_ITER_MOUNTED,
4608 flags.forceunmount ? MS_FORCE : 0)) == NULL)
4609 return (-1);
4610
4611 if (changelist_haszonedchild(cl)) {
4612 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4613 "child dataset with inherited mountpoint is used "
4614 "in a non-global zone"));
4615 (void) zfs_error(hdl, EZFS_ZONED, errbuf);
4616 ret = -1;
4617 goto error;
4618 }
4619
4620 if ((ret = changelist_prefix(cl)) != 0)
4621 goto error;
4622 }
4623
4624 if (ZFS_IS_VOLUME(zhp))
4625 zc.zc_objset_type = DMU_OST_ZVOL;
4626 else
4627 zc.zc_objset_type = DMU_OST_ZFS;
4628
4629 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4630 (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
4631
4632 zc.zc_cookie = !!flags.recursive;
4633 zc.zc_cookie |= (!!flags.nounmount) << 1;
4634
4635 if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
4636 /*
4637 * if it was recursive, the one that actually failed will
4638 * be in zc.zc_name
4639 */
4640 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4641 "cannot rename '%s'"), zc.zc_name);
4642
4643 if (flags.recursive && errno == EEXIST) {
4644 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4645 "a child dataset already has a snapshot "
4646 "with the new name"));
4647 (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
4648 } else if (errno == EACCES) {
4649 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4650 "cannot move encrypted child outside of "
4651 "its encryption root"));
4652 (void) zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
4653 } else {
4654 (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
4655 }
4656
4657 /*
4658 * On failure, we still want to remount any filesystems that
4659 * were previously mounted, so we don't alter the system state.
4660 */
4661 if (cl != NULL)
4662 (void) changelist_postfix(cl);
4663 } else {
4664 if (cl != NULL) {
4665 changelist_rename(cl, zfs_get_name(zhp), target);
4666 ret = changelist_postfix(cl);
4667 }
4668 }
4669
4670 error:
4671 if (cl != NULL) {
4672 changelist_free(cl);
4673 }
4674 return (ret);
4675 }
4676
4677 nvlist_t *
zfs_get_all_props(zfs_handle_t * zhp)4678 zfs_get_all_props(zfs_handle_t *zhp)
4679 {
4680 return (zhp->zfs_props);
4681 }
4682
4683 nvlist_t *
zfs_get_recvd_props(zfs_handle_t * zhp)4684 zfs_get_recvd_props(zfs_handle_t *zhp)
4685 {
4686 if (zhp->zfs_recvd_props == NULL)
4687 if (get_recvd_props_ioctl(zhp) != 0)
4688 return (NULL);
4689 return (zhp->zfs_recvd_props);
4690 }
4691
4692 nvlist_t *
zfs_get_user_props(zfs_handle_t * zhp)4693 zfs_get_user_props(zfs_handle_t *zhp)
4694 {
4695 return (zhp->zfs_user_props);
4696 }
4697
4698 /*
4699 * This function is used by 'zfs list' to determine the exact set of columns to
4700 * display, and their maximum widths. This does two main things:
4701 *
4702 * - If this is a list of all properties, then expand the list to include
4703 * all native properties, and set a flag so that for each dataset we look
4704 * for new unique user properties and add them to the list.
4705 *
4706 * - For non fixed-width properties, keep track of the maximum width seen
4707 * so that we can size the column appropriately. If the user has
4708 * requested received property values, we also need to compute the width
4709 * of the RECEIVED column.
4710 */
4711 int
zfs_expand_proplist(zfs_handle_t * zhp,zprop_list_t ** plp,boolean_t received,boolean_t literal)4712 zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
4713 boolean_t literal)
4714 {
4715 libzfs_handle_t *hdl = zhp->zfs_hdl;
4716 zprop_list_t *entry;
4717 zprop_list_t **last, **start;
4718 nvlist_t *userprops, *propval;
4719 nvpair_t *elem;
4720 const char *strval;
4721 char buf[ZFS_MAXPROPLEN];
4722
4723 if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
4724 return (-1);
4725
4726 userprops = zfs_get_user_props(zhp);
4727
4728 entry = *plp;
4729 if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
4730 /*
4731 * Go through and add any user properties as necessary. We
4732 * start by incrementing our list pointer to the first
4733 * non-native property.
4734 */
4735 start = plp;
4736 while (*start != NULL) {
4737 if ((*start)->pl_prop == ZPROP_USERPROP)
4738 break;
4739 start = &(*start)->pl_next;
4740 }
4741
4742 elem = NULL;
4743 while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
4744 /*
4745 * See if we've already found this property in our list.
4746 */
4747 for (last = start; *last != NULL;
4748 last = &(*last)->pl_next) {
4749 if (strcmp((*last)->pl_user_prop,
4750 nvpair_name(elem)) == 0)
4751 break;
4752 }
4753
4754 if (*last == NULL) {
4755 entry = zfs_alloc(hdl, sizeof (zprop_list_t));
4756 entry->pl_user_prop =
4757 zfs_strdup(hdl, nvpair_name(elem));
4758 entry->pl_prop = ZPROP_USERPROP;
4759 entry->pl_width = strlen(nvpair_name(elem));
4760 entry->pl_all = B_TRUE;
4761 *last = entry;
4762 }
4763 }
4764 }
4765
4766 /*
4767 * Now go through and check the width of any non-fixed columns
4768 */
4769 for (entry = *plp; entry != NULL; entry = entry->pl_next) {
4770 if (entry->pl_fixed && !literal)
4771 continue;
4772
4773 if (entry->pl_prop != ZPROP_USERPROP) {
4774 if (zfs_prop_get(zhp, entry->pl_prop,
4775 buf, sizeof (buf), NULL, NULL, 0, literal) == 0) {
4776 if (strlen(buf) > entry->pl_width)
4777 entry->pl_width = strlen(buf);
4778 }
4779 if (received && zfs_prop_get_recvd(zhp,
4780 zfs_prop_to_name(entry->pl_prop),
4781 buf, sizeof (buf), literal) == 0)
4782 if (strlen(buf) > entry->pl_recvd_width)
4783 entry->pl_recvd_width = strlen(buf);
4784 } else {
4785 if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop,
4786 &propval) == 0) {
4787 strval = fnvlist_lookup_string(propval,
4788 ZPROP_VALUE);
4789 if (strlen(strval) > entry->pl_width)
4790 entry->pl_width = strlen(strval);
4791 }
4792 if (received && zfs_prop_get_recvd(zhp,
4793 entry->pl_user_prop,
4794 buf, sizeof (buf), literal) == 0)
4795 if (strlen(buf) > entry->pl_recvd_width)
4796 entry->pl_recvd_width = strlen(buf);
4797 }
4798 }
4799
4800 return (0);
4801 }
4802
4803 void
zfs_prune_proplist(zfs_handle_t * zhp,uint8_t * props)4804 zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
4805 {
4806 nvpair_t *curr;
4807 nvpair_t *next;
4808
4809 /*
4810 * Keep a reference to the props-table against which we prune the
4811 * properties.
4812 */
4813 zhp->zfs_props_table = props;
4814
4815 curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
4816
4817 while (curr) {
4818 zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
4819 next = nvlist_next_nvpair(zhp->zfs_props, curr);
4820
4821 /*
4822 * User properties will result in ZPROP_USERPROP (an alias
4823 * for ZPROP_INVAL), and since we
4824 * only know how to prune standard ZFS properties, we always
4825 * leave these in the list. This can also happen if we
4826 * encounter an unknown DSL property (when running older
4827 * software, for example).
4828 */
4829 if (zfs_prop != ZPROP_USERPROP && props[zfs_prop] == B_FALSE)
4830 (void) nvlist_remove(zhp->zfs_props,
4831 nvpair_name(curr), nvpair_type(curr));
4832 curr = next;
4833 }
4834 }
4835
4836 static int
zfs_smb_acl_mgmt(libzfs_handle_t * hdl,char * dataset,char * path,zfs_smb_acl_op_t cmd,char * resource1,char * resource2)4837 zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
4838 zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
4839 {
4840 zfs_cmd_t zc = {"\0"};
4841 nvlist_t *nvlist = NULL;
4842 int error;
4843
4844 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4845 (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4846 zc.zc_cookie = (uint64_t)cmd;
4847
4848 if (cmd == ZFS_SMB_ACL_RENAME) {
4849 if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
4850 (void) no_memory(hdl);
4851 return (0);
4852 }
4853 }
4854
4855 switch (cmd) {
4856 case ZFS_SMB_ACL_ADD:
4857 case ZFS_SMB_ACL_REMOVE:
4858 (void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
4859 break;
4860 case ZFS_SMB_ACL_RENAME:
4861 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
4862 resource1) != 0) {
4863 (void) no_memory(hdl);
4864 return (-1);
4865 }
4866 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
4867 resource2) != 0) {
4868 (void) no_memory(hdl);
4869 return (-1);
4870 }
4871 zcmd_write_src_nvlist(hdl, &zc, nvlist);
4872 break;
4873 case ZFS_SMB_ACL_PURGE:
4874 break;
4875 default:
4876 return (-1);
4877 }
4878 error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
4879 nvlist_free(nvlist);
4880 return (error);
4881 }
4882
4883 int
zfs_smb_acl_add(libzfs_handle_t * hdl,char * dataset,char * path,char * resource)4884 zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
4885 char *path, char *resource)
4886 {
4887 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
4888 resource, NULL));
4889 }
4890
4891 int
zfs_smb_acl_remove(libzfs_handle_t * hdl,char * dataset,char * path,char * resource)4892 zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
4893 char *path, char *resource)
4894 {
4895 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
4896 resource, NULL));
4897 }
4898
4899 int
zfs_smb_acl_purge(libzfs_handle_t * hdl,char * dataset,char * path)4900 zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
4901 {
4902 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
4903 NULL, NULL));
4904 }
4905
4906 int
zfs_smb_acl_rename(libzfs_handle_t * hdl,char * dataset,char * path,char * oldname,char * newname)4907 zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
4908 char *oldname, char *newname)
4909 {
4910 return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
4911 oldname, newname));
4912 }
4913
4914 int
zfs_userspace(zfs_handle_t * zhp,zfs_userquota_prop_t type,zfs_userspace_cb_t func,void * arg)4915 zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4916 zfs_userspace_cb_t func, void *arg)
4917 {
4918 zfs_cmd_t zc = {"\0"};
4919 zfs_useracct_t buf[100];
4920 libzfs_handle_t *hdl = zhp->zfs_hdl;
4921 int ret;
4922
4923 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4924
4925 zc.zc_objset_type = type;
4926 zc.zc_nvlist_dst = (uintptr_t)buf;
4927
4928 for (;;) {
4929 zfs_useracct_t *zua = buf;
4930
4931 zc.zc_nvlist_dst_size = sizeof (buf);
4932 if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
4933 if ((errno == ENOTSUP &&
4934 (type == ZFS_PROP_USEROBJUSED ||
4935 type == ZFS_PROP_GROUPOBJUSED ||
4936 type == ZFS_PROP_USEROBJQUOTA ||
4937 type == ZFS_PROP_GROUPOBJQUOTA ||
4938 type == ZFS_PROP_PROJECTOBJUSED ||
4939 type == ZFS_PROP_PROJECTOBJQUOTA ||
4940 type == ZFS_PROP_PROJECTUSED ||
4941 type == ZFS_PROP_PROJECTQUOTA)))
4942 break;
4943
4944 return (zfs_standard_error_fmt(hdl, errno,
4945 dgettext(TEXT_DOMAIN,
4946 "cannot get used/quota for %s"), zc.zc_name));
4947 }
4948 if (zc.zc_nvlist_dst_size == 0)
4949 break;
4950
4951 while (zc.zc_nvlist_dst_size > 0) {
4952 if ((ret = func(arg, zua->zu_domain, zua->zu_rid,
4953 zua->zu_space)) != 0)
4954 return (ret);
4955 zua++;
4956 zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4957 }
4958 }
4959
4960 return (0);
4961 }
4962
4963 struct holdarg {
4964 nvlist_t *nvl;
4965 const char *snapname;
4966 const char *tag;
4967 boolean_t recursive;
4968 int error;
4969 };
4970
4971 static int
zfs_hold_one(zfs_handle_t * zhp,void * arg)4972 zfs_hold_one(zfs_handle_t *zhp, void *arg)
4973 {
4974 struct holdarg *ha = arg;
4975 char name[ZFS_MAX_DATASET_NAME_LEN];
4976 int rv = 0;
4977
4978 if (snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name,
4979 ha->snapname) >= sizeof (name))
4980 return (EINVAL);
4981
4982 if (lzc_exists(name))
4983 fnvlist_add_string(ha->nvl, name, ha->tag);
4984
4985 if (ha->recursive)
4986 rv = zfs_iter_filesystems_v2(zhp, 0, zfs_hold_one, ha);
4987 zfs_close(zhp);
4988 return (rv);
4989 }
4990
4991 int
zfs_hold(zfs_handle_t * zhp,const char * snapname,const char * tag,boolean_t recursive,int cleanup_fd)4992 zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4993 boolean_t recursive, int cleanup_fd)
4994 {
4995 int ret;
4996 struct holdarg ha;
4997
4998 ha.nvl = fnvlist_alloc();
4999 ha.snapname = snapname;
5000 ha.tag = tag;
5001 ha.recursive = recursive;
5002 (void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
5003
5004 if (nvlist_empty(ha.nvl)) {
5005 char errbuf[ERRBUFLEN];
5006
5007 fnvlist_free(ha.nvl);
5008 ret = ENOENT;
5009 (void) snprintf(errbuf, sizeof (errbuf),
5010 dgettext(TEXT_DOMAIN,
5011 "cannot hold snapshot '%s@%s'"),
5012 zhp->zfs_name, snapname);
5013 (void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf);
5014 return (ret);
5015 }
5016
5017 ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl);
5018 fnvlist_free(ha.nvl);
5019
5020 return (ret);
5021 }
5022
5023 int
zfs_hold_nvl(zfs_handle_t * zhp,int cleanup_fd,nvlist_t * holds)5024 zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds)
5025 {
5026 int ret;
5027 nvlist_t *errors;
5028 libzfs_handle_t *hdl = zhp->zfs_hdl;
5029 char errbuf[ERRBUFLEN];
5030 nvpair_t *elem;
5031
5032 errors = NULL;
5033 ret = lzc_hold(holds, cleanup_fd, &errors);
5034
5035 if (ret == 0) {
5036 /* There may be errors even in the success case. */
5037 fnvlist_free(errors);
5038 return (0);
5039 }
5040
5041 if (nvlist_empty(errors)) {
5042 /* no hold-specific errors */
5043 (void) snprintf(errbuf, sizeof (errbuf),
5044 dgettext(TEXT_DOMAIN, "cannot hold"));
5045 switch (ret) {
5046 case ENOTSUP:
5047 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5048 "pool must be upgraded"));
5049 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
5050 break;
5051 case EINVAL:
5052 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
5053 break;
5054 default:
5055 (void) zfs_standard_error(hdl, ret, errbuf);
5056 }
5057 }
5058
5059 for (elem = nvlist_next_nvpair(errors, NULL);
5060 elem != NULL;
5061 elem = nvlist_next_nvpair(errors, elem)) {
5062 (void) snprintf(errbuf, sizeof (errbuf),
5063 dgettext(TEXT_DOMAIN,
5064 "cannot hold snapshot '%s'"), nvpair_name(elem));
5065 switch (fnvpair_value_int32(elem)) {
5066 case E2BIG:
5067 /*
5068 * Temporary tags wind up having the ds object id
5069 * prepended. So even if we passed the length check
5070 * above, it's still possible for the tag to wind
5071 * up being slightly too long.
5072 */
5073 (void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
5074 break;
5075 case EINVAL:
5076 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
5077 break;
5078 case EEXIST:
5079 (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
5080 break;
5081 default:
5082 (void) zfs_standard_error(hdl,
5083 fnvpair_value_int32(elem), errbuf);
5084 }
5085 }
5086
5087 fnvlist_free(errors);
5088 return (ret);
5089 }
5090
5091 static int
zfs_release_one(zfs_handle_t * zhp,void * arg)5092 zfs_release_one(zfs_handle_t *zhp, void *arg)
5093 {
5094 struct holdarg *ha = arg;
5095 char name[ZFS_MAX_DATASET_NAME_LEN];
5096 int rv = 0;
5097 nvlist_t *existing_holds;
5098
5099 if (snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name,
5100 ha->snapname) >= sizeof (name)) {
5101 ha->error = EINVAL;
5102 rv = EINVAL;
5103 }
5104
5105 if (lzc_get_holds(name, &existing_holds) != 0) {
5106 ha->error = ENOENT;
5107 } else if (!nvlist_exists(existing_holds, ha->tag)) {
5108 ha->error = ESRCH;
5109 } else {
5110 nvlist_t *torelease = fnvlist_alloc();
5111 fnvlist_add_boolean(torelease, ha->tag);
5112 fnvlist_add_nvlist(ha->nvl, name, torelease);
5113 fnvlist_free(torelease);
5114 }
5115
5116 if (ha->recursive)
5117 rv = zfs_iter_filesystems_v2(zhp, 0, zfs_release_one, ha);
5118 zfs_close(zhp);
5119 return (rv);
5120 }
5121
5122 int
zfs_release(zfs_handle_t * zhp,const char * snapname,const char * tag,boolean_t recursive)5123 zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
5124 boolean_t recursive)
5125 {
5126 int ret;
5127 struct holdarg ha;
5128 nvlist_t *errors = NULL;
5129 nvpair_t *elem;
5130 libzfs_handle_t *hdl = zhp->zfs_hdl;
5131 char errbuf[ERRBUFLEN];
5132
5133 ha.nvl = fnvlist_alloc();
5134 ha.snapname = snapname;
5135 ha.tag = tag;
5136 ha.recursive = recursive;
5137 ha.error = 0;
5138 (void) zfs_release_one(zfs_handle_dup(zhp), &ha);
5139
5140 if (nvlist_empty(ha.nvl)) {
5141 fnvlist_free(ha.nvl);
5142 ret = ha.error;
5143 (void) snprintf(errbuf, sizeof (errbuf),
5144 dgettext(TEXT_DOMAIN,
5145 "cannot release hold from snapshot '%s@%s'"),
5146 zhp->zfs_name, snapname);
5147 if (ret == ESRCH) {
5148 (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
5149 } else {
5150 (void) zfs_standard_error(hdl, ret, errbuf);
5151 }
5152 return (ret);
5153 }
5154
5155 ret = lzc_release(ha.nvl, &errors);
5156 fnvlist_free(ha.nvl);
5157
5158 if (ret == 0) {
5159 /* There may be errors even in the success case. */
5160 fnvlist_free(errors);
5161 return (0);
5162 }
5163
5164 if (nvlist_empty(errors)) {
5165 /* no hold-specific errors */
5166 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
5167 "cannot release"));
5168 switch (errno) {
5169 case ENOTSUP:
5170 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5171 "pool must be upgraded"));
5172 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
5173 break;
5174 default:
5175 (void) zfs_standard_error(hdl, errno, errbuf);
5176 }
5177 }
5178
5179 for (elem = nvlist_next_nvpair(errors, NULL);
5180 elem != NULL;
5181 elem = nvlist_next_nvpair(errors, elem)) {
5182 (void) snprintf(errbuf, sizeof (errbuf),
5183 dgettext(TEXT_DOMAIN,
5184 "cannot release hold from snapshot '%s'"),
5185 nvpair_name(elem));
5186 switch (fnvpair_value_int32(elem)) {
5187 case ESRCH:
5188 (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
5189 break;
5190 case EINVAL:
5191 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
5192 break;
5193 default:
5194 (void) zfs_standard_error(hdl,
5195 fnvpair_value_int32(elem), errbuf);
5196 }
5197 }
5198
5199 fnvlist_free(errors);
5200 return (ret);
5201 }
5202
5203 int
zfs_get_fsacl(zfs_handle_t * zhp,nvlist_t ** nvl)5204 zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
5205 {
5206 zfs_cmd_t zc = {"\0"};
5207 libzfs_handle_t *hdl = zhp->zfs_hdl;
5208 int nvsz = 2048;
5209 void *nvbuf;
5210 int err = 0;
5211 char errbuf[ERRBUFLEN];
5212
5213 assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
5214 zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
5215
5216 tryagain:
5217
5218 nvbuf = malloc(nvsz);
5219 if (nvbuf == NULL) {
5220 err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
5221 goto out;
5222 }
5223
5224 zc.zc_nvlist_dst_size = nvsz;
5225 zc.zc_nvlist_dst = (uintptr_t)nvbuf;
5226
5227 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
5228
5229 if (zfs_ioctl(hdl, ZFS_IOC_GET_FSACL, &zc) != 0) {
5230 (void) snprintf(errbuf, sizeof (errbuf),
5231 dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
5232 zc.zc_name);
5233 switch (errno) {
5234 case ENOMEM:
5235 free(nvbuf);
5236 nvsz = zc.zc_nvlist_dst_size;
5237 goto tryagain;
5238
5239 case ENOTSUP:
5240 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5241 "pool must be upgraded"));
5242 err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
5243 break;
5244 case EINVAL:
5245 err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
5246 break;
5247 case ENOENT:
5248 err = zfs_error(hdl, EZFS_NOENT, errbuf);
5249 break;
5250 default:
5251 err = zfs_standard_error(hdl, errno, errbuf);
5252 break;
5253 }
5254 } else {
5255 /* success */
5256 int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
5257 if (rc) {
5258 err = zfs_standard_error_fmt(hdl, rc, dgettext(
5259 TEXT_DOMAIN, "cannot get permissions on '%s'"),
5260 zc.zc_name);
5261 }
5262 }
5263
5264 free(nvbuf);
5265 out:
5266 return (err);
5267 }
5268
5269 int
zfs_set_fsacl(zfs_handle_t * zhp,boolean_t un,nvlist_t * nvl)5270 zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
5271 {
5272 zfs_cmd_t zc = {"\0"};
5273 libzfs_handle_t *hdl = zhp->zfs_hdl;
5274 char *nvbuf;
5275 char errbuf[ERRBUFLEN];
5276 size_t nvsz;
5277 int err;
5278
5279 assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
5280 zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
5281
5282 err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
5283 assert(err == 0);
5284
5285 nvbuf = malloc(nvsz);
5286
5287 err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
5288 assert(err == 0);
5289
5290 zc.zc_nvlist_src_size = nvsz;
5291 zc.zc_nvlist_src = (uintptr_t)nvbuf;
5292 zc.zc_perm_action = un;
5293
5294 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
5295
5296 if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
5297 (void) snprintf(errbuf, sizeof (errbuf),
5298 dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
5299 zc.zc_name);
5300 switch (errno) {
5301 case ENOTSUP:
5302 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5303 "pool must be upgraded"));
5304 err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
5305 break;
5306 case EINVAL:
5307 err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
5308 break;
5309 case ENOENT:
5310 err = zfs_error(hdl, EZFS_NOENT, errbuf);
5311 break;
5312 default:
5313 err = zfs_standard_error(hdl, errno, errbuf);
5314 break;
5315 }
5316 }
5317
5318 free(nvbuf);
5319
5320 return (err);
5321 }
5322
5323 int
zfs_get_holds(zfs_handle_t * zhp,nvlist_t ** nvl)5324 zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
5325 {
5326 int err;
5327 char errbuf[ERRBUFLEN];
5328
5329 err = lzc_get_holds(zhp->zfs_name, nvl);
5330
5331 if (err != 0) {
5332 libzfs_handle_t *hdl = zhp->zfs_hdl;
5333
5334 (void) snprintf(errbuf, sizeof (errbuf),
5335 dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
5336 zhp->zfs_name);
5337 switch (err) {
5338 case ENOTSUP:
5339 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5340 "pool must be upgraded"));
5341 err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
5342 break;
5343 case EINVAL:
5344 err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
5345 break;
5346 case ENOENT:
5347 err = zfs_error(hdl, EZFS_NOENT, errbuf);
5348 break;
5349 default:
5350 err = zfs_standard_error(hdl, errno, errbuf);
5351 break;
5352 }
5353 }
5354
5355 return (err);
5356 }
5357
5358 /*
5359 * The theory of raidz space accounting
5360 *
5361 * The "referenced" property of RAIDZ vdevs is scaled such that a 128KB block
5362 * will "reference" 128KB, even though it allocates more than that, to store the
5363 * parity information (and perhaps skip sectors). This concept of the
5364 * "referenced" (and other DMU space accounting) being lower than the allocated
5365 * space by a constant factor is called "raidz deflation."
5366 *
5367 * As mentioned above, the constant factor for raidz deflation assumes a 128KB
5368 * block size. However, zvols typically have a much smaller block size (default
5369 * 8KB). These smaller blocks may require proportionally much more parity
5370 * information (and perhaps skip sectors). In this case, the change to the
5371 * "referenced" property may be much more than the logical block size.
5372 *
5373 * Suppose a raidz vdev has 5 disks with ashift=12. A 128k block may be written
5374 * as follows.
5375 *
5376 * +-------+-------+-------+-------+-------+
5377 * | disk1 | disk2 | disk3 | disk4 | disk5 |
5378 * +-------+-------+-------+-------+-------+
5379 * | P0 | D0 | D8 | D16 | D24 |
5380 * | P1 | D1 | D9 | D17 | D25 |
5381 * | P2 | D2 | D10 | D18 | D26 |
5382 * | P3 | D3 | D11 | D19 | D27 |
5383 * | P4 | D4 | D12 | D20 | D28 |
5384 * | P5 | D5 | D13 | D21 | D29 |
5385 * | P6 | D6 | D14 | D22 | D30 |
5386 * | P7 | D7 | D15 | D23 | D31 |
5387 * +-------+-------+-------+-------+-------+
5388 *
5389 * Above, notice that 160k was allocated: 8 x 4k parity sectors + 32 x 4k data
5390 * sectors. The dataset's referenced will increase by 128k and the pool's
5391 * allocated and free properties will be adjusted by 160k.
5392 *
5393 * A 4k block written to the same raidz vdev will require two 4k sectors. The
5394 * blank cells represent unallocated space.
5395 *
5396 * +-------+-------+-------+-------+-------+
5397 * | disk1 | disk2 | disk3 | disk4 | disk5 |
5398 * +-------+-------+-------+-------+-------+
5399 * | P0 | D0 | | | |
5400 * +-------+-------+-------+-------+-------+
5401 *
5402 * Above, notice that the 4k block required one sector for parity and another
5403 * for data. vdev_raidz_asize() will return 8k and as such the pool's allocated
5404 * and free properties will be adjusted by 8k. The dataset will not be charged
5405 * 8k. Rather, it will be charged a value that is scaled according to the
5406 * overhead of the 128k block on the same vdev. This 8k allocation will be
5407 * charged 8k * 128k / 160k. 128k is from SPA_OLD_MAXBLOCKSIZE and 160k is as
5408 * calculated in the 128k block example above.
5409 *
5410 * Every raidz allocation is sized to be a multiple of nparity+1 sectors. That
5411 * is, every raidz1 allocation will be a multiple of 2 sectors, raidz2
5412 * allocations are a multiple of 3 sectors, and raidz3 allocations are a
5413 * multiple of of 4 sectors. When a block does not fill the required number of
5414 * sectors, skip blocks (sectors) are used.
5415 *
5416 * An 8k block being written to a raidz vdev may be written as follows:
5417 *
5418 * +-------+-------+-------+-------+-------+
5419 * | disk1 | disk2 | disk3 | disk4 | disk5 |
5420 * +-------+-------+-------+-------+-------+
5421 * | P0 | D0 | D1 | S0 | |
5422 * +-------+-------+-------+-------+-------+
5423 *
5424 * In order to maintain the nparity+1 allocation size, a skip block (S0) was
5425 * added. For this 8k block, the pool's allocated and free properties are
5426 * adjusted by 16k and the dataset's referenced is increased by 16k * 128k /
5427 * 160k. Again, 128k is from SPA_OLD_MAXBLOCKSIZE and 160k is as calculated in
5428 * the 128k block example above.
5429 *
5430 * The situation is slightly different for dRAID since the minimum allocation
5431 * size is the full group width. The same 8K block above would be written as
5432 * follows in a dRAID group:
5433 *
5434 * +-------+-------+-------+-------+-------+
5435 * | disk1 | disk2 | disk3 | disk4 | disk5 |
5436 * +-------+-------+-------+-------+-------+
5437 * | P0 | D0 | D1 | S0 | S1 |
5438 * +-------+-------+-------+-------+-------+
5439 *
5440 * Compression may lead to a variety of block sizes being written for the same
5441 * volume or file. There is no clear way to reserve just the amount of space
5442 * that will be required, so the worst case (no compression) is assumed.
5443 * Note that metadata blocks will typically be compressed, so the reservation
5444 * size returned by zvol_volsize_to_reservation() will generally be slightly
5445 * larger than the maximum that the volume can reference.
5446 */
5447
5448 /*
5449 * Derived from function of same name in module/zfs/vdev_raidz.c. Returns the
5450 * amount of space (in bytes) that will be allocated for the specified block
5451 * size. Note that the "referenced" space accounted will be less than this, but
5452 * not necessarily equal to "blksize", due to RAIDZ deflation.
5453 */
5454 static uint64_t
vdev_raidz_asize(uint64_t ndisks,uint64_t nparity,uint64_t ashift,uint64_t blksize)5455 vdev_raidz_asize(uint64_t ndisks, uint64_t nparity, uint64_t ashift,
5456 uint64_t blksize)
5457 {
5458 uint64_t asize, ndata;
5459
5460 ASSERT3U(ndisks, >, nparity);
5461 ndata = ndisks - nparity;
5462 asize = ((blksize - 1) >> ashift) + 1;
5463 asize += nparity * ((asize + ndata - 1) / ndata);
5464 asize = roundup(asize, nparity + 1) << ashift;
5465
5466 return (asize);
5467 }
5468
5469 /*
5470 * Derived from function of same name in module/zfs/vdev_draid.c. Returns the
5471 * amount of space (in bytes) that will be allocated for the specified block
5472 * size.
5473 */
5474 static uint64_t
vdev_draid_asize(uint64_t ndisks,uint64_t nparity,uint64_t ashift,uint64_t blksize)5475 vdev_draid_asize(uint64_t ndisks, uint64_t nparity, uint64_t ashift,
5476 uint64_t blksize)
5477 {
5478 ASSERT3U(ndisks, >, nparity);
5479 uint64_t ndata = ndisks - nparity;
5480 uint64_t rows = ((blksize - 1) / (ndata << ashift)) + 1;
5481 uint64_t asize = (rows * ndisks) << ashift;
5482
5483 return (asize);
5484 }
5485
5486 /*
5487 * Determine how much space will be allocated if it lands on the most space-
5488 * inefficient top-level vdev. Returns the size in bytes required to store one
5489 * copy of the volume data. See theory comment above.
5490 */
5491 static uint64_t
volsize_from_vdevs(zpool_handle_t * zhp,uint64_t nblocks,uint64_t blksize)5492 volsize_from_vdevs(zpool_handle_t *zhp, uint64_t nblocks, uint64_t blksize)
5493 {
5494 nvlist_t *config, *tree, **vdevs;
5495 uint_t nvdevs;
5496 uint64_t ret = 0;
5497
5498 config = zpool_get_config(zhp, NULL);
5499 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree) != 0 ||
5500 nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN,
5501 &vdevs, &nvdevs) != 0) {
5502 return (nblocks * blksize);
5503 }
5504
5505 for (int v = 0; v < nvdevs; v++) {
5506 const char *type;
5507 uint64_t nparity, ashift, asize, tsize;
5508 uint64_t volsize;
5509
5510 if (nvlist_lookup_string(vdevs[v], ZPOOL_CONFIG_TYPE,
5511 &type) != 0)
5512 continue;
5513
5514 if (strcmp(type, VDEV_TYPE_RAIDZ) != 0 &&
5515 strcmp(type, VDEV_TYPE_DRAID) != 0)
5516 continue;
5517
5518 if (nvlist_lookup_uint64(vdevs[v],
5519 ZPOOL_CONFIG_NPARITY, &nparity) != 0)
5520 continue;
5521
5522 if (nvlist_lookup_uint64(vdevs[v],
5523 ZPOOL_CONFIG_ASHIFT, &ashift) != 0)
5524 continue;
5525
5526 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
5527 nvlist_t **disks;
5528 uint_t ndisks;
5529
5530 if (nvlist_lookup_nvlist_array(vdevs[v],
5531 ZPOOL_CONFIG_CHILDREN, &disks, &ndisks) != 0)
5532 continue;
5533
5534 /* allocation size for the "typical" 128k block */
5535 tsize = vdev_raidz_asize(ndisks, nparity, ashift,
5536 SPA_OLD_MAXBLOCKSIZE);
5537
5538 /* allocation size for the blksize block */
5539 asize = vdev_raidz_asize(ndisks, nparity, ashift,
5540 blksize);
5541 } else {
5542 uint64_t ndata;
5543
5544 if (nvlist_lookup_uint64(vdevs[v],
5545 ZPOOL_CONFIG_DRAID_NDATA, &ndata) != 0)
5546 continue;
5547
5548 /* allocation size for the "typical" 128k block */
5549 tsize = vdev_draid_asize(ndata + nparity, nparity,
5550 ashift, SPA_OLD_MAXBLOCKSIZE);
5551
5552 /* allocation size for the blksize block */
5553 asize = vdev_draid_asize(ndata + nparity, nparity,
5554 ashift, blksize);
5555 }
5556
5557 /*
5558 * Scale this size down as a ratio of 128k / tsize.
5559 * See theory statement above.
5560 */
5561 volsize = nblocks * asize * SPA_OLD_MAXBLOCKSIZE / tsize;
5562 if (volsize > ret) {
5563 ret = volsize;
5564 }
5565 }
5566
5567 if (ret == 0) {
5568 ret = nblocks * blksize;
5569 }
5570
5571 return (ret);
5572 }
5573
5574 /*
5575 * Convert the zvol's volume size to an appropriate reservation. See theory
5576 * comment above.
5577 *
5578 * Note: If this routine is updated, it is necessary to update the ZFS test
5579 * suite's shell version in reservation.shlib.
5580 */
5581 uint64_t
zvol_volsize_to_reservation(zpool_handle_t * zph,uint64_t volsize,nvlist_t * props)5582 zvol_volsize_to_reservation(zpool_handle_t *zph, uint64_t volsize,
5583 nvlist_t *props)
5584 {
5585 uint64_t numdb;
5586 uint64_t nblocks, volblocksize;
5587 int ncopies;
5588 const char *strval;
5589
5590 if (nvlist_lookup_string(props,
5591 zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
5592 ncopies = atoi(strval);
5593 else
5594 ncopies = 1;
5595 if (nvlist_lookup_uint64(props,
5596 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
5597 &volblocksize) != 0)
5598 volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
5599
5600 nblocks = volsize / volblocksize;
5601 /*
5602 * Metadata defaults to using 128k blocks, not volblocksize blocks. For
5603 * this reason, only the data blocks are scaled based on vdev config.
5604 */
5605 volsize = volsize_from_vdevs(zph, nblocks, volblocksize);
5606
5607 /* start with metadnode L0-L6 */
5608 numdb = 7;
5609 /* calculate number of indirects */
5610 while (nblocks > 1) {
5611 nblocks += DNODES_PER_LEVEL - 1;
5612 nblocks /= DNODES_PER_LEVEL;
5613 numdb += nblocks;
5614 }
5615 numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1);
5616 volsize *= ncopies;
5617 /*
5618 * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't
5619 * compressed, but in practice they compress down to about
5620 * 1100 bytes
5621 */
5622 numdb *= 1ULL << DN_MAX_INDBLKSHIFT;
5623 volsize += numdb;
5624 return (volsize);
5625 }
5626
5627 /*
5628 * Wait for the given activity and return the status of the wait (whether or not
5629 * any waiting was done) in the 'waited' parameter. Non-existent fses are
5630 * reported via the 'missing' parameter, rather than by printing an error
5631 * message. This is convenient when this function is called in a loop over a
5632 * long period of time (as it is, for example, by zfs's wait cmd). In that
5633 * scenario, a fs being exported or destroyed should be considered a normal
5634 * event, so we don't want to print an error when we find that the fs doesn't
5635 * exist.
5636 */
5637 int
zfs_wait_status(zfs_handle_t * zhp,zfs_wait_activity_t activity,boolean_t * missing,boolean_t * waited)5638 zfs_wait_status(zfs_handle_t *zhp, zfs_wait_activity_t activity,
5639 boolean_t *missing, boolean_t *waited)
5640 {
5641 int error = lzc_wait_fs(zhp->zfs_name, activity, waited);
5642 *missing = (error == ENOENT);
5643 if (*missing)
5644 return (0);
5645
5646 if (error != 0) {
5647 (void) zfs_standard_error_fmt(zhp->zfs_hdl, error,
5648 dgettext(TEXT_DOMAIN, "error waiting in fs '%s'"),
5649 zhp->zfs_name);
5650 }
5651
5652 return (error);
5653 }
5654