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