Print this page
OS-1566 filesystem limits for ZFS datasets
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libzfs/common/libzfs_util.c
+++ new/usr/src/lib/libzfs/common/libzfs_util.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
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 24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25 25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Internal utility routines for the ZFS library.
30 30 */
31 31
32 32 #include <errno.h>
33 33 #include <fcntl.h>
34 34 #include <libintl.h>
35 35 #include <stdarg.h>
36 36 #include <stdio.h>
37 37 #include <stdlib.h>
38 38 #include <strings.h>
39 39 #include <unistd.h>
40 40 #include <ctype.h>
41 41 #include <math.h>
42 42 #include <sys/mnttab.h>
43 43 #include <sys/mntent.h>
44 44 #include <sys/types.h>
45 45
46 46 #include <libzfs.h>
47 47 #include <libzfs_core.h>
48 48
49 49 #include "libzfs_impl.h"
50 50 #include "zfs_prop.h"
51 51 #include "zfeature_common.h"
52 52
53 53 int
54 54 libzfs_errno(libzfs_handle_t *hdl)
55 55 {
56 56 return (hdl->libzfs_error);
57 57 }
58 58
59 59 const char *
60 60 libzfs_error_action(libzfs_handle_t *hdl)
61 61 {
62 62 return (hdl->libzfs_action);
63 63 }
64 64
65 65 const char *
66 66 libzfs_error_description(libzfs_handle_t *hdl)
67 67 {
68 68 if (hdl->libzfs_desc[0] != '\0')
69 69 return (hdl->libzfs_desc);
70 70
71 71 switch (hdl->libzfs_error) {
72 72 case EZFS_NOMEM:
73 73 return (dgettext(TEXT_DOMAIN, "out of memory"));
74 74 case EZFS_BADPROP:
75 75 return (dgettext(TEXT_DOMAIN, "invalid property value"));
76 76 case EZFS_PROPREADONLY:
77 77 return (dgettext(TEXT_DOMAIN, "read-only property"));
78 78 case EZFS_PROPTYPE:
79 79 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
80 80 "datasets of this type"));
81 81 case EZFS_PROPNONINHERIT:
82 82 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
83 83 case EZFS_PROPSPACE:
84 84 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
85 85 case EZFS_PROPCACHED:
86 86 return (dgettext(TEXT_DOMAIN, "property unavailable since "
87 87 "cachedprops flag set"));
88 88 case EZFS_BADTYPE:
89 89 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
90 90 "datasets of this type"));
91 91 case EZFS_BUSY:
92 92 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
93 93 case EZFS_EXISTS:
94 94 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
95 95 case EZFS_NOENT:
96 96 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
97 97 case EZFS_BADSTREAM:
98 98 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
99 99 case EZFS_DSREADONLY:
100 100 return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
101 101 case EZFS_VOLTOOBIG:
102 102 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
103 103 "this system"));
104 104 case EZFS_INVALIDNAME:
105 105 return (dgettext(TEXT_DOMAIN, "invalid name"));
106 106 case EZFS_BADRESTORE:
107 107 return (dgettext(TEXT_DOMAIN, "unable to restore to "
108 108 "destination"));
109 109 case EZFS_BADBACKUP:
110 110 return (dgettext(TEXT_DOMAIN, "backup failed"));
111 111 case EZFS_BADTARGET:
112 112 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
113 113 case EZFS_NODEVICE:
114 114 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
115 115 case EZFS_BADDEV:
116 116 return (dgettext(TEXT_DOMAIN, "invalid device"));
117 117 case EZFS_NOREPLICAS:
118 118 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
119 119 case EZFS_RESILVERING:
120 120 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
121 121 case EZFS_BADVERSION:
122 122 return (dgettext(TEXT_DOMAIN, "unsupported version or "
123 123 "feature"));
124 124 case EZFS_POOLUNAVAIL:
125 125 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
126 126 case EZFS_DEVOVERFLOW:
127 127 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
128 128 case EZFS_BADPATH:
129 129 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
130 130 case EZFS_CROSSTARGET:
131 131 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
132 132 "pools"));
133 133 case EZFS_ZONED:
134 134 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
135 135 case EZFS_MOUNTFAILED:
136 136 return (dgettext(TEXT_DOMAIN, "mount failed"));
137 137 case EZFS_UMOUNTFAILED:
138 138 return (dgettext(TEXT_DOMAIN, "umount failed"));
139 139 case EZFS_UNSHARENFSFAILED:
140 140 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
141 141 case EZFS_SHARENFSFAILED:
142 142 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
143 143 case EZFS_UNSHARESMBFAILED:
144 144 return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
145 145 case EZFS_SHARESMBFAILED:
146 146 return (dgettext(TEXT_DOMAIN, "smb add share failed"));
147 147 case EZFS_PERM:
148 148 return (dgettext(TEXT_DOMAIN, "permission denied"));
149 149 case EZFS_NOSPC:
150 150 return (dgettext(TEXT_DOMAIN, "out of space"));
151 151 case EZFS_FAULT:
152 152 return (dgettext(TEXT_DOMAIN, "bad address"));
153 153 case EZFS_IO:
154 154 return (dgettext(TEXT_DOMAIN, "I/O error"));
155 155 case EZFS_INTR:
156 156 return (dgettext(TEXT_DOMAIN, "signal received"));
157 157 case EZFS_ISSPARE:
158 158 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
159 159 "spare"));
160 160 case EZFS_INVALCONFIG:
161 161 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
162 162 case EZFS_RECURSIVE:
163 163 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
164 164 case EZFS_NOHISTORY:
165 165 return (dgettext(TEXT_DOMAIN, "no history available"));
166 166 case EZFS_POOLPROPS:
167 167 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
168 168 "pool properties"));
169 169 case EZFS_POOL_NOTSUP:
170 170 return (dgettext(TEXT_DOMAIN, "operation not supported "
171 171 "on this type of pool"));
172 172 case EZFS_POOL_INVALARG:
173 173 return (dgettext(TEXT_DOMAIN, "invalid argument for "
174 174 "this pool operation"));
175 175 case EZFS_NAMETOOLONG:
176 176 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
177 177 case EZFS_OPENFAILED:
178 178 return (dgettext(TEXT_DOMAIN, "open failed"));
179 179 case EZFS_NOCAP:
180 180 return (dgettext(TEXT_DOMAIN,
181 181 "disk capacity information could not be retrieved"));
182 182 case EZFS_LABELFAILED:
183 183 return (dgettext(TEXT_DOMAIN, "write of label failed"));
184 184 case EZFS_BADWHO:
185 185 return (dgettext(TEXT_DOMAIN, "invalid user/group"));
186 186 case EZFS_BADPERM:
187 187 return (dgettext(TEXT_DOMAIN, "invalid permission"));
188 188 case EZFS_BADPERMSET:
189 189 return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
190 190 case EZFS_NODELEGATION:
191 191 return (dgettext(TEXT_DOMAIN, "delegated administration is "
192 192 "disabled on pool"));
193 193 case EZFS_BADCACHE:
194 194 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
195 195 case EZFS_ISL2CACHE:
196 196 return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
197 197 case EZFS_VDEVNOTSUP:
198 198 return (dgettext(TEXT_DOMAIN, "vdev specification is not "
199 199 "supported"));
200 200 case EZFS_NOTSUP:
201 201 return (dgettext(TEXT_DOMAIN, "operation not supported "
202 202 "on this dataset"));
203 203 case EZFS_ACTIVE_SPARE:
204 204 return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
205 205 "device"));
206 206 case EZFS_UNPLAYED_LOGS:
207 207 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
208 208 "logs"));
209 209 case EZFS_REFTAG_RELE:
210 210 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
211 211 case EZFS_REFTAG_HOLD:
212 212 return (dgettext(TEXT_DOMAIN, "tag already exists on this "
213 213 "dataset"));
214 214 case EZFS_TAGTOOLONG:
215 215 return (dgettext(TEXT_DOMAIN, "tag too long"));
216 216 case EZFS_PIPEFAILED:
217 217 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
218 218 case EZFS_THREADCREATEFAILED:
219 219 return (dgettext(TEXT_DOMAIN, "thread create failed"));
220 220 case EZFS_POSTSPLIT_ONLINE:
221 221 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
222 222 "into a new one"));
223 223 case EZFS_SCRUBBING:
224 224 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
225 225 "use 'zpool scrub -s' to cancel current scrub"));
226 226 case EZFS_NO_SCRUB:
227 227 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
228 228 case EZFS_DIFF:
229 229 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
230 230 case EZFS_DIFFDATA:
231 231 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
232 232 case EZFS_POOLREADONLY:
233 233 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
234 234 case EZFS_UNKNOWN:
235 235 return (dgettext(TEXT_DOMAIN, "unknown error"));
236 236 default:
237 237 assert(hdl->libzfs_error == 0);
238 238 return (dgettext(TEXT_DOMAIN, "no error"));
239 239 }
240 240 }
241 241
242 242 /*PRINTFLIKE2*/
243 243 void
244 244 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
245 245 {
246 246 va_list ap;
247 247
248 248 va_start(ap, fmt);
249 249
250 250 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
251 251 fmt, ap);
252 252 hdl->libzfs_desc_active = 1;
253 253
254 254 va_end(ap);
255 255 }
256 256
257 257 static void
258 258 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
259 259 {
260 260 (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
261 261 fmt, ap);
262 262 hdl->libzfs_error = error;
263 263
264 264 if (hdl->libzfs_desc_active)
265 265 hdl->libzfs_desc_active = 0;
266 266 else
267 267 hdl->libzfs_desc[0] = '\0';
268 268
269 269 if (hdl->libzfs_printerr) {
270 270 if (error == EZFS_UNKNOWN) {
271 271 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
272 272 "error: %s\n"), libzfs_error_description(hdl));
273 273 abort();
274 274 }
275 275
276 276 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
277 277 libzfs_error_description(hdl));
278 278 if (error == EZFS_NOMEM)
279 279 exit(1);
280 280 }
281 281 }
282 282
283 283 int
284 284 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
285 285 {
286 286 return (zfs_error_fmt(hdl, error, "%s", msg));
287 287 }
288 288
289 289 /*PRINTFLIKE3*/
290 290 int
291 291 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
292 292 {
293 293 va_list ap;
294 294
295 295 va_start(ap, fmt);
296 296
297 297 zfs_verror(hdl, error, fmt, ap);
298 298
299 299 va_end(ap);
300 300
301 301 return (-1);
302 302 }
303 303
304 304 static int
305 305 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
306 306 va_list ap)
307 307 {
308 308 switch (error) {
309 309 case EPERM:
310 310 case EACCES:
311 311 zfs_verror(hdl, EZFS_PERM, fmt, ap);
312 312 return (-1);
313 313
314 314 case ECANCELED:
315 315 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
316 316 return (-1);
317 317
318 318 case EIO:
319 319 zfs_verror(hdl, EZFS_IO, fmt, ap);
320 320 return (-1);
321 321
322 322 case EFAULT:
323 323 zfs_verror(hdl, EZFS_FAULT, fmt, ap);
324 324 return (-1);
325 325
326 326 case EINTR:
327 327 zfs_verror(hdl, EZFS_INTR, fmt, ap);
328 328 return (-1);
329 329 }
330 330
331 331 return (0);
332 332 }
333 333
334 334 int
335 335 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
336 336 {
337 337 return (zfs_standard_error_fmt(hdl, error, "%s", msg));
338 338 }
339 339
340 340 /*PRINTFLIKE3*/
341 341 int
342 342 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
343 343 {
344 344 va_list ap;
345 345
346 346 va_start(ap, fmt);
347 347
348 348 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
349 349 va_end(ap);
350 350 return (-1);
351 351 }
352 352
353 353 switch (error) {
354 354 case ENXIO:
355 355 case ENODEV:
356 356 case EPIPE:
357 357 zfs_verror(hdl, EZFS_IO, fmt, ap);
358 358 break;
359 359
360 360 case ENOENT:
361 361 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
362 362 "dataset does not exist"));
363 363 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
364 364 break;
365 365
366 366 case ENOSPC:
367 367 case EDQUOT:
368 368 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
369 369 return (-1);
370 370
371 371 case EEXIST:
372 372 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
373 373 "dataset already exists"));
374 374 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
375 375 break;
376 376
377 377 case EBUSY:
378 378 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
379 379 "dataset is busy"));
380 380 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
381 381 break;
382 382 case EROFS:
383 383 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
384 384 break;
385 385 case ENAMETOOLONG:
386 386 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
387 387 break;
388 388 case ENOTSUP:
389 389 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
390 390 break;
391 391 case EAGAIN:
392 392 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
393 393 "pool I/O is currently suspended"));
394 394 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
395 395 break;
396 396 default:
397 397 zfs_error_aux(hdl, strerror(error));
398 398 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
399 399 break;
400 400 }
401 401
402 402 va_end(ap);
403 403 return (-1);
404 404 }
405 405
406 406 int
407 407 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
408 408 {
409 409 return (zpool_standard_error_fmt(hdl, error, "%s", msg));
410 410 }
411 411
412 412 /*PRINTFLIKE3*/
413 413 int
414 414 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
415 415 {
416 416 va_list ap;
417 417
418 418 va_start(ap, fmt);
419 419
420 420 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
421 421 va_end(ap);
422 422 return (-1);
423 423 }
424 424
425 425 switch (error) {
426 426 case ENODEV:
427 427 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
428 428 break;
429 429
430 430 case ENOENT:
431 431 zfs_error_aux(hdl,
432 432 dgettext(TEXT_DOMAIN, "no such pool or dataset"));
433 433 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
434 434 break;
435 435
436 436 case EEXIST:
437 437 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
438 438 "pool already exists"));
439 439 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
440 440 break;
441 441
442 442 case EBUSY:
443 443 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
444 444 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
445 445 break;
446 446
447 447 case ENXIO:
448 448 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
449 449 "one or more devices is currently unavailable"));
450 450 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
451 451 break;
452 452
453 453 case ENAMETOOLONG:
454 454 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
455 455 break;
456 456
457 457 case ENOTSUP:
458 458 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
459 459 break;
460 460
461 461 case EINVAL:
462 462 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
463 463 break;
464 464
465 465 case ENOSPC:
466 466 case EDQUOT:
467 467 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
468 468 return (-1);
469 469
470 470 case EAGAIN:
471 471 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
472 472 "pool I/O is currently suspended"));
473 473 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
474 474 break;
475 475
476 476 case EROFS:
477 477 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
478 478 break;
479 479
480 480 default:
481 481 zfs_error_aux(hdl, strerror(error));
482 482 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
483 483 }
484 484
485 485 va_end(ap);
486 486 return (-1);
487 487 }
488 488
489 489 /*
490 490 * Display an out of memory error message and abort the current program.
491 491 */
492 492 int
493 493 no_memory(libzfs_handle_t *hdl)
494 494 {
495 495 return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
496 496 }
497 497
498 498 /*
499 499 * A safe form of malloc() which will die if the allocation fails.
500 500 */
501 501 void *
502 502 zfs_alloc(libzfs_handle_t *hdl, size_t size)
503 503 {
504 504 void *data;
505 505
506 506 if ((data = calloc(1, size)) == NULL)
507 507 (void) no_memory(hdl);
508 508
509 509 return (data);
510 510 }
511 511
512 512 /*
513 513 * A safe form of asprintf() which will die if the allocation fails.
514 514 */
515 515 /*PRINTFLIKE2*/
516 516 char *
517 517 zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
518 518 {
519 519 va_list ap;
520 520 char *ret;
521 521 int err;
522 522
523 523 va_start(ap, fmt);
524 524
525 525 err = vasprintf(&ret, fmt, ap);
526 526
527 527 va_end(ap);
528 528
529 529 if (err < 0)
530 530 (void) no_memory(hdl);
531 531
532 532 return (ret);
533 533 }
534 534
535 535 /*
536 536 * A safe form of realloc(), which also zeroes newly allocated space.
537 537 */
538 538 void *
539 539 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
540 540 {
541 541 void *ret;
542 542
543 543 if ((ret = realloc(ptr, newsize)) == NULL) {
544 544 (void) no_memory(hdl);
545 545 return (NULL);
546 546 }
547 547
548 548 bzero((char *)ret + oldsize, (newsize - oldsize));
549 549 return (ret);
550 550 }
551 551
552 552 /*
553 553 * A safe form of strdup() which will die if the allocation fails.
554 554 */
555 555 char *
556 556 zfs_strdup(libzfs_handle_t *hdl, const char *str)
557 557 {
558 558 char *ret;
559 559
560 560 if ((ret = strdup(str)) == NULL)
561 561 (void) no_memory(hdl);
562 562
563 563 return (ret);
564 564 }
565 565
566 566 /*
567 567 * Convert a number to an appropriately human-readable output.
568 568 */
569 569 void
570 570 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
571 571 {
572 572 uint64_t n = num;
573 573 int index = 0;
574 574 char u;
575 575
576 576 while (n >= 1024) {
577 577 n /= 1024;
578 578 index++;
579 579 }
580 580
581 581 u = " KMGTPE"[index];
582 582
583 583 if (index == 0) {
584 584 (void) snprintf(buf, buflen, "%llu", n);
585 585 } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
586 586 /*
587 587 * If this is an even multiple of the base, always display
588 588 * without any decimal precision.
589 589 */
590 590 (void) snprintf(buf, buflen, "%llu%c", n, u);
591 591 } else {
592 592 /*
593 593 * We want to choose a precision that reflects the best choice
594 594 * for fitting in 5 characters. This can get rather tricky when
595 595 * we have numbers that are very close to an order of magnitude.
596 596 * For example, when displaying 10239 (which is really 9.999K),
597 597 * we want only a single place of precision for 10.0K. We could
598 598 * develop some complex heuristics for this, but it's much
599 599 * easier just to try each combination in turn.
600 600 */
601 601 int i;
602 602 for (i = 2; i >= 0; i--) {
603 603 if (snprintf(buf, buflen, "%.*f%c", i,
604 604 (double)num / (1ULL << 10 * index), u) <= 5)
605 605 break;
606 606 }
607 607 }
608 608 }
609 609
610 610 void
611 611 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
612 612 {
613 613 hdl->libzfs_printerr = printerr;
614 614 }
615 615
616 616 /*
617 617 * Set the value of the cachedprops flag. If the cachedprops flag is set,
618 618 * operations which get ZFS properties will only retrieve a property if the
619 619 * property is cached somewhere in memory.
620 620 *
621 621 * Consumers of libzfs should take care when setting this flag, as they will
622 622 * prevent themselves from listing the full set of ZFS properties.
623 623 *
624 624 * ZFS properties which always require disk I/O are ZPL properties (utf8only,
625 625 * normalization, etc.) and the volsize and volblocksize properties for volumes.
626 626 */
627 627 void
628 628 libzfs_set_cachedprops(libzfs_handle_t *hdl, boolean_t cachedprops)
629 629 {
630 630 hdl->libzfs_cachedprops = cachedprops;
631 631 }
632 632
633 633 /*
634 634 * Adds a src nvlist to a zfs_cmd_t which specifies that only cached (i.e., will
635 635 * not require a disk access) properties should be retrieved.
636 636 */
637 637 int
638 638 libzfs_cmd_set_cachedprops(libzfs_handle_t *hdl, zfs_cmd_t *zc)
639 639 {
640 640 nvlist_t *nvl;
641 641 int ret;
642 642
643 643 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
644 644 nvlist_add_boolean_value(nvl, "cachedpropsonly", B_TRUE) != 0)
645 645 return (no_memory(hdl));
646 646
647 647 ret = zcmd_write_src_nvlist(hdl, zc, nvl);
648 648 nvlist_free(nvl);
649 649 return (ret);
650 650 }
651 651
652 652 libzfs_handle_t *
653 653 libzfs_init(void)
654 654 {
655 655 libzfs_handle_t *hdl;
656 656
657 657 if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
658 658 return (NULL);
659 659 }
660 660
661 661 if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
662 662 free(hdl);
663 663 return (NULL);
664 664 }
665 665
666 666 if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
667 667 (void) close(hdl->libzfs_fd);
668 668 free(hdl);
669 669 return (NULL);
670 670 }
671 671
672 672 hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
673 673
674 674 if (libzfs_core_init() != 0) {
675 675 (void) close(hdl->libzfs_fd);
676 676 (void) fclose(hdl->libzfs_mnttab);
677 677 (void) fclose(hdl->libzfs_sharetab);
678 678 free(hdl);
679 679 return (NULL);
680 680 }
681 681
682 682 zfs_prop_init();
683 683 zpool_prop_init();
684 684 zpool_feature_init();
685 685 libzfs_mnttab_init(hdl);
686 686
687 687 hdl->libzfs_cachedprops = B_FALSE;
688 688
689 689 return (hdl);
690 690 }
691 691
692 692 void
693 693 libzfs_fini(libzfs_handle_t *hdl)
694 694 {
695 695 (void) close(hdl->libzfs_fd);
696 696 if (hdl->libzfs_mnttab)
697 697 (void) fclose(hdl->libzfs_mnttab);
698 698 if (hdl->libzfs_sharetab)
699 699 (void) fclose(hdl->libzfs_sharetab);
700 700 zfs_uninit_libshare(hdl);
701 701 zpool_free_handles(hdl);
702 702 libzfs_fru_clear(hdl, B_TRUE);
703 703 namespace_clear(hdl);
704 704 libzfs_mnttab_fini(hdl);
705 705 libzfs_core_fini();
706 706 free(hdl);
707 707 }
708 708
709 709 libzfs_handle_t *
710 710 zpool_get_handle(zpool_handle_t *zhp)
711 711 {
712 712 return (zhp->zpool_hdl);
713 713 }
714 714
715 715 libzfs_handle_t *
716 716 zfs_get_handle(zfs_handle_t *zhp)
717 717 {
718 718 return (zhp->zfs_hdl);
719 719 }
720 720
721 721 zpool_handle_t *
722 722 zfs_get_pool_handle(const zfs_handle_t *zhp)
723 723 {
724 724 return (zhp->zpool_hdl);
725 725 }
726 726
727 727 /*
728 728 * Given a name, determine whether or not it's a valid path
729 729 * (starts with '/' or "./"). If so, walk the mnttab trying
730 730 * to match the device number. If not, treat the path as an
731 731 * fs/vol/snap name.
732 732 */
733 733 zfs_handle_t *
734 734 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
735 735 {
736 736 struct stat64 statbuf;
737 737 struct extmnttab entry;
738 738 int ret;
739 739
740 740 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
741 741 /*
742 742 * It's not a valid path, assume it's a name of type 'argtype'.
743 743 */
744 744 return (zfs_open(hdl, path, argtype));
745 745 }
746 746
747 747 if (stat64(path, &statbuf) != 0) {
748 748 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
749 749 return (NULL);
750 750 }
751 751
752 752 rewind(hdl->libzfs_mnttab);
753 753 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
754 754 if (makedevice(entry.mnt_major, entry.mnt_minor) ==
755 755 statbuf.st_dev) {
756 756 break;
757 757 }
758 758 }
759 759 if (ret != 0) {
760 760 return (NULL);
761 761 }
762 762
763 763 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
764 764 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
765 765 path);
766 766 return (NULL);
767 767 }
768 768
769 769 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
770 770 }
771 771
772 772 /*
773 773 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
774 774 * an ioctl().
775 775 */
776 776 int
777 777 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
778 778 {
779 779 if (len == 0)
780 780 len = 16 * 1024;
781 781 zc->zc_nvlist_dst_size = len;
782 782 if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
783 783 zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
784 784 return (-1);
785 785
786 786 return (0);
787 787 }
788 788
789 789 /*
790 790 * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will
791 791 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
792 792 * filled in by the kernel to indicate the actual required size.
793 793 */
794 794 int
795 795 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
796 796 {
797 797 free((void *)(uintptr_t)zc->zc_nvlist_dst);
798 798 if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
799 799 zfs_alloc(hdl, zc->zc_nvlist_dst_size))
800 800 == NULL)
801 801 return (-1);
802 802
803 803 return (0);
804 804 }
805 805
806 806 /*
807 807 * Called to free the src and dst nvlists stored in the command structure.
808 808 */
809 809 void
810 810 zcmd_free_nvlists(zfs_cmd_t *zc)
811 811 {
812 812 free((void *)(uintptr_t)zc->zc_nvlist_conf);
813 813 free((void *)(uintptr_t)zc->zc_nvlist_src);
814 814 free((void *)(uintptr_t)zc->zc_nvlist_dst);
815 815 }
816 816
817 817 static int
818 818 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
819 819 nvlist_t *nvl)
820 820 {
821 821 char *packed;
822 822 size_t len;
823 823
824 824 verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
825 825
826 826 if ((packed = zfs_alloc(hdl, len)) == NULL)
827 827 return (-1);
828 828
829 829 verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
830 830
831 831 *outnv = (uint64_t)(uintptr_t)packed;
832 832 *outlen = len;
833 833
834 834 return (0);
835 835 }
836 836
837 837 int
838 838 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
839 839 {
840 840 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
841 841 &zc->zc_nvlist_conf_size, nvl));
842 842 }
843 843
844 844 int
845 845 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
846 846 {
847 847 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
848 848 &zc->zc_nvlist_src_size, nvl));
849 849 }
850 850
851 851 /*
852 852 * Unpacks an nvlist from the ZFS ioctl command structure.
853 853 */
854 854 int
855 855 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
856 856 {
857 857 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
858 858 zc->zc_nvlist_dst_size, nvlp, 0) != 0)
859 859 return (no_memory(hdl));
860 860
861 861 return (0);
862 862 }
863 863
864 864 int
865 865 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
866 866 {
867 867 return (ioctl(hdl->libzfs_fd, request, zc));
868 868 }
869 869
870 870 /*
871 871 * ================================================================
872 872 * API shared by zfs and zpool property management
873 873 * ================================================================
874 874 */
875 875
876 876 static void
877 877 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
878 878 {
879 879 zprop_list_t *pl = cbp->cb_proplist;
880 880 int i;
881 881 char *title;
882 882 size_t len;
883 883
884 884 cbp->cb_first = B_FALSE;
885 885 if (cbp->cb_scripted)
886 886 return;
887 887
888 888 /*
889 889 * Start with the length of the column headers.
890 890 */
891 891 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
892 892 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
893 893 "PROPERTY"));
894 894 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
895 895 "VALUE"));
896 896 cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
897 897 "RECEIVED"));
898 898 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
899 899 "SOURCE"));
900 900
901 901 /* first property is always NAME */
902 902 assert(cbp->cb_proplist->pl_prop ==
903 903 ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME));
904 904
905 905 /*
906 906 * Go through and calculate the widths for each column. For the
907 907 * 'source' column, we kludge it up by taking the worst-case scenario of
908 908 * inheriting from the longest name. This is acceptable because in the
909 909 * majority of cases 'SOURCE' is the last column displayed, and we don't
910 910 * use the width anyway. Note that the 'VALUE' column can be oversized,
911 911 * if the name of the property is much longer than any values we find.
912 912 */
913 913 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
914 914 /*
915 915 * 'PROPERTY' column
916 916 */
917 917 if (pl->pl_prop != ZPROP_INVAL) {
918 918 const char *propname = (type == ZFS_TYPE_POOL) ?
919 919 zpool_prop_to_name(pl->pl_prop) :
920 920 zfs_prop_to_name(pl->pl_prop);
921 921
922 922 len = strlen(propname);
923 923 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
924 924 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
925 925 } else {
926 926 len = strlen(pl->pl_user_prop);
927 927 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
928 928 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
929 929 }
930 930
931 931 /*
932 932 * 'VALUE' column. The first property is always the 'name'
933 933 * property that was tacked on either by /sbin/zfs's
934 934 * zfs_do_get() or when calling zprop_expand_list(), so we
935 935 * ignore its width. If the user specified the name property
936 936 * to display, then it will be later in the list in any case.
937 937 */
938 938 if (pl != cbp->cb_proplist &&
939 939 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
940 940 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
941 941
942 942 /* 'RECEIVED' column. */
943 943 if (pl != cbp->cb_proplist &&
944 944 pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
945 945 cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
946 946
947 947 /*
948 948 * 'NAME' and 'SOURCE' columns
949 949 */
950 950 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
951 951 ZFS_PROP_NAME) &&
952 952 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
953 953 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
954 954 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
955 955 strlen(dgettext(TEXT_DOMAIN, "inherited from"));
956 956 }
957 957 }
958 958
959 959 /*
960 960 * Now go through and print the headers.
961 961 */
962 962 for (i = 0; i < ZFS_GET_NCOLS; i++) {
963 963 switch (cbp->cb_columns[i]) {
964 964 case GET_COL_NAME:
965 965 title = dgettext(TEXT_DOMAIN, "NAME");
966 966 break;
967 967 case GET_COL_PROPERTY:
968 968 title = dgettext(TEXT_DOMAIN, "PROPERTY");
969 969 break;
970 970 case GET_COL_VALUE:
971 971 title = dgettext(TEXT_DOMAIN, "VALUE");
972 972 break;
973 973 case GET_COL_RECVD:
974 974 title = dgettext(TEXT_DOMAIN, "RECEIVED");
975 975 break;
976 976 case GET_COL_SOURCE:
977 977 title = dgettext(TEXT_DOMAIN, "SOURCE");
978 978 break;
979 979 default:
980 980 title = NULL;
981 981 }
982 982
983 983 if (title != NULL) {
984 984 if (i == (ZFS_GET_NCOLS - 1) ||
985 985 cbp->cb_columns[i + 1] == GET_COL_NONE)
986 986 (void) printf("%s", title);
987 987 else
988 988 (void) printf("%-*s ",
989 989 cbp->cb_colwidths[cbp->cb_columns[i]],
990 990 title);
991 991 }
992 992 }
993 993 (void) printf("\n");
994 994 }
995 995
996 996 /*
997 997 * Display a single line of output, according to the settings in the callback
998 998 * structure.
999 999 */
1000 1000 void
1001 1001 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
1002 1002 const char *propname, const char *value, zprop_source_t sourcetype,
1003 1003 const char *source, const char *recvd_value)
1004 1004 {
1005 1005 int i;
1006 1006 const char *str;
1007 1007 char buf[128];
1008 1008
1009 1009 /*
1010 1010 * Ignore those source types that the user has chosen to ignore.
1011 1011 */
1012 1012 if ((sourcetype & cbp->cb_sources) == 0)
1013 1013 return;
1014 1014
1015 1015 if (cbp->cb_first)
1016 1016 zprop_print_headers(cbp, cbp->cb_type);
1017 1017
1018 1018 for (i = 0; i < ZFS_GET_NCOLS; i++) {
1019 1019 switch (cbp->cb_columns[i]) {
1020 1020 case GET_COL_NAME:
1021 1021 str = name;
1022 1022 break;
1023 1023
1024 1024 case GET_COL_PROPERTY:
1025 1025 str = propname;
1026 1026 break;
1027 1027
1028 1028 case GET_COL_VALUE:
1029 1029 str = value;
1030 1030 break;
1031 1031
1032 1032 case GET_COL_SOURCE:
1033 1033 switch (sourcetype) {
1034 1034 case ZPROP_SRC_NONE:
1035 1035 str = "-";
1036 1036 break;
1037 1037
1038 1038 case ZPROP_SRC_DEFAULT:
1039 1039 str = "default";
1040 1040 break;
1041 1041
1042 1042 case ZPROP_SRC_LOCAL:
1043 1043 str = "local";
1044 1044 break;
1045 1045
1046 1046 case ZPROP_SRC_TEMPORARY:
1047 1047 str = "temporary";
1048 1048 break;
1049 1049
1050 1050 case ZPROP_SRC_INHERITED:
1051 1051 (void) snprintf(buf, sizeof (buf),
1052 1052 "inherited from %s", source);
1053 1053 str = buf;
1054 1054 break;
1055 1055 case ZPROP_SRC_RECEIVED:
1056 1056 str = "received";
1057 1057 break;
1058 1058 }
1059 1059 break;
1060 1060
1061 1061 case GET_COL_RECVD:
1062 1062 str = (recvd_value == NULL ? "-" : recvd_value);
1063 1063 break;
1064 1064
1065 1065 default:
1066 1066 continue;
1067 1067 }
1068 1068
1069 1069 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1070 1070 (void) printf("%s", str);
1071 1071 else if (cbp->cb_scripted)
1072 1072 (void) printf("%s\t", str);
1073 1073 else
1074 1074 (void) printf("%-*s ",
1075 1075 cbp->cb_colwidths[cbp->cb_columns[i]],
1076 1076 str);
1077 1077 }
1078 1078
1079 1079 (void) printf("\n");
1080 1080 }
1081 1081
1082 1082 /*
1083 1083 * Given a numeric suffix, convert the value into a number of bits that the
1084 1084 * resulting value must be shifted.
1085 1085 */
1086 1086 static int
1087 1087 str2shift(libzfs_handle_t *hdl, const char *buf)
1088 1088 {
1089 1089 const char *ends = "BKMGTPEZ";
1090 1090 int i;
1091 1091
1092 1092 if (buf[0] == '\0')
1093 1093 return (0);
1094 1094 for (i = 0; i < strlen(ends); i++) {
1095 1095 if (toupper(buf[0]) == ends[i])
1096 1096 break;
1097 1097 }
1098 1098 if (i == strlen(ends)) {
1099 1099 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1100 1100 "invalid numeric suffix '%s'"), buf);
1101 1101 return (-1);
1102 1102 }
1103 1103
1104 1104 /*
1105 1105 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
1106 1106 * allow 'BB' - that's just weird.
1107 1107 */
1108 1108 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1109 1109 toupper(buf[0]) != 'B'))
1110 1110 return (10*i);
1111 1111
1112 1112 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1113 1113 "invalid numeric suffix '%s'"), buf);
1114 1114 return (-1);
1115 1115 }
1116 1116
1117 1117 /*
1118 1118 * Convert a string of the form '100G' into a real number. Used when setting
1119 1119 * properties or creating a volume. 'buf' is used to place an extended error
1120 1120 * message for the caller to use.
1121 1121 */
1122 1122 int
1123 1123 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1124 1124 {
1125 1125 char *end;
1126 1126 int shift;
1127 1127
1128 1128 *num = 0;
1129 1129
1130 1130 /* Check to see if this looks like a number. */
1131 1131 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1132 1132 if (hdl)
1133 1133 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1134 1134 "bad numeric value '%s'"), value);
1135 1135 return (-1);
1136 1136 }
1137 1137
1138 1138 /* Rely on strtoull() to process the numeric portion. */
1139 1139 errno = 0;
1140 1140 *num = strtoull(value, &end, 10);
1141 1141
1142 1142 /*
1143 1143 * Check for ERANGE, which indicates that the value is too large to fit
1144 1144 * in a 64-bit value.
1145 1145 */
1146 1146 if (errno == ERANGE) {
1147 1147 if (hdl)
1148 1148 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1149 1149 "numeric value is too large"));
1150 1150 return (-1);
1151 1151 }
1152 1152
1153 1153 /*
1154 1154 * If we have a decimal value, then do the computation with floating
1155 1155 * point arithmetic. Otherwise, use standard arithmetic.
1156 1156 */
1157 1157 if (*end == '.') {
1158 1158 double fval = strtod(value, &end);
1159 1159
1160 1160 if ((shift = str2shift(hdl, end)) == -1)
1161 1161 return (-1);
1162 1162
1163 1163 fval *= pow(2, shift);
1164 1164
1165 1165 if (fval > UINT64_MAX) {
1166 1166 if (hdl)
1167 1167 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1168 1168 "numeric value is too large"));
1169 1169 return (-1);
1170 1170 }
1171 1171
1172 1172 *num = (uint64_t)fval;
1173 1173 } else {
1174 1174 if ((shift = str2shift(hdl, end)) == -1)
1175 1175 return (-1);
1176 1176
1177 1177 /* Check for overflow */
1178 1178 if (shift >= 64 || (*num << shift) >> shift != *num) {
1179 1179 if (hdl)
1180 1180 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1181 1181 "numeric value is too large"));
1182 1182 return (-1);
1183 1183 }
1184 1184
1185 1185 *num <<= shift;
1186 1186 }
1187 1187
1188 1188 return (0);
1189 1189 }
1190 1190
1191 1191 /*
1192 1192 * Given a propname=value nvpair to set, parse any numeric properties
1193 1193 * (index, boolean, etc) if they are specified as strings and add the
1194 1194 * resulting nvpair to the returned nvlist.
1195 1195 *
1196 1196 * At the DSL layer, all properties are either 64-bit numbers or strings.
1197 1197 * We want the user to be able to ignore this fact and specify properties
1198 1198 * as native values (numbers, for example) or as strings (to simplify
1199 1199 * command line utilities). This also handles converting index types
1200 1200 * (compression, checksum, etc) from strings to their on-disk index.
1201 1201 */
1202 1202 int
1203 1203 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1204 1204 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1205 1205 const char *errbuf)
1206 1206 {
1207 1207 data_type_t datatype = nvpair_type(elem);
1208 1208 zprop_type_t proptype;
1209 1209 const char *propname;
1210 1210 char *value;
1211 1211 boolean_t isnone = B_FALSE;
1212 1212
1213 1213 if (type == ZFS_TYPE_POOL) {
1214 1214 proptype = zpool_prop_get_type(prop);
1215 1215 propname = zpool_prop_to_name(prop);
1216 1216 } else {
1217 1217 proptype = zfs_prop_get_type(prop);
1218 1218 propname = zfs_prop_to_name(prop);
1219 1219 }
1220 1220
1221 1221 /*
1222 1222 * Convert any properties to the internal DSL value types.
1223 1223 */
1224 1224 *svalp = NULL;
1225 1225 *ivalp = 0;
1226 1226
1227 1227 switch (proptype) {
1228 1228 case PROP_TYPE_STRING:
1229 1229 if (datatype != DATA_TYPE_STRING) {
1230 1230 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1231 1231 "'%s' must be a string"), nvpair_name(elem));
1232 1232 goto error;
1233 1233 }
1234 1234 (void) nvpair_value_string(elem, svalp);
1235 1235 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1236 1236 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1237 1237 "'%s' is too long"), nvpair_name(elem));
1238 1238 goto error;
1239 1239 }
1240 1240 break;
1241 1241
1242 1242 case PROP_TYPE_NUMBER:
1243 1243 if (datatype == DATA_TYPE_STRING) {
1244 1244 (void) nvpair_value_string(elem, &value);
1245 1245 if (strcmp(value, "none") == 0) {
1246 1246 isnone = B_TRUE;
1247 1247 } else if (zfs_nicestrtonum(hdl, value, ivalp)
1248 1248 != 0) {
1249 1249 goto error;
1250 1250 }
1251 1251 } else if (datatype == DATA_TYPE_UINT64) {
1252 1252 (void) nvpair_value_uint64(elem, ivalp);
1253 1253 } else {
1254 1254 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1255 1255 "'%s' must be a number"), nvpair_name(elem));
1256 1256 goto error;
1257 1257 }
↓ open down ↓ |
1257 lines elided |
↑ open up ↑ |
1258 1258
1259 1259 /*
1260 1260 * Quota special: force 'none' and don't allow 0.
1261 1261 */
1262 1262 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1263 1263 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1264 1264 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1265 1265 "use 'none' to disable quota/refquota"));
1266 1266 goto error;
1267 1267 }
1268 +
1269 + /*
1270 + * Special handling for "*_limit=none". In this case it's not
1271 + * 0 but UINT64_MAX.
1272 + */
1273 + if ((type & ZFS_TYPE_DATASET) && isnone &&
1274 + (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
1275 + prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
1276 + *ivalp = UINT64_MAX;
1277 + }
1268 1278 break;
1269 1279
1270 1280 case PROP_TYPE_INDEX:
1271 1281 if (datatype != DATA_TYPE_STRING) {
1272 1282 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1273 1283 "'%s' must be a string"), nvpair_name(elem));
1274 1284 goto error;
1275 1285 }
1276 1286
1277 1287 (void) nvpair_value_string(elem, &value);
1278 1288
1279 1289 if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1280 1290 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1281 1291 "'%s' must be one of '%s'"), propname,
1282 1292 zprop_values(prop, type));
1283 1293 goto error;
1284 1294 }
1285 1295 break;
1286 1296
1287 1297 default:
1288 1298 abort();
1289 1299 }
1290 1300
1291 1301 /*
1292 1302 * Add the result to our return set of properties.
1293 1303 */
1294 1304 if (*svalp != NULL) {
1295 1305 if (nvlist_add_string(ret, propname, *svalp) != 0) {
1296 1306 (void) no_memory(hdl);
1297 1307 return (-1);
1298 1308 }
1299 1309 } else {
1300 1310 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1301 1311 (void) no_memory(hdl);
1302 1312 return (-1);
1303 1313 }
1304 1314 }
1305 1315
1306 1316 return (0);
1307 1317 error:
1308 1318 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1309 1319 return (-1);
1310 1320 }
1311 1321
1312 1322 static int
1313 1323 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1314 1324 zfs_type_t type)
1315 1325 {
1316 1326 int prop;
1317 1327 zprop_list_t *entry;
1318 1328
1319 1329 prop = zprop_name_to_prop(propname, type);
1320 1330
1321 1331 if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1322 1332 prop = ZPROP_INVAL;
1323 1333
1324 1334 /*
1325 1335 * When no property table entry can be found, return failure if
1326 1336 * this is a pool property or if this isn't a user-defined
1327 1337 * dataset property,
1328 1338 */
1329 1339 if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1330 1340 !zpool_prop_feature(propname) &&
1331 1341 !zpool_prop_unsupported(propname)) ||
1332 1342 (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
1333 1343 !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1334 1344 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1335 1345 "invalid property '%s'"), propname);
1336 1346 return (zfs_error(hdl, EZFS_BADPROP,
1337 1347 dgettext(TEXT_DOMAIN, "bad property list")));
1338 1348 }
1339 1349
1340 1350 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1341 1351 return (-1);
1342 1352
1343 1353 entry->pl_prop = prop;
1344 1354 if (prop == ZPROP_INVAL) {
1345 1355 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
1346 1356 NULL) {
1347 1357 free(entry);
1348 1358 return (-1);
1349 1359 }
1350 1360 entry->pl_width = strlen(propname);
1351 1361 } else {
1352 1362 entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1353 1363 type);
1354 1364 }
1355 1365
1356 1366 *listp = entry;
1357 1367
1358 1368 return (0);
1359 1369 }
1360 1370
1361 1371 /*
1362 1372 * Given a comma-separated list of properties, construct a property list
1363 1373 * containing both user-defined and native properties. This function will
1364 1374 * return a NULL list if 'all' is specified, which can later be expanded
1365 1375 * by zprop_expand_list().
1366 1376 */
1367 1377 int
1368 1378 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1369 1379 zfs_type_t type)
1370 1380 {
1371 1381 *listp = NULL;
1372 1382
1373 1383 /*
1374 1384 * If 'all' is specified, return a NULL list.
1375 1385 */
1376 1386 if (strcmp(props, "all") == 0)
1377 1387 return (0);
1378 1388
1379 1389 /*
1380 1390 * If no props were specified, return an error.
1381 1391 */
1382 1392 if (props[0] == '\0') {
1383 1393 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1384 1394 "no properties specified"));
1385 1395 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1386 1396 "bad property list")));
1387 1397 }
1388 1398
1389 1399 /*
1390 1400 * It would be nice to use getsubopt() here, but the inclusion of column
1391 1401 * aliases makes this more effort than it's worth.
1392 1402 */
1393 1403 while (*props != '\0') {
1394 1404 size_t len;
1395 1405 char *p;
1396 1406 char c;
1397 1407
1398 1408 if ((p = strchr(props, ',')) == NULL) {
1399 1409 len = strlen(props);
1400 1410 p = props + len;
1401 1411 } else {
1402 1412 len = p - props;
1403 1413 }
1404 1414
1405 1415 /*
1406 1416 * Check for empty options.
1407 1417 */
1408 1418 if (len == 0) {
1409 1419 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1410 1420 "empty property name"));
1411 1421 return (zfs_error(hdl, EZFS_BADPROP,
1412 1422 dgettext(TEXT_DOMAIN, "bad property list")));
1413 1423 }
1414 1424
1415 1425 /*
1416 1426 * Check all regular property names.
1417 1427 */
1418 1428 c = props[len];
1419 1429 props[len] = '\0';
1420 1430
1421 1431 if (strcmp(props, "space") == 0) {
1422 1432 static char *spaceprops[] = {
1423 1433 "name", "avail", "used", "usedbysnapshots",
1424 1434 "usedbydataset", "usedbyrefreservation",
1425 1435 "usedbychildren", NULL
1426 1436 };
1427 1437 int i;
1428 1438
1429 1439 for (i = 0; spaceprops[i]; i++) {
1430 1440 if (addlist(hdl, spaceprops[i], listp, type))
1431 1441 return (-1);
1432 1442 listp = &(*listp)->pl_next;
1433 1443 }
1434 1444 } else {
1435 1445 if (addlist(hdl, props, listp, type))
1436 1446 return (-1);
1437 1447 listp = &(*listp)->pl_next;
1438 1448 }
1439 1449
1440 1450 props = p;
1441 1451 if (c == ',')
1442 1452 props++;
1443 1453 }
1444 1454
1445 1455 return (0);
1446 1456 }
1447 1457
1448 1458 void
1449 1459 zprop_free_list(zprop_list_t *pl)
1450 1460 {
1451 1461 zprop_list_t *next;
1452 1462
1453 1463 while (pl != NULL) {
1454 1464 next = pl->pl_next;
1455 1465 free(pl->pl_user_prop);
1456 1466 free(pl);
1457 1467 pl = next;
1458 1468 }
1459 1469 }
1460 1470
1461 1471 typedef struct expand_data {
1462 1472 zprop_list_t **last;
1463 1473 libzfs_handle_t *hdl;
1464 1474 zfs_type_t type;
1465 1475 } expand_data_t;
1466 1476
1467 1477 int
1468 1478 zprop_expand_list_cb(int prop, void *cb)
1469 1479 {
1470 1480 zprop_list_t *entry;
1471 1481 expand_data_t *edp = cb;
1472 1482
1473 1483 if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1474 1484 return (ZPROP_INVAL);
1475 1485
1476 1486 entry->pl_prop = prop;
1477 1487 entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1478 1488 entry->pl_all = B_TRUE;
1479 1489
1480 1490 *(edp->last) = entry;
1481 1491 edp->last = &entry->pl_next;
1482 1492
1483 1493 return (ZPROP_CONT);
1484 1494 }
1485 1495
1486 1496 int
1487 1497 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1488 1498 {
1489 1499 zprop_list_t *entry;
1490 1500 zprop_list_t **last;
1491 1501 expand_data_t exp;
1492 1502
1493 1503 if (*plp == NULL) {
1494 1504 /*
1495 1505 * If this is the very first time we've been called for an 'all'
1496 1506 * specification, expand the list to include all native
1497 1507 * properties.
1498 1508 */
1499 1509 last = plp;
1500 1510
1501 1511 exp.last = last;
1502 1512 exp.hdl = hdl;
1503 1513 exp.type = type;
1504 1514
1505 1515 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1506 1516 B_FALSE, type) == ZPROP_INVAL)
1507 1517 return (-1);
1508 1518
1509 1519 /*
1510 1520 * Add 'name' to the beginning of the list, which is handled
1511 1521 * specially.
1512 1522 */
1513 1523 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1514 1524 return (-1);
1515 1525
1516 1526 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
1517 1527 ZFS_PROP_NAME;
1518 1528 entry->pl_width = zprop_width(entry->pl_prop,
1519 1529 &entry->pl_fixed, type);
1520 1530 entry->pl_all = B_TRUE;
1521 1531 entry->pl_next = *plp;
1522 1532 *plp = entry;
1523 1533 }
1524 1534 return (0);
1525 1535 }
1526 1536
1527 1537 int
1528 1538 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1529 1539 zfs_type_t type)
1530 1540 {
1531 1541 return (zprop_iter_common(func, cb, show_all, ordered, type));
1532 1542 }
↓ open down ↓ |
255 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX