Print this page
NEX-5063 Passing invalid trim rate to zpool(1M) coredumps
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
5745 zfs set allows only one dataset property to be set at a time
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com>
Reviewed by: Richard PALO <richard@NetBSD.org>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Rich Lowe <richlowe@richlowe.net>
5692 expose the number of hole blocks in a file
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Boris Protopopov <bprotopopov@hotmail.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
NEX-4336 zpool vdev-get with an unsuported prop name core dumps
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3558 KRRP Integration
OS-103 handle CoS descriptor persistent references across vdev operations
OS-102 add man page info and tests for vdev/CoS properties and ZFS meta features
Moved closed ZFS files to open repo, changed Makefiles accordingly
Removed unneeded weak symbols
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (fix lint -courtesy of Yuri Pankov)
re #12584 rb4049 zfsxx latest code merge (fix lint - courtesy of Yuri Pankov)
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
| 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.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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) 2013, Joyent, Inc. All rights reserved.
25 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 26 * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
26 27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
27 28 * Copyright (c) 2017 Datto Inc.
28 29 */
29 30
30 31 /*
31 32 * Internal utility routines for the ZFS library.
32 33 */
33 34
34 35 #include <errno.h>
35 36 #include <fcntl.h>
36 37 #include <libintl.h>
37 38 #include <stdarg.h>
38 39 #include <stdio.h>
39 40 #include <stdlib.h>
40 41 #include <strings.h>
41 42 #include <unistd.h>
42 43 #include <ctype.h>
43 44 #include <math.h>
44 45 #include <sys/filio.h>
45 46 #include <sys/mnttab.h>
46 47 #include <sys/mntent.h>
47 48 #include <sys/types.h>
48 49 #include <libcmdutils.h>
49 50
50 51 #include <libzfs.h>
51 52 #include <libzfs_core.h>
52 53
53 54 #include "libzfs_impl.h"
54 55 #include "zfs_prop.h"
55 56 #include "zfeature_common.h"
56 57
57 58 int
58 59 libzfs_errno(libzfs_handle_t *hdl)
59 60 {
60 61 return (hdl->libzfs_error);
61 62 }
62 63
63 64 const char *
64 65 libzfs_error_action(libzfs_handle_t *hdl)
65 66 {
66 67 return (hdl->libzfs_action);
67 68 }
68 69
69 70 const char *
70 71 libzfs_error_description(libzfs_handle_t *hdl)
71 72 {
72 73 if (hdl->libzfs_desc[0] != '\0')
73 74 return (hdl->libzfs_desc);
74 75
75 76 switch (hdl->libzfs_error) {
76 77 case EZFS_NOMEM:
77 78 return (dgettext(TEXT_DOMAIN, "out of memory"));
78 79 case EZFS_BADPROP:
79 80 return (dgettext(TEXT_DOMAIN, "invalid property value"));
80 81 case EZFS_PROPREADONLY:
81 82 return (dgettext(TEXT_DOMAIN, "read-only property"));
82 83 case EZFS_PROPTYPE:
83 84 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
84 85 "datasets of this type"));
85 86 case EZFS_PROPNONINHERIT:
86 87 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
87 88 case EZFS_PROPSPACE:
88 89 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
89 90 case EZFS_BADTYPE:
90 91 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
91 92 "datasets of this type"));
92 93 case EZFS_BUSY:
93 94 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
94 95 case EZFS_EXISTS:
95 96 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
96 97 case EZFS_NOENT:
97 98 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
98 99 case EZFS_BADSTREAM:
99 100 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
100 101 case EZFS_DSREADONLY:
101 102 return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
102 103 case EZFS_VOLTOOBIG:
103 104 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
104 105 "this system"));
105 106 case EZFS_INVALIDNAME:
106 107 return (dgettext(TEXT_DOMAIN, "invalid name"));
107 108 case EZFS_BADRESTORE:
108 109 return (dgettext(TEXT_DOMAIN, "unable to restore to "
109 110 "destination"));
110 111 case EZFS_BADBACKUP:
111 112 return (dgettext(TEXT_DOMAIN, "backup failed"));
112 113 case EZFS_BADTARGET:
113 114 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
114 115 case EZFS_NODEVICE:
115 116 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
116 117 case EZFS_BADDEV:
117 118 return (dgettext(TEXT_DOMAIN, "invalid device"));
118 119 case EZFS_NOREPLICAS:
119 120 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
120 121 case EZFS_RESILVERING:
121 122 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
122 123 case EZFS_BADVERSION:
123 124 return (dgettext(TEXT_DOMAIN, "unsupported version or "
124 125 "feature"));
125 126 case EZFS_POOLUNAVAIL:
126 127 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
127 128 case EZFS_DEVOVERFLOW:
128 129 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
129 130 case EZFS_BADPATH:
130 131 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
131 132 case EZFS_CROSSTARGET:
132 133 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
133 134 "pools"));
134 135 case EZFS_ZONED:
135 136 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
136 137 case EZFS_MOUNTFAILED:
137 138 return (dgettext(TEXT_DOMAIN, "mount failed"));
138 139 case EZFS_UMOUNTFAILED:
139 140 return (dgettext(TEXT_DOMAIN, "umount failed"));
140 141 case EZFS_UNSHARENFSFAILED:
141 142 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
142 143 case EZFS_SHARENFSFAILED:
143 144 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
144 145 case EZFS_UNSHARESMBFAILED:
145 146 return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
146 147 case EZFS_SHARESMBFAILED:
147 148 return (dgettext(TEXT_DOMAIN, "smb add share failed"));
148 149 case EZFS_PERM:
149 150 return (dgettext(TEXT_DOMAIN, "permission denied"));
150 151 case EZFS_NOSPC:
151 152 return (dgettext(TEXT_DOMAIN, "out of space"));
152 153 case EZFS_FAULT:
153 154 return (dgettext(TEXT_DOMAIN, "bad address"));
154 155 case EZFS_IO:
155 156 return (dgettext(TEXT_DOMAIN, "I/O error"));
156 157 case EZFS_INTR:
157 158 return (dgettext(TEXT_DOMAIN, "signal received"));
158 159 case EZFS_ISSPARE:
159 160 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
160 161 "spare"));
161 162 case EZFS_INVALCONFIG:
162 163 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
163 164 case EZFS_RECURSIVE:
164 165 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
165 166 case EZFS_NOHISTORY:
166 167 return (dgettext(TEXT_DOMAIN, "no history available"));
167 168 case EZFS_POOLPROPS:
168 169 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
169 170 "pool properties"));
170 171 case EZFS_POOL_NOTSUP:
171 172 return (dgettext(TEXT_DOMAIN, "operation not supported "
172 173 "on this type of pool"));
173 174 case EZFS_POOL_INVALARG:
174 175 return (dgettext(TEXT_DOMAIN, "invalid argument for "
175 176 "this pool operation"));
176 177 case EZFS_NAMETOOLONG:
177 178 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
178 179 case EZFS_OPENFAILED:
179 180 return (dgettext(TEXT_DOMAIN, "open failed"));
180 181 case EZFS_NOCAP:
181 182 return (dgettext(TEXT_DOMAIN,
182 183 "disk capacity information could not be retrieved"));
183 184 case EZFS_LABELFAILED:
184 185 return (dgettext(TEXT_DOMAIN, "write of label failed"));
185 186 case EZFS_BADWHO:
186 187 return (dgettext(TEXT_DOMAIN, "invalid user/group"));
187 188 case EZFS_BADPERM:
188 189 return (dgettext(TEXT_DOMAIN, "invalid permission"));
189 190 case EZFS_BADPERMSET:
190 191 return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
191 192 case EZFS_NODELEGATION:
192 193 return (dgettext(TEXT_DOMAIN, "delegated administration is "
193 194 "disabled on pool"));
194 195 case EZFS_BADCACHE:
195 196 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
196 197 case EZFS_ISL2CACHE:
197 198 return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
198 199 case EZFS_VDEVNOTSUP:
199 200 return (dgettext(TEXT_DOMAIN, "vdev specification is not "
200 201 "supported"));
201 202 case EZFS_NOTSUP:
202 203 return (dgettext(TEXT_DOMAIN, "operation not supported "
203 204 "on this dataset"));
204 205 case EZFS_ACTIVE_SPARE:
205 206 return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
206 207 "device"));
207 208 case EZFS_UNPLAYED_LOGS:
208 209 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
209 210 "logs"));
210 211 case EZFS_REFTAG_RELE:
211 212 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
212 213 case EZFS_REFTAG_HOLD:
213 214 return (dgettext(TEXT_DOMAIN, "tag already exists on this "
214 215 "dataset"));
215 216 case EZFS_TAGTOOLONG:
216 217 return (dgettext(TEXT_DOMAIN, "tag too long"));
217 218 case EZFS_PIPEFAILED:
218 219 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
219 220 case EZFS_THREADCREATEFAILED:
220 221 return (dgettext(TEXT_DOMAIN, "thread create failed"));
221 222 case EZFS_POSTSPLIT_ONLINE:
222 223 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
223 224 "into a new one"));
224 225 case EZFS_SCRUB_PAUSED:
225 226 return (dgettext(TEXT_DOMAIN, "scrub is paused; "
226 227 "use 'zpool scrub' to resume"));
227 228 case EZFS_SCRUBBING:
|
↓ open down ↓ |
193 lines elided |
↑ open up ↑ |
228 229 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
229 230 "use 'zpool scrub -s' to cancel current scrub"));
230 231 case EZFS_NO_SCRUB:
231 232 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
232 233 case EZFS_DIFF:
233 234 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
234 235 case EZFS_DIFFDATA:
235 236 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
236 237 case EZFS_POOLREADONLY:
237 238 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
238 - case EZFS_NO_PENDING:
239 - return (dgettext(TEXT_DOMAIN, "operation is not "
240 - "in progress"));
239 + case EZFS_PROPNOTSUP:
240 + return (dgettext(TEXT_DOMAIN, "property is not supported"));
241 + case EZFS_COSNOTFOUND:
242 + return (dgettext(TEXT_DOMAIN, "CoS descriptor not found"));
243 + case EZFS_COSEXIST:
244 + return (dgettext(TEXT_DOMAIN, "CoS descriptor already exists"));
245 + case EZFS_COSREF:
246 + return (dgettext(TEXT_DOMAIN,
247 + "CoS descriptor is still referenced"));
241 248 case EZFS_UNKNOWN:
242 249 return (dgettext(TEXT_DOMAIN, "unknown error"));
243 250 default:
244 251 assert(hdl->libzfs_error == 0);
245 252 return (dgettext(TEXT_DOMAIN, "no error"));
246 253 }
247 254 }
248 255
249 256 /*PRINTFLIKE2*/
250 257 void
251 258 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
252 259 {
253 260 va_list ap;
254 261
255 262 va_start(ap, fmt);
256 263
257 264 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
258 265 fmt, ap);
259 266 hdl->libzfs_desc_active = 1;
260 267
261 268 va_end(ap);
262 269 }
263 270
264 271 static void
265 272 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
266 273 {
267 274 (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
268 275 fmt, ap);
269 276 hdl->libzfs_error = error;
270 277
271 278 if (hdl->libzfs_desc_active)
272 279 hdl->libzfs_desc_active = 0;
273 280 else
274 281 hdl->libzfs_desc[0] = '\0';
275 282
276 283 if (hdl->libzfs_printerr) {
277 284 if (error == EZFS_UNKNOWN) {
278 285 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
279 286 "error: %s\n"), libzfs_error_description(hdl));
280 287 abort();
281 288 }
282 289
283 290 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
284 291 libzfs_error_description(hdl));
285 292 if (error == EZFS_NOMEM)
286 293 exit(1);
287 294 }
288 295 }
289 296
290 297 int
291 298 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
292 299 {
293 300 return (zfs_error_fmt(hdl, error, "%s", msg));
294 301 }
295 302
296 303 /*PRINTFLIKE3*/
297 304 int
298 305 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
299 306 {
300 307 va_list ap;
301 308
302 309 va_start(ap, fmt);
303 310
304 311 zfs_verror(hdl, error, fmt, ap);
305 312
306 313 va_end(ap);
307 314
308 315 return (-1);
309 316 }
310 317
311 318 static int
312 319 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
313 320 va_list ap)
314 321 {
315 322 switch (error) {
316 323 case EPERM:
317 324 case EACCES:
318 325 zfs_verror(hdl, EZFS_PERM, fmt, ap);
319 326 return (-1);
320 327
321 328 case ECANCELED:
322 329 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
323 330 return (-1);
324 331
325 332 case EIO:
326 333 zfs_verror(hdl, EZFS_IO, fmt, ap);
327 334 return (-1);
328 335
329 336 case EFAULT:
330 337 zfs_verror(hdl, EZFS_FAULT, fmt, ap);
331 338 return (-1);
332 339
333 340 case EINTR:
334 341 zfs_verror(hdl, EZFS_INTR, fmt, ap);
335 342 return (-1);
336 343 }
337 344
338 345 return (0);
339 346 }
340 347
341 348 int
342 349 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
343 350 {
344 351 return (zfs_standard_error_fmt(hdl, error, "%s", msg));
345 352 }
346 353
347 354 /*PRINTFLIKE3*/
348 355 int
349 356 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
350 357 {
351 358 va_list ap;
352 359
353 360 va_start(ap, fmt);
354 361
355 362 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
356 363 va_end(ap);
357 364 return (-1);
358 365 }
359 366
360 367 switch (error) {
361 368 case ENXIO:
362 369 case ENODEV:
363 370 case EPIPE:
364 371 zfs_verror(hdl, EZFS_IO, fmt, ap);
365 372 break;
366 373
367 374 case ENOENT:
368 375 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
369 376 "dataset does not exist"));
370 377 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
371 378 break;
372 379
373 380 case ENOSPC:
374 381 case EDQUOT:
375 382 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
376 383 return (-1);
377 384
378 385 case EEXIST:
379 386 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
380 387 "dataset already exists"));
381 388 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
|
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
382 389 break;
383 390
384 391 case EBUSY:
385 392 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
386 393 "dataset is busy"));
387 394 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
388 395 break;
389 396 case EROFS:
390 397 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
391 398 break;
399 + case EINVAL:
400 + zfs_verror(hdl, EZFS_INVALIDNAME, fmt, ap);
401 + break;
392 402 case ENAMETOOLONG:
393 403 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
394 404 break;
395 405 case ENOTSUP:
396 406 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
397 407 break;
398 408 case EAGAIN:
399 409 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
400 410 "pool I/O is currently suspended"));
401 411 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
402 412 break;
403 413 default:
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
404 414 zfs_error_aux(hdl, strerror(error));
405 415 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
406 416 break;
407 417 }
408 418
409 419 va_end(ap);
410 420 return (-1);
411 421 }
412 422
413 423 int
424 +zpool_vprop_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
425 +{
426 + return (zpool_vprop_standard_error_fmt(hdl, error, "%s", msg));
427 +}
428 +
429 +/*PRINTFLIKE3*/
430 +int
431 +zpool_vprop_standard_error_fmt(libzfs_handle_t *hdl, int error,
432 + const char *fmt, ...)
433 +{
434 + va_list ap;
435 +
436 + va_start(ap, fmt);
437 +
438 + if (zfs_common_error(hdl, error, fmt, ap) != 0) {
439 + va_end(ap);
440 + return (-1);
441 + }
442 +
443 + switch (error) {
444 + case ENOENT:
445 + zfs_verror(hdl, EZFS_COSNOTFOUND, fmt, ap);
446 + break;
447 + case ENOTSUP:
448 + zfs_verror(hdl, EZFS_PROPNOTSUP, fmt, ap);
449 + break;
450 +
451 + case EEXIST:
452 + zfs_verror(hdl, EZFS_COSEXIST, fmt, ap);
453 + break;
454 + case EBUSY:
455 + zfs_verror(hdl, EZFS_COSREF, fmt, ap);
456 + break;
457 + default:
458 + zfs_error_aux(hdl, strerror(error));
459 + zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
460 + break;
461 + }
462 +
463 + va_end(ap);
464 + return (-1);
465 +}
466 +
467 +int
414 468 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
415 469 {
416 470 return (zpool_standard_error_fmt(hdl, error, "%s", msg));
417 471 }
418 472
419 473 /*PRINTFLIKE3*/
420 474 int
421 475 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
422 476 {
423 477 va_list ap;
424 478
425 479 va_start(ap, fmt);
426 480
427 481 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
428 482 va_end(ap);
429 483 return (-1);
430 484 }
431 485
432 486 switch (error) {
433 487 case ENODEV:
434 488 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
435 489 break;
436 490
437 491 case ENOENT:
438 492 zfs_error_aux(hdl,
439 493 dgettext(TEXT_DOMAIN, "no such pool or dataset"));
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
440 494 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
441 495 break;
442 496
443 497 case EEXIST:
444 498 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
445 499 "pool already exists"));
446 500 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
447 501 break;
448 502
449 503 case EBUSY:
450 - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
504 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
505 + "pool or device is busy"));
451 506 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
452 507 break;
453 508
454 509 case ENXIO:
455 510 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
456 511 "one or more devices is currently unavailable"));
457 512 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
458 513 break;
459 514
460 515 case ENAMETOOLONG:
461 516 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
462 517 break;
463 518
464 519 case ENOTSUP:
465 520 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
466 521 break;
467 522
468 523 case EINVAL:
469 524 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
470 525 break;
471 526
472 527 case ENOSPC:
473 528 case EDQUOT:
474 529 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
475 530 return (-1);
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
476 531
477 532 case EAGAIN:
478 533 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
479 534 "pool I/O is currently suspended"));
480 535 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
481 536 break;
482 537
483 538 case EROFS:
484 539 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
485 540 break;
486 - /* There is no pending operation to cancel */
487 - case ENOTACTIVE:
488 - zfs_verror(hdl, EZFS_NO_PENDING, fmt, ap);
489 - break;
490 541
491 542 default:
492 543 zfs_error_aux(hdl, strerror(error));
493 544 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
494 545 }
495 546
496 547 va_end(ap);
497 548 return (-1);
498 549 }
499 550
500 551 /*
501 552 * Display an out of memory error message and abort the current program.
502 553 */
503 554 int
504 555 no_memory(libzfs_handle_t *hdl)
505 556 {
506 557 return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
507 558 }
508 559
509 560 /*
510 561 * A safe form of malloc() which will die if the allocation fails.
511 562 */
512 563 void *
513 564 zfs_alloc(libzfs_handle_t *hdl, size_t size)
514 565 {
515 566 void *data;
516 567
517 568 if ((data = calloc(1, size)) == NULL)
518 569 (void) no_memory(hdl);
519 570
520 571 return (data);
521 572 }
522 573
523 574 /*
524 575 * A safe form of asprintf() which will die if the allocation fails.
525 576 */
526 577 /*PRINTFLIKE2*/
527 578 char *
528 579 zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
529 580 {
530 581 va_list ap;
531 582 char *ret;
532 583 int err;
533 584
534 585 va_start(ap, fmt);
535 586
536 587 err = vasprintf(&ret, fmt, ap);
537 588
538 589 va_end(ap);
539 590
540 591 if (err < 0)
541 592 (void) no_memory(hdl);
542 593
543 594 return (ret);
544 595 }
545 596
546 597 /*
547 598 * A safe form of realloc(), which also zeroes newly allocated space.
548 599 */
549 600 void *
550 601 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
551 602 {
552 603 void *ret;
553 604
554 605 if ((ret = realloc(ptr, newsize)) == NULL) {
555 606 (void) no_memory(hdl);
556 607 return (NULL);
557 608 }
558 609
559 610 bzero((char *)ret + oldsize, (newsize - oldsize));
560 611 return (ret);
561 612 }
562 613
563 614 /*
564 615 * A safe form of strdup() which will die if the allocation fails.
565 616 */
566 617 char *
567 618 zfs_strdup(libzfs_handle_t *hdl, const char *str)
568 619 {
569 620 char *ret;
570 621
571 622 if ((ret = strdup(str)) == NULL)
572 623 (void) no_memory(hdl);
573 624
574 625 return (ret);
575 626 }
576 627
577 628 /*
578 629 * Convert a number to an appropriately human-readable output.
579 630 */
580 631 void
581 632 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
582 633 {
583 634 nicenum(num, buf, buflen);
584 635 }
585 636
586 637 void
587 638 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
588 639 {
589 640 hdl->libzfs_printerr = printerr;
590 641 }
591 642
592 643 libzfs_handle_t *
593 644 libzfs_init(void)
594 645 {
595 646 libzfs_handle_t *hdl;
596 647
597 648 if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
598 649 return (NULL);
599 650 }
600 651
601 652 if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
602 653 free(hdl);
603 654 return (NULL);
604 655 }
605 656
606 657 if ((hdl->libzfs_mnttab = fopen(MNTTAB, "rF")) == NULL) {
607 658 (void) close(hdl->libzfs_fd);
608 659 free(hdl);
609 660 return (NULL);
610 661 }
611 662
612 663 hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "rF");
613 664
614 665 if (libzfs_core_init() != 0) {
|
↓ open down ↓ |
115 lines elided |
↑ open up ↑ |
615 666 (void) close(hdl->libzfs_fd);
616 667 (void) fclose(hdl->libzfs_mnttab);
617 668 (void) fclose(hdl->libzfs_sharetab);
618 669 free(hdl);
619 670 return (NULL);
620 671 }
621 672
622 673 zfs_prop_init();
623 674 zpool_prop_init();
624 675 zpool_feature_init();
676 + vdev_prop_init();
677 + cos_prop_init();
625 678 libzfs_mnttab_init(hdl);
626 679
627 680 if (getenv("ZFS_PROP_DEBUG") != NULL) {
628 681 hdl->libzfs_prop_debug = B_TRUE;
629 682 }
630 683
631 684 return (hdl);
632 685 }
633 686
634 687 void
635 688 libzfs_fini(libzfs_handle_t *hdl)
636 689 {
637 690 (void) close(hdl->libzfs_fd);
638 691 if (hdl->libzfs_mnttab)
639 692 (void) fclose(hdl->libzfs_mnttab);
640 693 if (hdl->libzfs_sharetab)
641 694 (void) fclose(hdl->libzfs_sharetab);
695 + if (hdl->libzfs_log_str)
696 + free(hdl->libzfs_log_str);
642 697 zfs_uninit_libshare(hdl);
643 698 zpool_free_handles(hdl);
644 699 libzfs_fru_clear(hdl, B_TRUE);
645 700 namespace_clear(hdl);
646 701 libzfs_mnttab_fini(hdl);
647 702 libzfs_core_fini();
648 703 free(hdl);
649 704 }
650 705
651 706 libzfs_handle_t *
652 707 zpool_get_handle(zpool_handle_t *zhp)
653 708 {
654 709 return (zhp->zpool_hdl);
655 710 }
656 711
657 712 libzfs_handle_t *
658 713 zfs_get_handle(zfs_handle_t *zhp)
659 714 {
660 715 return (zhp->zfs_hdl);
661 716 }
662 717
663 718 zpool_handle_t *
664 719 zfs_get_pool_handle(const zfs_handle_t *zhp)
665 720 {
666 721 return (zhp->zpool_hdl);
667 722 }
668 723
669 724 /*
670 725 * Given a name, determine whether or not it's a valid path
671 726 * (starts with '/' or "./"). If so, walk the mnttab trying
672 727 * to match the device number. If not, treat the path as an
673 728 * fs/vol/snap/bkmark name.
674 729 */
675 730 zfs_handle_t *
676 731 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
677 732 {
678 733 struct stat64 statbuf;
679 734 struct extmnttab entry;
680 735 int ret;
681 736
682 737 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
683 738 /*
684 739 * It's not a valid path, assume it's a name of type 'argtype'.
685 740 */
686 741 return (zfs_open(hdl, path, argtype));
687 742 }
688 743
689 744 if (stat64(path, &statbuf) != 0) {
690 745 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
691 746 return (NULL);
692 747 }
693 748
694 749 rewind(hdl->libzfs_mnttab);
695 750 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
696 751 if (makedevice(entry.mnt_major, entry.mnt_minor) ==
697 752 statbuf.st_dev) {
698 753 break;
699 754 }
700 755 }
701 756 if (ret != 0) {
702 757 return (NULL);
703 758 }
704 759
705 760 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
706 761 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
707 762 path);
708 763 return (NULL);
709 764 }
710 765
711 766 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
712 767 }
713 768
714 769 /*
715 770 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
716 771 * an ioctl().
717 772 */
718 773 int
719 774 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
720 775 {
721 776 if (len == 0)
722 777 len = 16 * 1024;
723 778 zc->zc_nvlist_dst_size = len;
724 779 zc->zc_nvlist_dst =
725 780 (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
726 781 if (zc->zc_nvlist_dst == 0)
727 782 return (-1);
728 783
729 784 return (0);
730 785 }
731 786
732 787 /*
733 788 * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will
734 789 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
735 790 * filled in by the kernel to indicate the actual required size.
736 791 */
737 792 int
738 793 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
739 794 {
740 795 free((void *)(uintptr_t)zc->zc_nvlist_dst);
741 796 zc->zc_nvlist_dst =
742 797 (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
743 798 if (zc->zc_nvlist_dst == 0)
744 799 return (-1);
745 800
746 801 return (0);
747 802 }
748 803
749 804 /*
750 805 * Called to free the src and dst nvlists stored in the command structure.
751 806 */
752 807 void
753 808 zcmd_free_nvlists(zfs_cmd_t *zc)
754 809 {
755 810 free((void *)(uintptr_t)zc->zc_nvlist_conf);
756 811 free((void *)(uintptr_t)zc->zc_nvlist_src);
757 812 free((void *)(uintptr_t)zc->zc_nvlist_dst);
758 813 zc->zc_nvlist_conf = NULL;
759 814 zc->zc_nvlist_src = NULL;
760 815 zc->zc_nvlist_dst = NULL;
761 816 }
762 817
763 818 static int
764 819 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
765 820 nvlist_t *nvl)
766 821 {
767 822 char *packed;
768 823 size_t len;
769 824
770 825 verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
771 826
772 827 if ((packed = zfs_alloc(hdl, len)) == NULL)
773 828 return (-1);
774 829
775 830 verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
776 831
777 832 *outnv = (uint64_t)(uintptr_t)packed;
778 833 *outlen = len;
779 834
780 835 return (0);
781 836 }
782 837
783 838 int
784 839 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
785 840 {
786 841 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
787 842 &zc->zc_nvlist_conf_size, nvl));
788 843 }
789 844
790 845 int
791 846 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
792 847 {
793 848 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
794 849 &zc->zc_nvlist_src_size, nvl));
795 850 }
796 851
797 852 /*
798 853 * Unpacks an nvlist from the ZFS ioctl command structure.
799 854 */
|
↓ open down ↓ |
148 lines elided |
↑ open up ↑ |
800 855 int
801 856 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
802 857 {
803 858 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
804 859 zc->zc_nvlist_dst_size, nvlp, 0) != 0)
805 860 return (no_memory(hdl));
806 861
807 862 return (0);
808 863 }
809 864
865 +#pragma weak libzfs_log_event = libzfs_log_event_stub
866 +
867 +/* ARGSUSED hdl zc */
868 +void
869 +libzfs_log_event_stub(libzfs_handle_t *hdl, const char *zc)
870 +{
871 +}
872 +
810 873 int
811 874 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
812 875 {
813 - return (ioctl(hdl->libzfs_fd, request, zc));
876 + int error;
877 +
878 + error = ioctl(hdl->libzfs_fd, request, zc);
879 + if (error == 0)
880 + libzfs_log_event(hdl, zc->zc_name);
881 +
882 + return (error);
814 883 }
815 884
816 885 /*
817 886 * ================================================================
818 887 * API shared by zfs and zpool property management
819 888 * ================================================================
820 889 */
821 890
822 891 static void
823 892 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
824 893 {
825 894 zprop_list_t *pl = cbp->cb_proplist;
826 895 int i;
827 896 char *title;
828 897 size_t len;
829 898
830 899 cbp->cb_first = B_FALSE;
831 900 if (cbp->cb_scripted)
832 901 return;
833 902
834 903 /*
835 904 * Start with the length of the column headers.
836 905 */
837 906 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
838 907 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
839 908 "PROPERTY"));
840 909 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
841 910 "VALUE"));
842 911 cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
843 912 "RECEIVED"));
844 913 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
845 914 "SOURCE"));
846 915
847 916 /* first property is always NAME */
848 917 assert(cbp->cb_proplist->pl_prop ==
849 918 ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME));
850 919
851 920 /*
852 921 * Go through and calculate the widths for each column. For the
853 922 * 'source' column, we kludge it up by taking the worst-case scenario of
854 923 * inheriting from the longest name. This is acceptable because in the
855 924 * majority of cases 'SOURCE' is the last column displayed, and we don't
856 925 * use the width anyway. Note that the 'VALUE' column can be oversized,
857 926 * if the name of the property is much longer than any values we find.
858 927 */
859 928 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
860 929 /*
861 930 * 'PROPERTY' column
862 931 */
863 932 if (pl->pl_prop != ZPROP_INVAL) {
864 933 const char *propname = (type == ZFS_TYPE_POOL) ?
865 934 zpool_prop_to_name(pl->pl_prop) :
866 935 zfs_prop_to_name(pl->pl_prop);
867 936
868 937 len = strlen(propname);
869 938 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
870 939 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
871 940 } else {
872 941 len = strlen(pl->pl_user_prop);
873 942 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
874 943 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
875 944 }
876 945
877 946 /*
878 947 * 'VALUE' column. The first property is always the 'name'
879 948 * property that was tacked on either by /sbin/zfs's
880 949 * zfs_do_get() or when calling zprop_expand_list(), so we
881 950 * ignore its width. If the user specified the name property
882 951 * to display, then it will be later in the list in any case.
883 952 */
884 953 if (pl != cbp->cb_proplist &&
885 954 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
886 955 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
887 956
888 957 /* 'RECEIVED' column. */
889 958 if (pl != cbp->cb_proplist &&
890 959 pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
891 960 cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
892 961
893 962 /*
894 963 * 'NAME' and 'SOURCE' columns
895 964 */
896 965 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
897 966 ZFS_PROP_NAME) &&
898 967 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
899 968 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
900 969 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
901 970 strlen(dgettext(TEXT_DOMAIN, "inherited from"));
902 971 }
903 972 }
904 973
905 974 /*
906 975 * Now go through and print the headers.
907 976 */
908 977 for (i = 0; i < ZFS_GET_NCOLS; i++) {
909 978 switch (cbp->cb_columns[i]) {
910 979 case GET_COL_NAME:
911 980 title = dgettext(TEXT_DOMAIN, "NAME");
912 981 break;
913 982 case GET_COL_PROPERTY:
914 983 title = dgettext(TEXT_DOMAIN, "PROPERTY");
915 984 break;
916 985 case GET_COL_VALUE:
917 986 title = dgettext(TEXT_DOMAIN, "VALUE");
918 987 break;
919 988 case GET_COL_RECVD:
920 989 title = dgettext(TEXT_DOMAIN, "RECEIVED");
921 990 break;
922 991 case GET_COL_SOURCE:
923 992 title = dgettext(TEXT_DOMAIN, "SOURCE");
924 993 break;
925 994 default:
926 995 title = NULL;
927 996 }
928 997
929 998 if (title != NULL) {
930 999 if (i == (ZFS_GET_NCOLS - 1) ||
931 1000 cbp->cb_columns[i + 1] == GET_COL_NONE)
932 1001 (void) printf("%s", title);
933 1002 else
934 1003 (void) printf("%-*s ",
935 1004 cbp->cb_colwidths[cbp->cb_columns[i]],
936 1005 title);
937 1006 }
938 1007 }
939 1008 (void) printf("\n");
940 1009 }
941 1010
942 1011 /*
943 1012 * Display a single line of output, according to the settings in the callback
944 1013 * structure.
945 1014 */
946 1015 void
947 1016 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
948 1017 const char *propname, const char *value, zprop_source_t sourcetype,
949 1018 const char *source, const char *recvd_value)
950 1019 {
951 1020 int i;
952 1021 const char *str = NULL;
953 1022 char buf[128];
954 1023
955 1024 /*
956 1025 * Ignore those source types that the user has chosen to ignore.
957 1026 */
958 1027 if ((sourcetype & cbp->cb_sources) == 0)
959 1028 return;
960 1029
961 1030 if (cbp->cb_first)
962 1031 zprop_print_headers(cbp, cbp->cb_type);
963 1032
964 1033 for (i = 0; i < ZFS_GET_NCOLS; i++) {
965 1034 switch (cbp->cb_columns[i]) {
966 1035 case GET_COL_NAME:
967 1036 str = name;
968 1037 break;
969 1038
970 1039 case GET_COL_PROPERTY:
971 1040 str = propname;
972 1041 break;
973 1042
974 1043 case GET_COL_VALUE:
975 1044 str = value;
976 1045 break;
977 1046
978 1047 case GET_COL_SOURCE:
979 1048 switch (sourcetype) {
980 1049 case ZPROP_SRC_NONE:
981 1050 str = "-";
982 1051 break;
983 1052
984 1053 case ZPROP_SRC_DEFAULT:
985 1054 str = "default";
986 1055 break;
987 1056
988 1057 case ZPROP_SRC_LOCAL:
989 1058 str = "local";
990 1059 break;
991 1060
992 1061 case ZPROP_SRC_TEMPORARY:
993 1062 str = "temporary";
994 1063 break;
995 1064
996 1065 case ZPROP_SRC_INHERITED:
997 1066 (void) snprintf(buf, sizeof (buf),
998 1067 "inherited from %s", source);
999 1068 str = buf;
1000 1069 break;
1001 1070 case ZPROP_SRC_RECEIVED:
1002 1071 str = "received";
1003 1072 break;
1004 1073
1005 1074 default:
1006 1075 str = NULL;
1007 1076 assert(!"unhandled zprop_source_t");
1008 1077 }
1009 1078 break;
1010 1079
1011 1080 case GET_COL_RECVD:
1012 1081 str = (recvd_value == NULL ? "-" : recvd_value);
1013 1082 break;
1014 1083
1015 1084 default:
1016 1085 continue;
1017 1086 }
1018 1087
1019 1088 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1020 1089 (void) printf("%s", str);
1021 1090 else if (cbp->cb_scripted)
1022 1091 (void) printf("%s\t", str);
1023 1092 else
1024 1093 (void) printf("%-*s ",
1025 1094 cbp->cb_colwidths[cbp->cb_columns[i]],
1026 1095 str);
1027 1096 }
1028 1097
1029 1098 (void) printf("\n");
1030 1099 }
1031 1100
1032 1101 /*
1033 1102 * Given a numeric suffix, convert the value into a number of bits that the
1034 1103 * resulting value must be shifted.
1035 1104 */
1036 1105 static int
1037 1106 str2shift(libzfs_handle_t *hdl, const char *buf)
1038 1107 {
|
↓ open down ↓ |
215 lines elided |
↑ open up ↑ |
1039 1108 const char *ends = "BKMGTPEZ";
1040 1109 int i;
1041 1110
1042 1111 if (buf[0] == '\0')
1043 1112 return (0);
1044 1113 for (i = 0; i < strlen(ends); i++) {
1045 1114 if (toupper(buf[0]) == ends[i])
1046 1115 break;
1047 1116 }
1048 1117 if (i == strlen(ends)) {
1049 - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1050 - "invalid numeric suffix '%s'"), buf);
1118 + if (hdl)
1119 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1120 + "invalid numeric suffix '%s'"), buf);
1051 1121 return (-1);
1052 1122 }
1053 1123
1054 1124 /*
1055 1125 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
1056 1126 * allow 'BB' - that's just weird.
1057 1127 */
1058 1128 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1059 1129 toupper(buf[0]) != 'B'))
1060 1130 return (10*i);
1061 1131
1062 - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1063 - "invalid numeric suffix '%s'"), buf);
1132 + if (hdl)
1133 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1134 + "invalid numeric suffix '%s'"), buf);
1064 1135 return (-1);
1065 1136 }
1066 1137
1067 1138 /*
1068 1139 * Convert a string of the form '100G' into a real number. Used when setting
1069 1140 * properties or creating a volume. 'buf' is used to place an extended error
1070 1141 * message for the caller to use.
1071 1142 */
1072 1143 int
1073 1144 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1074 1145 {
1075 1146 char *end;
1076 1147 int shift;
1077 1148
1078 1149 *num = 0;
1079 1150
1080 1151 /* Check to see if this looks like a number. */
1081 1152 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1082 1153 if (hdl)
1083 1154 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1084 1155 "bad numeric value '%s'"), value);
1085 1156 return (-1);
1086 1157 }
1087 1158
1088 1159 /* Rely on strtoull() to process the numeric portion. */
1089 1160 errno = 0;
1090 1161 *num = strtoull(value, &end, 10);
1091 1162
1092 1163 /*
1093 1164 * Check for ERANGE, which indicates that the value is too large to fit
1094 1165 * in a 64-bit value.
1095 1166 */
1096 1167 if (errno == ERANGE) {
1097 1168 if (hdl)
1098 1169 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1099 1170 "numeric value is too large"));
1100 1171 return (-1);
1101 1172 }
1102 1173
1103 1174 /*
1104 1175 * If we have a decimal value, then do the computation with floating
1105 1176 * point arithmetic. Otherwise, use standard arithmetic.
1106 1177 */
1107 1178 if (*end == '.') {
1108 1179 double fval = strtod(value, &end);
1109 1180
1110 1181 if ((shift = str2shift(hdl, end)) == -1)
1111 1182 return (-1);
1112 1183
1113 1184 fval *= pow(2, shift);
1114 1185
1115 1186 if (fval > UINT64_MAX) {
1116 1187 if (hdl)
1117 1188 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1118 1189 "numeric value is too large"));
1119 1190 return (-1);
1120 1191 }
1121 1192
1122 1193 *num = (uint64_t)fval;
1123 1194 } else {
1124 1195 if ((shift = str2shift(hdl, end)) == -1)
1125 1196 return (-1);
1126 1197
1127 1198 /* Check for overflow */
1128 1199 if (shift >= 64 || (*num << shift) >> shift != *num) {
1129 1200 if (hdl)
1130 1201 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1131 1202 "numeric value is too large"));
1132 1203 return (-1);
1133 1204 }
1134 1205
1135 1206 *num <<= shift;
1136 1207 }
1137 1208
1138 1209 return (0);
1139 1210 }
1140 1211
1141 1212 /*
1142 1213 * Given a propname=value nvpair to set, parse any numeric properties
1143 1214 * (index, boolean, etc) if they are specified as strings and add the
1144 1215 * resulting nvpair to the returned nvlist.
1145 1216 *
1146 1217 * At the DSL layer, all properties are either 64-bit numbers or strings.
1147 1218 * We want the user to be able to ignore this fact and specify properties
1148 1219 * as native values (numbers, for example) or as strings (to simplify
1149 1220 * command line utilities). This also handles converting index types
1150 1221 * (compression, checksum, etc) from strings to their on-disk index.
1151 1222 */
1152 1223 int
|
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
1153 1224 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1154 1225 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1155 1226 const char *errbuf)
1156 1227 {
1157 1228 data_type_t datatype = nvpair_type(elem);
1158 1229 zprop_type_t proptype;
1159 1230 const char *propname;
1160 1231 char *value;
1161 1232 boolean_t isnone = B_FALSE;
1162 1233
1163 - if (type == ZFS_TYPE_POOL) {
1234 + switch (type) {
1235 + case ZFS_TYPE_POOL:
1164 1236 proptype = zpool_prop_get_type(prop);
1165 1237 propname = zpool_prop_to_name(prop);
1166 - } else {
1238 + break;
1239 + case ZFS_TYPE_VDEV:
1240 + proptype = vdev_prop_get_type(prop);
1241 + propname = vdev_prop_to_name(prop);
1242 + break;
1243 + case ZFS_TYPE_COS:
1244 + proptype = cos_prop_get_type(prop);
1245 + propname = cos_prop_to_name(prop);
1246 + break;
1247 + default:
1167 1248 proptype = zfs_prop_get_type(prop);
1168 1249 propname = zfs_prop_to_name(prop);
1169 1250 }
1170 1251
1171 1252 /*
1172 1253 * Convert any properties to the internal DSL value types.
1173 1254 */
1174 1255 *svalp = NULL;
1175 1256 *ivalp = 0;
1176 1257
1177 1258 switch (proptype) {
1178 1259 case PROP_TYPE_STRING:
1179 1260 if (datatype != DATA_TYPE_STRING) {
1180 1261 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1181 1262 "'%s' must be a string"), nvpair_name(elem));
1182 1263 goto error;
1183 1264 }
1184 1265 (void) nvpair_value_string(elem, svalp);
1185 1266 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1186 1267 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1187 1268 "'%s' is too long"), nvpair_name(elem));
1188 1269 goto error;
1189 1270 }
1190 1271 break;
1191 1272
1192 1273 case PROP_TYPE_NUMBER:
1193 1274 if (datatype == DATA_TYPE_STRING) {
1194 1275 (void) nvpair_value_string(elem, &value);
1195 1276 if (strcmp(value, "none") == 0) {
1196 1277 isnone = B_TRUE;
1197 1278 } else if (zfs_nicestrtonum(hdl, value, ivalp)
1198 1279 != 0) {
1199 1280 goto error;
1200 1281 }
1201 1282 } else if (datatype == DATA_TYPE_UINT64) {
1202 1283 (void) nvpair_value_uint64(elem, ivalp);
1203 1284 } else {
1204 1285 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1205 1286 "'%s' must be a number"), nvpair_name(elem));
1206 1287 goto error;
1207 1288 }
1208 1289
1209 1290 /*
1210 1291 * Quota special: force 'none' and don't allow 0.
1211 1292 */
1212 1293 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1213 1294 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1214 1295 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1215 1296 "use 'none' to disable quota/refquota"));
1216 1297 goto error;
1217 1298 }
1218 1299
1219 1300 /*
1220 1301 * Special handling for "*_limit=none". In this case it's not
1221 1302 * 0 but UINT64_MAX.
1222 1303 */
1223 1304 if ((type & ZFS_TYPE_DATASET) && isnone &&
1224 1305 (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
1225 1306 prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
1226 1307 *ivalp = UINT64_MAX;
1227 1308 }
1228 1309 break;
1229 1310
1230 1311 case PROP_TYPE_INDEX:
1231 1312 if (datatype != DATA_TYPE_STRING) {
1232 1313 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1233 1314 "'%s' must be a string"), nvpair_name(elem));
1234 1315 goto error;
1235 1316 }
1236 1317
1237 1318 (void) nvpair_value_string(elem, &value);
1238 1319
1239 1320 if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1240 1321 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1241 1322 "'%s' must be one of '%s'"), propname,
1242 1323 zprop_values(prop, type));
1243 1324 goto error;
1244 1325 }
1245 1326 break;
1246 1327
1247 1328 default:
1248 1329 abort();
1249 1330 }
1250 1331
1251 1332 /*
1252 1333 * Add the result to our return set of properties.
1253 1334 */
1254 1335 if (*svalp != NULL) {
1255 1336 if (nvlist_add_string(ret, propname, *svalp) != 0) {
1256 1337 (void) no_memory(hdl);
1257 1338 return (-1);
1258 1339 }
1259 1340 } else {
1260 1341 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1261 1342 (void) no_memory(hdl);
1262 1343 return (-1);
1263 1344 }
1264 1345 }
1265 1346
1266 1347 return (0);
1267 1348 error:
1268 1349 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1269 1350 return (-1);
1270 1351 }
1271 1352
1272 1353 static int
1273 1354 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1274 1355 zfs_type_t type)
1275 1356 {
1276 1357 int prop;
1277 1358 zprop_list_t *entry;
1278 1359
1279 1360 prop = zprop_name_to_prop(propname, type);
1280 1361
1281 1362 if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1282 1363 prop = ZPROP_INVAL;
1283 1364
1284 1365 /*
1285 1366 * When no property table entry can be found, return failure if
1286 1367 * this is a pool property or if this isn't a user-defined
1287 1368 * dataset property,
1288 1369 */
1289 1370 if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1290 1371 !zpool_prop_feature(propname) &&
1291 1372 !zpool_prop_unsupported(propname)) ||
1292 1373 (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
1293 1374 !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1294 1375 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1295 1376 "invalid property '%s'"), propname);
1296 1377 return (zfs_error(hdl, EZFS_BADPROP,
1297 1378 dgettext(TEXT_DOMAIN, "bad property list")));
1298 1379 }
1299 1380
1300 1381 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1301 1382 return (-1);
1302 1383
1303 1384 entry->pl_prop = prop;
1304 1385 if (prop == ZPROP_INVAL) {
1305 1386 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
1306 1387 NULL) {
1307 1388 free(entry);
1308 1389 return (-1);
1309 1390 }
1310 1391 entry->pl_width = strlen(propname);
1311 1392 } else {
1312 1393 entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1313 1394 type);
1314 1395 }
1315 1396
1316 1397 *listp = entry;
1317 1398
1318 1399 return (0);
1319 1400 }
1320 1401
1321 1402 /*
1322 1403 * Given a comma-separated list of properties, construct a property list
1323 1404 * containing both user-defined and native properties. This function will
1324 1405 * return a NULL list if 'all' is specified, which can later be expanded
1325 1406 * by zprop_expand_list().
1326 1407 */
1327 1408 int
1328 1409 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1329 1410 zfs_type_t type)
1330 1411 {
1331 1412 *listp = NULL;
1332 1413
1333 1414 /*
1334 1415 * If 'all' is specified, return a NULL list.
1335 1416 */
1336 1417 if (strcmp(props, "all") == 0)
1337 1418 return (0);
1338 1419
1339 1420 /*
1340 1421 * If no props were specified, return an error.
1341 1422 */
1342 1423 if (props[0] == '\0') {
1343 1424 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1344 1425 "no properties specified"));
1345 1426 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1346 1427 "bad property list")));
1347 1428 }
1348 1429
1349 1430 /*
1350 1431 * It would be nice to use getsubopt() here, but the inclusion of column
1351 1432 * aliases makes this more effort than it's worth.
1352 1433 */
1353 1434 while (*props != '\0') {
1354 1435 size_t len;
1355 1436 char *p;
1356 1437 char c;
1357 1438
1358 1439 if ((p = strchr(props, ',')) == NULL) {
1359 1440 len = strlen(props);
1360 1441 p = props + len;
1361 1442 } else {
1362 1443 len = p - props;
1363 1444 }
1364 1445
1365 1446 /*
1366 1447 * Check for empty options.
1367 1448 */
1368 1449 if (len == 0) {
1369 1450 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1370 1451 "empty property name"));
1371 1452 return (zfs_error(hdl, EZFS_BADPROP,
1372 1453 dgettext(TEXT_DOMAIN, "bad property list")));
1373 1454 }
1374 1455
1375 1456 /*
1376 1457 * Check all regular property names.
1377 1458 */
1378 1459 c = props[len];
1379 1460 props[len] = '\0';
1380 1461
1381 1462 if (strcmp(props, "space") == 0) {
1382 1463 static char *spaceprops[] = {
1383 1464 "name", "avail", "used", "usedbysnapshots",
1384 1465 "usedbydataset", "usedbyrefreservation",
1385 1466 "usedbychildren", NULL
1386 1467 };
1387 1468 int i;
1388 1469
1389 1470 for (i = 0; spaceprops[i]; i++) {
1390 1471 if (addlist(hdl, spaceprops[i], listp, type))
1391 1472 return (-1);
1392 1473 listp = &(*listp)->pl_next;
1393 1474 }
1394 1475 } else {
1395 1476 if (addlist(hdl, props, listp, type))
1396 1477 return (-1);
1397 1478 listp = &(*listp)->pl_next;
1398 1479 }
1399 1480
1400 1481 props = p;
1401 1482 if (c == ',')
1402 1483 props++;
1403 1484 }
1404 1485
1405 1486 return (0);
1406 1487 }
1407 1488
1408 1489 void
1409 1490 zprop_free_list(zprop_list_t *pl)
1410 1491 {
1411 1492 zprop_list_t *next;
1412 1493
1413 1494 while (pl != NULL) {
1414 1495 next = pl->pl_next;
1415 1496 free(pl->pl_user_prop);
1416 1497 free(pl);
1417 1498 pl = next;
1418 1499 }
1419 1500 }
1420 1501
1421 1502 typedef struct expand_data {
1422 1503 zprop_list_t **last;
1423 1504 libzfs_handle_t *hdl;
1424 1505 zfs_type_t type;
1425 1506 } expand_data_t;
1426 1507
1427 1508 int
1428 1509 zprop_expand_list_cb(int prop, void *cb)
1429 1510 {
1430 1511 zprop_list_t *entry;
1431 1512 expand_data_t *edp = cb;
1432 1513
1433 1514 if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1434 1515 return (ZPROP_INVAL);
1435 1516
1436 1517 entry->pl_prop = prop;
1437 1518 entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1438 1519 entry->pl_all = B_TRUE;
1439 1520
1440 1521 *(edp->last) = entry;
1441 1522 edp->last = &entry->pl_next;
1442 1523
1443 1524 return (ZPROP_CONT);
1444 1525 }
1445 1526
1446 1527 int
1447 1528 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1448 1529 {
1449 1530 zprop_list_t *entry;
1450 1531 zprop_list_t **last;
1451 1532 expand_data_t exp;
1452 1533
1453 1534 if (*plp == NULL) {
1454 1535 /*
1455 1536 * If this is the very first time we've been called for an 'all'
1456 1537 * specification, expand the list to include all native
1457 1538 * properties.
1458 1539 */
1459 1540 last = plp;
1460 1541
1461 1542 exp.last = last;
1462 1543 exp.hdl = hdl;
1463 1544 exp.type = type;
1464 1545
1465 1546 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1466 1547 B_FALSE, type) == ZPROP_INVAL)
1467 1548 return (-1);
1468 1549
1469 1550 /*
1470 1551 * Add 'name' to the beginning of the list, which is handled
1471 1552 * specially.
1472 1553 */
1473 1554 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1474 1555 return (-1);
1475 1556
1476 1557 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
1477 1558 ZFS_PROP_NAME;
1478 1559 entry->pl_width = zprop_width(entry->pl_prop,
1479 1560 &entry->pl_fixed, type);
1480 1561 entry->pl_all = B_TRUE;
1481 1562 entry->pl_next = *plp;
1482 1563 *plp = entry;
1483 1564 }
|
↓ open down ↓ |
307 lines elided |
↑ open up ↑ |
1484 1565 return (0);
1485 1566 }
1486 1567
1487 1568 int
1488 1569 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1489 1570 zfs_type_t type)
1490 1571 {
1491 1572 return (zprop_iter_common(func, cb, show_all, ordered, type));
1492 1573 }
1493 1574
1575 +int
1576 +vdev_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp)
1577 +{
1578 + *listp = NULL;
1579 +
1580 + /*
1581 + * If 'all' is specified, return a NULL list.
1582 + */
1583 + if (strcmp(props, "all") == 0) {
1584 + vdev_prop_t prop;
1585 + for (prop = VDEV_PROP_PATH; prop < VDEV_NUM_PROPS; prop++) {
1586 + const char *propname = vdev_prop_to_name(prop);
1587 + if (addlist(hdl, (char *)propname, listp,
1588 + ZFS_TYPE_VDEV))
1589 + return (-1);
1590 + listp = &(*listp)->pl_next;
1591 + }
1592 +
1593 + return (0);
1594 + }
1595 +
1596 + /*
1597 + * If no props were specified, return an error.
1598 + */
1599 + if (props[0] == '\0') {
1600 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1601 + "no properties specified"));
1602 + return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1603 + "bad property list")));
1604 + }
1605 +
1606 + /*
1607 + * It would be nice to use getsubopt() here, but the inclusion of column
1608 + * aliases makes this more effort than it's worth.
1609 + */
1610 + while (*props != '\0') {
1611 + size_t len;
1612 + char *p;
1613 + char c;
1614 +
1615 + if ((p = strchr(props, ',')) == NULL) {
1616 + len = strlen(props);
1617 + p = props + len;
1618 + } else {
1619 + len = p - props;
1620 + }
1621 +
1622 + /*
1623 + * Check for empty options.
1624 + */
1625 + if (len == 0) {
1626 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1627 + "empty property name"));
1628 + return (zfs_error(hdl, EZFS_BADPROP,
1629 + dgettext(TEXT_DOMAIN, "bad property list")));
1630 + }
1631 +
1632 + /*
1633 + * Check all regular property names.
1634 + */
1635 + c = props[len];
1636 + props[len] = '\0';
1637 +
1638 + /*
1639 + * Make sure we're looking at a valid prop.
1640 + */
1641 + if (vdev_name_to_prop(props) == ZPROP_INVAL) {
1642 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1643 + "invalid property '%s'"), props);
1644 + return (zfs_error(hdl, EZFS_BADPROP,
1645 + dgettext(TEXT_DOMAIN, "bad property list")));
1646 + }
1647 +
1648 + if (addlist(hdl, props, listp, ZFS_TYPE_VDEV))
1649 + return (-1);
1650 + listp = &(*listp)->pl_next;
1651 +
1652 + props = p;
1653 + if (c == ',')
1654 + props++;
1655 + }
1656 +
1657 + return (0);
1658 +}
1659 +
1660 +int
1661 +cos_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp)
1662 +{
1663 + *listp = NULL;
1664 +
1665 + /*
1666 + * If 'all' is specified, return a NULL list.
1667 + */
1668 + if (strcmp(props, "all") == 0) {
1669 + cos_prop_t prop;
1670 + for (prop = COS_PROP_GUID; prop < COS_NUM_PROPS; prop++) {
1671 + const char *propname = cos_prop_to_name(prop);
1672 + if (addlist(hdl, (char *)propname, listp,
1673 + ZFS_TYPE_COS))
1674 + return (-1);
1675 + listp = &(*listp)->pl_next;
1676 + }
1677 +
1678 + return (0);
1679 + }
1680 +
1681 + /*
1682 + * If no props were specified, return an error.
1683 + */
1684 + if (props[0] == '\0') {
1685 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1686 + "no properties specified"));
1687 + return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1688 + "bad property list")));
1689 + }
1690 +
1691 + /*
1692 + * It would be nice to use getsubopt() here, but the inclusion of column
1693 + * aliases makes this more effort than it's worth.
1694 + */
1695 + while (*props != '\0') {
1696 + size_t len;
1697 + char *p;
1698 + char c;
1699 +
1700 + if ((p = strchr(props, ',')) == NULL) {
1701 + len = strlen(props);
1702 + p = props + len;
1703 + } else {
1704 + len = p - props;
1705 + }
1706 +
1707 + /*
1708 + * Check for empty options.
1709 + */
1710 + if (len == 0) {
1711 + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1712 + "empty property name"));
1713 + return (zfs_error(hdl, EZFS_BADPROP,
1714 + dgettext(TEXT_DOMAIN, "bad property list")));
1715 + }
1716 +
1717 + /*
1718 + * Check all regular property names.
1719 + */
1720 + c = props[len];
1721 + props[len] = '\0';
1722 +
1723 + if (addlist(hdl, props, listp, ZFS_TYPE_COS))
1724 + return (-1);
1725 + listp = &(*listp)->pl_next;
1726 +
1727 + props = p;
1728 + if (c == ',')
1729 + props++;
1730 + }
1731 +
1732 + return (0);
1733 +}
1734 +
1735 +void
1736 +vdev_print_headers(zprop_get_cbdata_t *cbp)
1737 +{
1738 + zprop_list_t *pl = cbp->cb_proplist;
1739 + int i;
1740 + char *title;
1741 + size_t len;
1742 +
1743 + cbp->cb_first = B_FALSE;
1744 + if (cbp->cb_scripted)
1745 + return;
1746 +
1747 + /*
1748 + * Start with the length of the column headers.
1749 + */
1750 + cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN,
1751 + "POOLNAME"));
1752 + cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
1753 + "c0t0d0s0"));
1754 + cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
1755 + "PROPERTY"));
1756 + cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
1757 + "VALUE"));
1758 +
1759 + for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
1760 + /*
1761 + * 'PROPERTY' column
1762 + */
1763 + const char *propname = vdev_prop_to_name(pl->pl_prop);
1764 +
1765 + len = strlen(propname);
1766 + if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
1767 + cbp->cb_colwidths[GET_COL_PROPERTY] = len;
1768 +
1769 + /*
1770 + * 'VALUE' column.
1771 + */
1772 + if (pl != cbp->cb_proplist &&
1773 + pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
1774 + cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
1775 +
1776 + /*
1777 + * 'NAME'
1778 + */
1779 + if (pl->pl_prop == 0 &&
1780 + pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
1781 + cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
1782 + }
1783 + /*
1784 + * 'SOURCE'
1785 + */
1786 + if (pl->pl_prop == 0 &&
1787 + pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) {
1788 + cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width;
1789 + }
1790 + }
1791 +
1792 + /*
1793 + * Now go through and print the headers.
1794 + */
1795 + for (i = 0; i < ZFS_GET_NCOLS-1; i++) {
1796 + switch (cbp->cb_columns[i]) {
1797 + case GET_COL_NAME:
1798 + title = dgettext(TEXT_DOMAIN, "POOLNAME");
1799 + break;
1800 + case GET_COL_SOURCE:
1801 + title = dgettext(TEXT_DOMAIN, "VDEV");
1802 + break;
1803 + case GET_COL_PROPERTY:
1804 + title = dgettext(TEXT_DOMAIN, "PROPERTY");
1805 + break;
1806 + case GET_COL_VALUE:
1807 + title = dgettext(TEXT_DOMAIN, "VALUE");
1808 + break;
1809 + default:
1810 + title = NULL;
1811 + }
1812 +
1813 + if (title != NULL) {
1814 + if (i == (ZFS_GET_NCOLS - 1) ||
1815 + cbp->cb_columns[i + 1] == GET_COL_NONE)
1816 + (void) printf("%s", title);
1817 + else
1818 + (void) printf("%-*s ",
1819 + cbp->cb_colwidths[cbp->cb_columns[i]],
1820 + title);
1821 + }
1822 + }
1823 + (void) printf("\n");
1824 +}
1825 +
1826 +void
1827 +cos_print_headers(zprop_get_cbdata_t *cbp)
1828 +{
1829 + zprop_list_t *pl = cbp->cb_proplist;
1830 + int i;
1831 + char *title;
1832 + size_t len;
1833 +
1834 + cbp->cb_first = B_FALSE;
1835 + if (cbp->cb_scripted)
1836 + return;
1837 +
1838 + /*
1839 + * Start with the length of the column headers.
1840 + */
1841 + cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN,
1842 + "POOLNAME"));
1843 + cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
1844 + "c0t0d0s0"));
1845 + cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
1846 + "PROPERTY"));
1847 + cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
1848 + "VALUE"));
1849 +
1850 + for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
1851 + /*
1852 + * 'PROPERTY' column
1853 + */
1854 + const char *propname = cos_prop_to_name(pl->pl_prop);
1855 +
1856 + len = strlen(propname);
1857 + if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
1858 + cbp->cb_colwidths[GET_COL_PROPERTY] = len;
1859 +
1860 + /*
1861 + * 'VALUE' column.
1862 + */
1863 + if (pl != cbp->cb_proplist &&
1864 + pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
1865 + cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
1866 +
1867 + /*
1868 + * 'NAME'
1869 + */
1870 + if (pl->pl_prop == 0 &&
1871 + pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
1872 + cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
1873 + }
1874 + /*
1875 + * 'SOURCE'
1876 + */
1877 + if (pl->pl_prop == 0 &&
1878 + pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) {
1879 + cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width;
1880 + }
1881 + }
1882 +
1883 + /*
1884 + * Now go through and print the headers.
1885 + */
1886 + for (i = 0; i < ZFS_GET_NCOLS-1; i++) {
1887 + switch (cbp->cb_columns[i]) {
1888 + case GET_COL_NAME:
1889 + title = dgettext(TEXT_DOMAIN, "POOLNAME");
1890 + break;
1891 + case GET_COL_SOURCE:
1892 + title = dgettext(TEXT_DOMAIN, "COS");
1893 + break;
1894 + case GET_COL_PROPERTY:
1895 + title = dgettext(TEXT_DOMAIN, "PROPERTY");
1896 + break;
1897 + case GET_COL_VALUE:
1898 + title = dgettext(TEXT_DOMAIN, "VALUE");
1899 + break;
1900 + default:
1901 + title = NULL;
1902 + }
1903 +
1904 + if (title != NULL) {
1905 + if (i == (ZFS_GET_NCOLS - 1) ||
1906 + cbp->cb_columns[i + 1] == GET_COL_NONE)
1907 + (void) printf("%s", title);
1908 + else
1909 + (void) printf("%-*s ",
1910 + cbp->cb_colwidths[cbp->cb_columns[i]],
1911 + title);
1912 + }
1913 + }
1914 + (void) printf("\n");
1915 +}
1916 +
1917 +void
1918 +vdev_print_one_property(const char *poolname, const char *vdevname,
1919 + zprop_get_cbdata_t *cbp, const char *propname, const char *value)
1920 +{
1921 + int i;
1922 + const char *str;
1923 +
1924 + if (cbp->cb_first)
1925 + vdev_print_headers(cbp);
1926 +
1927 + for (i = 0; i < ZFS_GET_NCOLS; i++) {
1928 + switch (cbp->cb_columns[i]) {
1929 + case GET_COL_NAME:
1930 + str = poolname;
1931 + break;
1932 +
1933 + case GET_COL_SOURCE:
1934 + str = vdevname;
1935 + break;
1936 +
1937 + case GET_COL_PROPERTY:
1938 + str = propname;
1939 + break;
1940 +
1941 + case GET_COL_VALUE:
1942 + str = value;
1943 + break;
1944 +
1945 + default:
1946 + continue;
1947 + }
1948 +
1949 + if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1950 + (void) printf("%s", str);
1951 + else if (cbp->cb_scripted)
1952 + (void) printf("%s\t", str);
1953 + else
1954 + (void) printf("%-*s ",
1955 + cbp->cb_colwidths[cbp->cb_columns[i]],
1956 + str);
1957 + }
1958 +
1959 + (void) printf("\n");
1960 +}
1961 +
1962 +void
1963 +cos_print_one_property(const char *poolname, const char *cosname,
1964 + zprop_get_cbdata_t *cbp, const char *propname, const char *value)
1965 +{
1966 + int i;
1967 + const char *str;
1968 +
1969 + if (cbp->cb_first)
1970 + cos_print_headers(cbp);
1971 +
1972 + for (i = 0; i < ZFS_GET_NCOLS; i++) {
1973 + switch (cbp->cb_columns[i]) {
1974 + case GET_COL_NAME:
1975 + str = poolname;
1976 + break;
1977 +
1978 + case GET_COL_SOURCE:
1979 + str = cosname;
1980 + break;
1981 +
1982 + case GET_COL_PROPERTY:
1983 + str = propname;
1984 + break;
1985 +
1986 + case GET_COL_VALUE:
1987 + str = value;
1988 + break;
1989 +
1990 + default:
1991 + continue;
1992 + }
1993 +
1994 + if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1995 + (void) printf("%s", str);
1996 + else if (cbp->cb_scripted)
1997 + (void) printf("%s\t", str);
1998 + else
1999 + (void) printf("%-*s ",
2000 + cbp->cb_colwidths[cbp->cb_columns[i]],
2001 + str);
2002 + }
2003 +
2004 + (void) printf("\n");
2005 +}
2006 +
1494 2007 /*
1495 2008 * zfs_get_hole_count retrieves the number of holes (blocks which are
1496 2009 * zero-filled) in the specified file using the _FIO_COUNT_FILLED ioctl. It
1497 2010 * also optionally fetches the block size when bs is non-NULL. With hole count
1498 2011 * and block size the full space consumed by the holes of a file can be
1499 2012 * calculated.
1500 2013 *
1501 2014 * On success, zero is returned, the count argument is set to the
1502 2015 * number of holes, and the bs argument is set to the block size (if it is
1503 2016 * not NULL). On error, a non-zero errno is returned and the values in count
1504 2017 * and bs are undefined.
1505 2018 */
1506 2019 int
1507 2020 zfs_get_hole_count(const char *path, uint64_t *count, uint64_t *bs)
1508 2021 {
1509 2022 int fd, err;
1510 2023 struct stat64 ss;
1511 2024 uint64_t fill;
1512 2025
1513 2026 fd = open(path, O_RDONLY | O_LARGEFILE);
1514 2027 if (fd == -1)
1515 2028 return (errno);
1516 2029
1517 2030 if (ioctl(fd, _FIO_COUNT_FILLED, &fill) == -1) {
1518 2031 err = errno;
1519 2032 (void) close(fd);
1520 2033 return (err);
1521 2034 }
1522 2035
1523 2036 if (fstat64(fd, &ss) == -1) {
1524 2037 err = errno;
1525 2038 (void) close(fd);
1526 2039 return (err);
1527 2040 }
1528 2041
1529 2042 *count = (ss.st_size + ss.st_blksize - 1) / ss.st_blksize - fill;
1530 2043 VERIFY3S(*count, >=, 0);
1531 2044 if (bs != NULL) {
1532 2045 *bs = ss.st_blksize;
1533 2046 }
1534 2047
1535 2048 if (close(fd) == -1) {
1536 2049 return (errno);
1537 2050 }
1538 2051 return (0);
1539 2052 }
|
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX