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