1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 * Copyright (c) 2013 by Delphix. All rights reserved.
27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
29 * Copyright 2016 Nexenta Systems, Inc.
30 * Copyright (c) 2017 Datto Inc.
31 */
32
33 #include <assert.h>
34 #include <ctype.h>
35 #include <dirent.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <libgen.h>
39 #include <libintl.h>
40 #include <libuutil.h>
41 #include <locale.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <strings.h>
46 #include <unistd.h>
47 #include <priv.h>
48 #include <pwd.h>
49 #include <zone.h>
50 #include <zfs_prop.h>
51 #include <sys/fs/zfs.h>
52 #include <sys/stat.h>
53
54 #include <libzfs.h>
55
56 #include "zpool_util.h"
57 #include "zfs_comutil.h"
58 #include "zfeature_common.h"
59
60 #include "statcommon.h"
61
62 #ifndef MAX
63 #define MAX(x, y) ((x) > (y) ? (x) : (y))
64 #endif /* MAX */
65
66 static int zpool_do_create(int, char **);
67 static int zpool_do_destroy(int, char **);
68
69 static int zpool_do_add(int, char **);
70 static int zpool_do_remove(int, char **);
71 static int zpool_do_labelclear(int, char **);
72
73 static int zpool_do_list(int, char **);
74 static int zpool_do_iostat(int, char **);
75 static int zpool_do_status(int, char **);
76
77 static int zpool_do_online(int, char **);
78 static int zpool_do_offline(int, char **);
79 static int zpool_do_clear(int, char **);
80 static int zpool_do_reopen(int, char **);
81
82 static int zpool_do_reguid(int, char **);
83
84 static int zpool_do_attach(int, char **);
85 static int zpool_do_detach(int, char **);
86 static int zpool_do_replace(int, char **);
87 static int zpool_do_split(int, char **);
88
89 static int zpool_do_scrub(int, char **);
90 static int zpool_do_trim(int, char **);
91
92 static int zpool_do_import(int, char **);
93 static int zpool_do_export(int, char **);
94
95 static int zpool_do_upgrade(int, char **);
96
97 static int zpool_do_history(int, char **);
98
99 static int zpool_do_get(int, char **);
100 static int zpool_do_set(int, char **);
101
102 static int zpool_do_vdev_get(int, char **);
103 static int zpool_do_vdev_set(int, char **);
104
105 static int zpool_do_cos_alloc(int, char **);
106 static int zpool_do_cos_free(int, char **);
107 static int zpool_do_cos_list(int, char **);
108 static int zpool_do_cos_get(int, char **);
109 static int zpool_do_cos_set(int, char **);
110
111 static boolean_t nexenta_meta_enable();
112
113 /*
114 * These libumem hooks provide a reasonable set of defaults for the allocator's
115 * debugging facilities.
116 */
117
118 #ifdef DEBUG
119 const char *
120 _umem_debug_init(void)
121 {
122 return ("default,verbose"); /* $UMEM_DEBUG setting */
123 }
124
125 const char *
126 _umem_logging_init(void)
127 {
128 return ("fail,contents"); /* $UMEM_LOGGING setting */
129 }
130 #endif
131
132 typedef enum {
133 HELP_ADD,
134 HELP_ATTACH,
135 HELP_CLEAR,
136 HELP_CREATE,
137 HELP_DESTROY,
138 HELP_DETACH,
139 HELP_EXPORT,
140 HELP_HISTORY,
141 HELP_IMPORT,
142 HELP_IOSTAT,
143 HELP_LABELCLEAR,
144 HELP_LIST,
145 HELP_OFFLINE,
146 HELP_ONLINE,
147 HELP_REPLACE,
148 HELP_REMOVE,
149 HELP_SCRUB,
150 HELP_TRIM,
151 HELP_STATUS,
152 HELP_UPGRADE,
153 HELP_GET,
154 HELP_SET,
155 HELP_SPLIT,
156 HELP_REGUID,
157 HELP_REOPEN,
158 HELP_VDEV_GET,
159 HELP_VDEV_SET,
160 HELP_COS_ALLOC,
161 HELP_COS_FREE,
162 HELP_COS_LIST,
163 HELP_COS_GET,
164 HELP_COS_SET
165 } zpool_help_t;
166
167
168 typedef struct zpool_command {
169 const char *name;
170 int (*func)(int, char **);
171 zpool_help_t usage;
172 } zpool_command_t;
173
174 /*
175 * Master command table. Each ZFS command has a name, associated function, and
176 * usage message. The usage messages need to be internationalized, so we have
177 * to have a function to return the usage message based on a command index.
178 *
179 * These commands are organized according to how they are displayed in the usage
180 * message. An empty command (one with a NULL name) indicates an empty line in
181 * the generic usage message.
182 */
183 static zpool_command_t command_table[] = {
184 { "create", zpool_do_create, HELP_CREATE },
185 { "destroy", zpool_do_destroy, HELP_DESTROY },
186 { NULL },
187 { "add", zpool_do_add, HELP_ADD },
188 { "remove", zpool_do_remove, HELP_REMOVE },
189 { NULL },
190 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
191 { NULL },
192 { "list", zpool_do_list, HELP_LIST },
193 { "iostat", zpool_do_iostat, HELP_IOSTAT },
194 { "status", zpool_do_status, HELP_STATUS },
195 { NULL },
196 { "online", zpool_do_online, HELP_ONLINE },
197 { "offline", zpool_do_offline, HELP_OFFLINE },
198 { "clear", zpool_do_clear, HELP_CLEAR },
199 { "reopen", zpool_do_reopen, HELP_REOPEN },
200 { NULL },
201 { "attach", zpool_do_attach, HELP_ATTACH },
202 { "detach", zpool_do_detach, HELP_DETACH },
203 { "replace", zpool_do_replace, HELP_REPLACE },
204 { "split", zpool_do_split, HELP_SPLIT },
205 { NULL },
206 { "scrub", zpool_do_scrub, HELP_SCRUB },
207 { NULL },
208 { "trim", zpool_do_trim, HELP_TRIM },
209 { NULL },
210 { "import", zpool_do_import, HELP_IMPORT },
211 { "export", zpool_do_export, HELP_EXPORT },
212 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
213 { "reguid", zpool_do_reguid, HELP_REGUID },
214 { NULL },
215 { "history", zpool_do_history, HELP_HISTORY },
216 { "get", zpool_do_get, HELP_GET },
217 { "set", zpool_do_set, HELP_SET },
218 { "vdev-get", zpool_do_vdev_get, HELP_VDEV_GET },
219 { "vdev-set", zpool_do_vdev_set, HELP_VDEV_SET },
220 { "cos-alloc", zpool_do_cos_alloc, HELP_COS_ALLOC },
221 { "cos-free", zpool_do_cos_free, HELP_COS_FREE },
222 { "cos-list", zpool_do_cos_list, HELP_COS_LIST },
223 { "cos-get", zpool_do_cos_get, HELP_COS_GET },
224 { "cos-set", zpool_do_cos_set, HELP_COS_SET }
225 };
226
227 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
228
229 static zpool_command_t *current_command;
230 static char history_str[HIS_MAX_RECORD_LEN];
231 static boolean_t log_history = B_TRUE;
232 static uint_t timestamp_fmt = NODATE;
233
234 static const char *
235 get_usage(zpool_help_t idx)
236 {
237 switch (idx) {
238 case HELP_ADD:
239 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
240 case HELP_ATTACH:
241 return (gettext("\tattach [-f] <pool> <device> "
242 "<new-device>\n"));
243 case HELP_CLEAR:
244 return (gettext("\tclear [-nF] <pool> [device]\n"));
245 case HELP_CREATE:
246 return (gettext("\tcreate [-fnd] [-B] "
247 "[-o property=value] ... \n"
248 "\t [-O file-system-property=value] ... \n"
249 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
250 case HELP_DESTROY:
251 return (gettext("\tdestroy [-f] <pool>\n"));
252 case HELP_DETACH:
253 return (gettext("\tdetach <pool> <device>\n"));
254 case HELP_EXPORT:
255 return (gettext("\texport [-f] <pool> ...\n"));
256 case HELP_HISTORY:
257 return (gettext("\thistory [-il] [<pool>] ...\n"));
258 case HELP_IMPORT:
259 return (gettext("\timport [-d dir] [-D] [-t num]\n"
260 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
261 "\timport [-o mntopts] [-o property=value] ... \n"
262 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
263 "[-R root] [-F [-n]] [-t num] -a\n"
264 "\timport [-o mntopts] [-o property=value] ... \n"
265 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
266 "[-R root] [-F [-n]]\n"
267 "\t <pool | id> [newpool]\n"));
268 case HELP_IOSTAT:
269 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
270 "[count]]\n"));
271 case HELP_LABELCLEAR:
272 return (gettext("\tlabelclear [-f] <vdev>\n"));
273 case HELP_LIST:
274 return (gettext("\tlist [-Hp] [-o property[,...]] "
275 "[-T d|u] [pool] ... [interval [count]]\n"));
276 case HELP_OFFLINE:
277 return (gettext("\toffline [-t] <pool> <device> ...\n"));
278 case HELP_ONLINE:
279 return (gettext("\tonline <pool> <device> ...\n"));
280 case HELP_REPLACE:
281 return (gettext("\treplace [-f] <pool> <device> "
282 "[new-device]\n"));
283 case HELP_REMOVE:
284 return (gettext("\tremove <pool> <device> ...\n"));
285 case HELP_REOPEN:
286 return (gettext("\treopen <pool>\n"));
287 case HELP_SCRUB:
288 return (gettext("\tscrub [-m|-M|-p|-s] <pool> ...\n"));
289 case HELP_TRIM:
290 return (gettext("\ttrim [-s|-r <rate>] <pool> ...\n"));
291 case HELP_STATUS:
292 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
293 "[count]]\n"));
294 case HELP_UPGRADE:
295 return (gettext("\tupgrade\n"
296 "\tupgrade -v\n"
297 "\tupgrade [-V version] <-a | pool ...>\n"));
298 case HELP_GET:
299 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
300 "<\"all\" | property[,...]> <pool> ...\n"));
301 case HELP_SET:
302 return (gettext("\tset <property=value> <pool> \n"));
303 case HELP_SPLIT:
304 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
305 "\t [-o property=value] <pool> <newpool> "
306 "[<device> ...]\n"));
307 case HELP_REGUID:
308 return (gettext("\treguid <pool>\n"));
309 case HELP_VDEV_GET:
310 return (gettext("\tvdev-get <property | all> <pool> "
311 "<vdev name | GUID>\n"));
312 case HELP_VDEV_SET:
313 return (gettext("\tvdev-set <property=value> <pool> "
314 "<vdev name | GUID>\n"));
315 case HELP_COS_ALLOC:
316 return (gettext("\tcos-alloc <pool> <cos name | GUID>\n"));
317 case HELP_COS_FREE:
318 return (gettext("\tcos-free [-f] <pool> <cos name | GUID>\n"));
319 case HELP_COS_LIST:
320 return (gettext("\tcos-list <pool>\n"));
321 case HELP_COS_GET:
322 return (gettext("\tcos-get <property | all> <pool>"
323 "<cos name | GUID>\n"));
324 case HELP_COS_SET:
325 return (gettext("\tcos-set <property=value> <pool>"
326 "<cos name | GUID>\n"));
327 }
328
329 abort();
330 /* NOTREACHED */
331 }
332 /*
333 * Check if additional ZFS meta features are enabled.
334 */
335 static boolean_t
336 nexenta_meta_enable()
337 {
338 if (getenv("nexenta_meta_enable") == NULL) {
339 (void) fprintf(stderr, gettext("feature not enabled\n"));
340 (void) fprintf(stderr,
341 gettext("set nexenta_meta_enable to access\n"));
342 return (B_FALSE);
343 }
344 return (B_TRUE);
345 }
346
347 /*
348 * Callback routine that will print out a pool property value.
349 */
350 static int
351 print_prop_cb(int prop, void *cb)
352 {
353 FILE *fp = cb;
354
355 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
356
357 if (zpool_prop_readonly(prop))
358 (void) fprintf(fp, " NO ");
359 else
360 (void) fprintf(fp, " YES ");
361
362 if (zpool_prop_values(prop) == NULL)
363 (void) fprintf(fp, "-\n");
364 else
365 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
366
367 return (ZPROP_CONT);
368 }
369
370 /*
371 * Display usage message. If we're inside a command, display only the usage for
372 * that command. Otherwise, iterate over the entire command table and display
373 * a complete usage message.
374 */
375 void
376 usage(boolean_t requested)
377 {
378 FILE *fp = requested ? stdout : stderr;
379
380 if (current_command == NULL) {
381 int i;
382
383 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
384 (void) fprintf(fp,
385 gettext("where 'command' is one of the following:\n\n"));
386
387 for (i = 0; i < NCOMMAND; i++) {
388 if (command_table[i].name == NULL)
389 (void) fprintf(fp, "\n");
390 else
391 (void) fprintf(fp, "%s",
392 get_usage(command_table[i].usage));
393 }
394 } else {
395 (void) fprintf(fp, gettext("usage:\n"));
396 (void) fprintf(fp, "%s", get_usage(current_command->usage));
397 }
398
399 if (current_command != NULL &&
400 ((strcmp(current_command->name, "set") == 0) ||
401 (strcmp(current_command->name, "get") == 0) ||
402 (strcmp(current_command->name, "list") == 0))) {
403
404 (void) fprintf(fp,
405 gettext("\nthe following properties are supported:\n"));
406
407 (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
408 "PROPERTY", "EDIT", "VALUES");
409
410 /* Iterate over all properties */
411 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
412 ZFS_TYPE_POOL);
413
414 (void) fprintf(fp, "\t%-15s ", "feature@...");
415 (void) fprintf(fp, "YES disabled | enabled | active\n");
416
417 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
418 "appended with a feature name.\nSee zpool-features(5).\n"));
419 }
420
421 /*
422 * See comments at end of main().
423 */
424 if (getenv("ZFS_ABORT") != NULL) {
425 (void) printf("dumping core by request\n");
426 abort();
427 }
428
429 exit(requested ? 0 : 2);
430 }
431
432 void
433 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
434 boolean_t print_logs)
435 {
436 nvlist_t **child;
437 uint_t c, children;
438 char *vname;
439
440 if (name != NULL)
441 (void) printf("\t%*s%s\n", indent, "", name);
442
443 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
444 &child, &children) != 0)
445 return;
446
447 for (c = 0; c < children; c++) {
448 uint64_t is_log = B_FALSE;
449
450 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
451 &is_log);
452 if ((is_log && !print_logs) || (!is_log && print_logs))
453 continue;
454
455 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
456 print_vdev_tree(zhp, vname, child[c], indent + 2,
457 B_FALSE);
458 free(vname);
459 }
460 }
461
462 static boolean_t
463 prop_list_contains_feature(nvlist_t *proplist)
464 {
465 nvpair_t *nvp;
466 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
467 nvp = nvlist_next_nvpair(proplist, nvp)) {
468 if (zpool_prop_feature(nvpair_name(nvp)))
469 return (B_TRUE);
470 }
471 return (B_FALSE);
472 }
473
474 /*
475 * Add a property pair (name, string-value) into a property nvlist.
476 */
477 static int
478 add_prop_list(const char *propname, char *propval, nvlist_t **props,
479 boolean_t poolprop)
480 {
481 zpool_prop_t prop = ZPROP_INVAL;
482 zfs_prop_t fprop;
483 nvlist_t *proplist;
484 const char *normnm;
485 char *strval;
486
487 if (*props == NULL &&
488 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
489 (void) fprintf(stderr,
490 gettext("internal error: out of memory\n"));
491 return (1);
492 }
493
494 proplist = *props;
495
496 if (poolprop) {
497 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
498
499 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
500 !zpool_prop_feature(propname)) {
501 (void) fprintf(stderr, gettext("property '%s' is "
502 "not a valid pool property\n"), propname);
503 return (2);
504 }
505
506 /*
507 * feature@ properties and version should not be specified
508 * at the same time.
509 */
510 if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
511 nvlist_exists(proplist, vname)) ||
512 (prop == ZPOOL_PROP_VERSION &&
513 prop_list_contains_feature(proplist))) {
514 (void) fprintf(stderr, gettext("'feature@' and "
515 "'version' properties cannot be specified "
516 "together\n"));
517 return (2);
518 }
519
520
521 if (zpool_prop_feature(propname))
522 normnm = propname;
523 else
524 normnm = zpool_prop_to_name(prop);
525 } else {
526 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
527 normnm = zfs_prop_to_name(fprop);
528 } else {
529 normnm = propname;
530 }
531 }
532
533 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
534 prop != ZPOOL_PROP_CACHEFILE) {
535 (void) fprintf(stderr, gettext("property '%s' "
536 "specified multiple times\n"), propname);
537 return (2);
538 }
539
540 if (nvlist_add_string(proplist, normnm, propval) != 0) {
541 (void) fprintf(stderr, gettext("internal "
542 "error: out of memory\n"));
543 return (1);
544 }
545
546 return (0);
547 }
548
549 /*
550 * Add a property pair (name, string-value) into a vdev property nvlist.
551 */
552 static int
553 add_vdev_prop_list(const char *propname, char *propval, nvlist_t **props)
554 {
555 vdev_prop_t prop = ZPROP_INVAL;
556 nvlist_t *proplist;
557 const char *normnm;
558
559 if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
560 (void) fprintf(stderr,
561 gettext("internal error: out of memory\n"));
562 return (1);
563 }
564
565 proplist = *props;
566 if ((prop = vdev_name_to_prop(propname)) == ZPROP_INVAL) {
567 (void) fprintf(stderr, gettext("property '%s' is "
568 "not a valid vdev property\n"), propname);
569 return (2);
570 }
571 normnm = vdev_prop_to_name(prop);
572
573 if (nvlist_add_string(proplist, normnm, propval) != 0) {
574 (void) fprintf(stderr, gettext("internal "
575 "error: out of memory\n"));
576 return (1);
577 }
578
579 return (0);
580 }
581
582 /*
583 * Add a property pair (name, string-value) into a cos property nvlist.
584 */
585 static int
586 add_cos_prop_list(const char *propname, char *propval, nvlist_t **props)
587 {
588 cos_prop_t prop = ZPROP_INVAL;
589 nvlist_t *proplist;
590 const char *normnm;
591
592 if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
593 (void) fprintf(stderr,
594 gettext("internal error: out of memory\n"));
595 return (1);
596 }
597
598 proplist = *props;
599 if ((prop = cos_name_to_prop(propname)) == ZPROP_INVAL) {
600 (void) fprintf(stderr, gettext("property '%s' is "
601 "not a valid cos property\n"), propname);
602 return (2);
603 }
604 normnm = cos_prop_to_name(prop);
605
606 if (nvlist_add_string(proplist, normnm, propval) != 0) {
607 (void) fprintf(stderr, gettext("internal "
608 "error: out of memory\n"));
609 return (1);
610 }
611
612 return (0);
613 }
614
615 /*
616 * zpool add [-fn] <pool> <vdev> ...
617 *
618 * -f Force addition of devices, even if they appear in use
619 * -n Do not add the devices, but display the resulting layout if
620 * they were to be added.
621 *
622 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
623 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
624 * libzfs.
625 */
626 int
627 zpool_do_add(int argc, char **argv)
628 {
629 boolean_t force = B_FALSE;
630 boolean_t dryrun = B_FALSE;
631 int c;
632 nvlist_t *nvroot;
633 char *poolname;
634 zpool_boot_label_t boot_type;
635 uint64_t boot_size;
636 int ret;
637 zpool_handle_t *zhp;
638 nvlist_t *config;
639
640 /* check options */
641 while ((c = getopt(argc, argv, "fn")) != -1) {
642 switch (c) {
643 case 'f':
644 force = B_TRUE;
645 break;
646 case 'n':
647 dryrun = B_TRUE;
648 break;
649 case '?':
650 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
651 optopt);
652 usage(B_FALSE);
653 }
654 }
655
656 argc -= optind;
657 argv += optind;
658
659 /* get pool name and check number of arguments */
660 if (argc < 1) {
661 (void) fprintf(stderr, gettext("missing pool name argument\n"));
662 usage(B_FALSE);
663 }
664 if (argc < 2) {
665 (void) fprintf(stderr, gettext("missing vdev specification\n"));
666 usage(B_FALSE);
667 }
668
669 poolname = argv[0];
670
671 argc--;
672 argv++;
673
674 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
675 return (1);
676
677 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
678 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
679 poolname);
680 zpool_close(zhp);
681 return (1);
682 }
683
684 if (zpool_is_bootable(zhp))
685 boot_type = ZPOOL_COPY_BOOT_LABEL;
686 else
687 boot_type = ZPOOL_NO_BOOT_LABEL;
688
689 /* pass off to get_vdev_spec for processing */
690 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
691 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
692 boot_type, boot_size, argc, argv);
693 if (nvroot == NULL) {
694 zpool_close(zhp);
695 return (1);
696 }
697
698 if (dryrun) {
699 nvlist_t *poolnvroot;
700
701 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
702 &poolnvroot) == 0);
703
704 (void) printf(gettext("would update '%s' to the following "
705 "configuration:\n"), zpool_get_name(zhp));
706
707 /* print original main pool and new tree */
708 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
709 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
710
711 /* Do the same for the logs */
712 if (num_logs(poolnvroot) > 0) {
713 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
714 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
715 } else if (num_logs(nvroot) > 0) {
716 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
717 }
718
719 ret = 0;
720 } else {
721 ret = (zpool_add(zhp, nvroot) != 0);
722 }
723
724 nvlist_free(nvroot);
725 zpool_close(zhp);
726
727 return (ret);
728 }
729
730 /*
731 * zpool remove <pool> <vdev> ...
732 *
733 * Removes the given vdev from the pool. Currently, this supports removing
734 * spares, cache, and log devices from the pool.
735 */
736 int
737 zpool_do_remove(int argc, char **argv)
738 {
739 char *poolname;
740 int i, ret = 0;
741 zpool_handle_t *zhp;
742
743 argc--;
744 argv++;
745
746 /* get pool name and check number of arguments */
747 if (argc < 1) {
748 (void) fprintf(stderr, gettext("missing pool name argument\n"));
749 usage(B_FALSE);
750 }
751 if (argc < 2) {
752 (void) fprintf(stderr, gettext("missing device\n"));
753 usage(B_FALSE);
754 }
755
756 poolname = argv[0];
757
758 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
759 return (1);
760
761 for (i = 1; i < argc; i++) {
762 if (zpool_vdev_remove(zhp, argv[i]) != 0)
763 ret = 1;
764 }
765
766 return (ret);
767 }
768
769 /*
770 * zpool labelclear [-f] <vdev>
771 *
772 * -f Force clearing the label for the vdevs which are members of
773 * the exported or foreign pools.
774 *
775 * Verifies that the vdev is not active and zeros out the label information
776 * on the device.
777 */
778 int
779 zpool_do_labelclear(int argc, char **argv)
780 {
781 char vdev[MAXPATHLEN];
782 char *name = NULL;
783 struct stat st;
784 int c, fd, ret = 0;
785 nvlist_t *config;
786 pool_state_t state;
787 boolean_t inuse = B_FALSE;
788 boolean_t force = B_FALSE;
789
790 /* check options */
791 while ((c = getopt(argc, argv, "f")) != -1) {
792 switch (c) {
793 case 'f':
794 force = B_TRUE;
795 break;
796 default:
797 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
798 optopt);
799 usage(B_FALSE);
800 }
801 }
802
803 argc -= optind;
804 argv += optind;
805
806 /* get vdev name */
807 if (argc < 1) {
808 (void) fprintf(stderr, gettext("missing vdev name\n"));
809 usage(B_FALSE);
810 }
811 if (argc > 1) {
812 (void) fprintf(stderr, gettext("too many arguments\n"));
813 usage(B_FALSE);
814 }
815
816 /*
817 * Check if we were given absolute path and use it as is.
818 * Otherwise if the provided vdev name doesn't point to a file,
819 * try prepending dsk path and appending s0.
820 */
821 (void) strlcpy(vdev, argv[0], sizeof (vdev));
822 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
823 char *s;
824
825 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
826 ZFS_DISK_ROOT, argv[0]);
827 if ((s = strrchr(argv[0], 's')) == NULL ||
828 !isdigit(*(s + 1)))
829 (void) strlcat(vdev, "s0", sizeof (vdev));
830 if (stat(vdev, &st) != 0) {
831 (void) fprintf(stderr, gettext(
832 "failed to find device %s, try specifying absolute "
833 "path instead\n"), argv[0]);
834 return (1);
835 }
836 }
837
838 if ((fd = open(vdev, O_RDWR)) < 0) {
839 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
840 vdev, strerror(errno));
841 return (1);
842 }
843
844 if (zpool_read_label(fd, &config) != 0) {
845 (void) fprintf(stderr,
846 gettext("failed to read label from %s\n"), vdev);
847 return (1);
848 }
849 nvlist_free(config);
850
851 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
852 if (ret != 0) {
853 (void) fprintf(stderr,
854 gettext("failed to check state for %s\n"), vdev);
855 return (1);
856 }
857
858 if (!inuse)
859 goto wipe_label;
860
861 switch (state) {
862 default:
863 case POOL_STATE_ACTIVE:
864 case POOL_STATE_SPARE:
865 case POOL_STATE_L2CACHE:
866 (void) fprintf(stderr, gettext(
867 "%s is a member (%s) of pool \"%s\"\n"),
868 vdev, zpool_pool_state_to_name(state), name);
869 ret = 1;
870 goto errout;
871
872 case POOL_STATE_EXPORTED:
873 if (force)
874 break;
875 (void) fprintf(stderr, gettext(
876 "use '-f' to override the following error:\n"
877 "%s is a member of exported pool \"%s\"\n"),
878 vdev, name);
879 ret = 1;
880 goto errout;
881
882 case POOL_STATE_POTENTIALLY_ACTIVE:
883 if (force)
884 break;
885 (void) fprintf(stderr, gettext(
886 "use '-f' to override the following error:\n"
887 "%s is a member of potentially active pool \"%s\"\n"),
888 vdev, name);
889 ret = 1;
890 goto errout;
891
892 case POOL_STATE_DESTROYED:
893 /* inuse should never be set for a destroyed pool */
894 assert(0);
895 break;
896 }
897
898 wipe_label:
899 ret = zpool_clear_label(fd);
900 if (ret != 0) {
901 (void) fprintf(stderr,
902 gettext("failed to clear label for %s\n"), vdev);
903 }
904
905 errout:
906 free(name);
907 (void) close(fd);
908
909 return (ret);
910 }
911
912 /*
913 * zpool create [-fnd] [-B] [-o property=value] ...
914 * [-O file-system-property=value] ...
915 * [-R root] [-m mountpoint] <pool> <dev> ...
916 *
917 * -B Create boot partition.
918 * -f Force creation, even if devices appear in use
919 * -n Do not create the pool, but display the resulting layout if it
920 * were to be created.
921 * -R Create a pool under an alternate root
922 * -m Set default mountpoint for the root dataset. By default it's
923 * '/<pool>'
924 * -o Set property=value.
925 * -d Don't automatically enable all supported pool features
926 * (individual features can be enabled with -o).
927 * -O Set fsproperty=value in the pool's root file system
928 *
929 * Creates the named pool according to the given vdev specification. The
930 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
931 * we get the nvlist back from get_vdev_spec(), we either print out the contents
932 * (if '-n' was specified), or pass it to libzfs to do the creation.
933 */
934
935 #define SYSTEM256 (256 * 1024 * 1024)
936 int
937 zpool_do_create(int argc, char **argv)
938 {
939 boolean_t force = B_FALSE;
940 boolean_t dryrun = B_FALSE;
941 boolean_t enable_all_pool_feat = B_TRUE;
942 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
943 uint64_t boot_size = 0;
944 int c;
945 nvlist_t *nvroot = NULL;
946 char *poolname;
947 int ret = 1;
948 char *altroot = NULL;
949 char *mountpoint = NULL;
950 nvlist_t *fsprops = NULL;
951 nvlist_t *props = NULL;
952 char *propval;
953
954 /* check options */
955 while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) {
956 switch (c) {
957 case 'f':
958 force = B_TRUE;
959 break;
960 case 'n':
961 dryrun = B_TRUE;
962 break;
963 case 'd':
964 enable_all_pool_feat = B_FALSE;
965 break;
966 case 'B':
967 /*
968 * We should create the system partition.
969 * Also make sure the size is set.
970 */
971 boot_type = ZPOOL_CREATE_BOOT_LABEL;
972 if (boot_size == 0)
973 boot_size = SYSTEM256;
974 break;
975 case 'R':
976 altroot = optarg;
977 if (add_prop_list(zpool_prop_to_name(
978 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
979 goto errout;
980 if (nvlist_lookup_string(props,
981 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
982 &propval) == 0)
983 break;
984 if (add_prop_list(zpool_prop_to_name(
985 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
986 goto errout;
987 break;
988 case 'm':
989 /* Equivalent to -O mountpoint=optarg */
990 mountpoint = optarg;
991 break;
992 case 'o':
993 if ((propval = strchr(optarg, '=')) == NULL) {
994 (void) fprintf(stderr, gettext("missing "
995 "'=' for -o option\n"));
996 goto errout;
997 }
998 *propval = '\0';
999 propval++;
1000
1001 if (add_prop_list(optarg, propval, &props, B_TRUE))
1002 goto errout;
1003
1004 /*
1005 * Get bootsize value for make_root_vdev().
1006 */
1007 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
1008 if (zfs_nicestrtonum(g_zfs, propval,
1009 &boot_size) < 0 || boot_size == 0) {
1010 (void) fprintf(stderr,
1011 gettext("bad boot partition size "
1012 "'%s': %s\n"), propval,
1013 libzfs_error_description(g_zfs));
1014 goto errout;
1015 }
1016 }
1017
1018 /*
1019 * If the user is creating a pool that doesn't support
1020 * feature flags, don't enable any features.
1021 */
1022 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1023 char *end;
1024 u_longlong_t ver;
1025
1026 ver = strtoull(propval, &end, 10);
1027 if (*end == '\0' &&
1028 ver < SPA_VERSION_FEATURES) {
1029 enable_all_pool_feat = B_FALSE;
1030 }
1031 }
1032 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1033 altroot = propval;
1034 break;
1035 case 'O':
1036 if ((propval = strchr(optarg, '=')) == NULL) {
1037 (void) fprintf(stderr, gettext("missing "
1038 "'=' for -O option\n"));
1039 goto errout;
1040 }
1041 *propval = '\0';
1042 propval++;
1043
1044 /*
1045 * Mountpoints are checked and then added later.
1046 * Uniquely among properties, they can be specified
1047 * more than once, to avoid conflict with -m.
1048 */
1049 if (0 == strcmp(optarg,
1050 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1051 mountpoint = propval;
1052 } else if (add_prop_list(optarg, propval, &fsprops,
1053 B_FALSE)) {
1054 goto errout;
1055 }
1056 break;
1057 case ':':
1058 (void) fprintf(stderr, gettext("missing argument for "
1059 "'%c' option\n"), optopt);
1060 goto badusage;
1061 case '?':
1062 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1063 optopt);
1064 goto badusage;
1065 }
1066 }
1067
1068 argc -= optind;
1069 argv += optind;
1070
1071 /* get pool name and check number of arguments */
1072 if (argc < 1) {
1073 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1074 goto badusage;
1075 }
1076 if (argc < 2) {
1077 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1078 goto badusage;
1079 }
1080
1081 poolname = argv[0];
1082
1083 /*
1084 * As a special case, check for use of '/' in the name, and direct the
1085 * user to use 'zfs create' instead.
1086 */
1087 if (strchr(poolname, '/') != NULL) {
1088 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1089 "character '/' in pool name\n"), poolname);
1090 (void) fprintf(stderr, gettext("use 'zfs create' to "
1091 "create a dataset\n"));
1092 goto errout;
1093 }
1094
1095 /*
1096 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1097 * and not set otherwise.
1098 */
1099 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1100 const char *propname;
1101 char *strptr, *buf = NULL;
1102 int rv;
1103
1104 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1105 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1106 (void) asprintf(&buf, "%" PRIu64, boot_size);
1107 if (buf == NULL) {
1108 (void) fprintf(stderr,
1109 gettext("internal error: out of memory\n"));
1110 goto errout;
1111 }
1112 rv = add_prop_list(propname, buf, &props, B_TRUE);
1113 free(buf);
1114 if (rv != 0)
1115 goto errout;
1116 }
1117 } else {
1118 const char *propname;
1119 char *strptr;
1120
1121 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1122 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1123 (void) fprintf(stderr, gettext("error: setting boot "
1124 "partition size requires option '-B'\n"));
1125 goto errout;
1126 }
1127 }
1128
1129 /* pass off to get_vdev_spec for bulk processing */
1130 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1131 boot_type, boot_size, argc - 1, argv + 1);
1132 if (nvroot == NULL)
1133 goto errout;
1134
1135 /* make_root_vdev() allows 0 toplevel children if there are spares */
1136 if (!zfs_allocatable_devs(nvroot)) {
1137 (void) fprintf(stderr, gettext("invalid vdev "
1138 "specification: at least one toplevel vdev must be "
1139 "specified\n"));
1140 goto errout;
1141 }
1142
1143 if (altroot != NULL && altroot[0] != '/') {
1144 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1145 "must be an absolute path\n"), altroot);
1146 goto errout;
1147 }
1148
1149 /*
1150 * Check the validity of the mountpoint and direct the user to use the
1151 * '-m' mountpoint option if it looks like its in use.
1152 */
1153 if (mountpoint == NULL ||
1154 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1155 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1156 char buf[MAXPATHLEN];
1157 DIR *dirp;
1158
1159 if (mountpoint && mountpoint[0] != '/') {
1160 (void) fprintf(stderr, gettext("invalid mountpoint "
1161 "'%s': must be an absolute path, 'legacy', or "
1162 "'none'\n"), mountpoint);
1163 goto errout;
1164 }
1165
1166 if (mountpoint == NULL) {
1167 if (altroot != NULL)
1168 (void) snprintf(buf, sizeof (buf), "%s/%s",
1169 altroot, poolname);
1170 else
1171 (void) snprintf(buf, sizeof (buf), "/%s",
1172 poolname);
1173 } else {
1174 if (altroot != NULL)
1175 (void) snprintf(buf, sizeof (buf), "%s%s",
1176 altroot, mountpoint);
1177 else
1178 (void) snprintf(buf, sizeof (buf), "%s",
1179 mountpoint);
1180 }
1181
1182 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1183 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1184 "%s\n"), buf, strerror(errno));
1185 (void) fprintf(stderr, gettext("use '-m' "
1186 "option to provide a different default\n"));
1187 goto errout;
1188 } else if (dirp) {
1189 int count = 0;
1190
1191 while (count < 3 && readdir(dirp) != NULL)
1192 count++;
1193 (void) closedir(dirp);
1194
1195 if (count > 2) {
1196 (void) fprintf(stderr, gettext("mountpoint "
1197 "'%s' exists and is not empty\n"), buf);
1198 (void) fprintf(stderr, gettext("use '-m' "
1199 "option to provide a "
1200 "different default\n"));
1201 goto errout;
1202 }
1203 }
1204 }
1205
1206 /*
1207 * Now that the mountpoint's validity has been checked, ensure that
1208 * the property is set appropriately prior to creating the pool.
1209 */
1210 if (mountpoint != NULL) {
1211 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1212 mountpoint, &fsprops, B_FALSE);
1213 if (ret != 0)
1214 goto errout;
1215 }
1216
1217 ret = 1;
1218 if (dryrun) {
1219 /*
1220 * For a dry run invocation, print out a basic message and run
1221 * through all the vdevs in the list and print out in an
1222 * appropriate hierarchy.
1223 */
1224 (void) printf(gettext("would create '%s' with the "
1225 "following layout:\n\n"), poolname);
1226
1227 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1228 if (num_logs(nvroot) > 0)
1229 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1230
1231 ret = 0;
1232 } else {
1233 /*
1234 * Hand off to libzfs.
1235 */
1236 if (enable_all_pool_feat) {
1237 spa_feature_t i;
1238 for (i = 0; i < SPA_FEATURES; i++) {
1239 char propname[MAXPATHLEN];
1240 zfeature_info_t *feat = &spa_feature_table[i];
1241
1242 (void) snprintf(propname, sizeof (propname),
1243 "feature@%s", feat->fi_uname);
1244
1245 /*
1246 * Skip feature if user specified it manually
1247 * on the command line.
1248 */
1249 if (nvlist_exists(props, propname))
1250 continue;
1251
1252 ret = add_prop_list(propname,
1253 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1254 if (ret != 0)
1255 goto errout;
1256 }
1257 }
1258
1259 ret = 1;
1260 if (zpool_create(g_zfs, poolname,
1261 nvroot, props, fsprops) == 0) {
1262 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
1263 ZFS_TYPE_FILESYSTEM);
1264 if (pool != NULL) {
1265 if (zfs_mount(pool, NULL, 0) == 0)
1266 ret = zfs_shareall(pool);
1267 zfs_close(pool);
1268 }
1269 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1270 (void) fprintf(stderr, gettext("pool name may have "
1271 "been omitted\n"));
1272 }
1273 }
1274
1275 errout:
1276 nvlist_free(nvroot);
1277 nvlist_free(fsprops);
1278 nvlist_free(props);
1279 return (ret);
1280 badusage:
1281 nvlist_free(fsprops);
1282 nvlist_free(props);
1283 usage(B_FALSE);
1284 return (2);
1285 }
1286
1287 /*
1288 * zpool destroy <pool>
1289 *
1290 * -f Forcefully unmount any datasets
1291 *
1292 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1293 */
1294 int
1295 zpool_do_destroy(int argc, char **argv)
1296 {
1297 boolean_t force = B_FALSE;
1298 int c;
1299 char *pool;
1300 zpool_handle_t *zhp;
1301 int ret;
1302
1303 /* check options */
1304 while ((c = getopt(argc, argv, "f")) != -1) {
1305 switch (c) {
1306 case 'f':
1307 force = B_TRUE;
1308 break;
1309 case '?':
1310 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1311 optopt);
1312 usage(B_FALSE);
1313 }
1314 }
1315
1316 argc -= optind;
1317 argv += optind;
1318
1319 /* check arguments */
1320 if (argc < 1) {
1321 (void) fprintf(stderr, gettext("missing pool argument\n"));
1322 usage(B_FALSE);
1323 }
1324 if (argc > 1) {
1325 (void) fprintf(stderr, gettext("too many arguments\n"));
1326 usage(B_FALSE);
1327 }
1328
1329 pool = argv[0];
1330
1331 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1332 /*
1333 * As a special case, check for use of '/' in the name, and
1334 * direct the user to use 'zfs destroy' instead.
1335 */
1336 if (strchr(pool, '/') != NULL)
1337 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1338 "destroy a dataset\n"));
1339 return (1);
1340 }
1341
1342 ret = zfs_check_krrp(g_zfs, argv[0]);
1343 /*
1344 * ENOTSUP means that autosnaper doesn't handle this pool.
1345 */
1346 if (ret != ENOTSUP) {
1347 if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1348 ret = EBUSY;
1349
1350 if (ret) {
1351 (void) zpool_standard_error(g_zfs,
1352 ret, gettext("cannnot destroy pool because "
1353 "of krrp"));
1354 zpool_close(zhp);
1355 ret = 1;
1356 return (ret);
1357 }
1358 } else {
1359 ret = 0;
1360 }
1361
1362 if (zpool_disable_datasets(zhp, force) != 0) {
1363 (void) fprintf(stderr, gettext("could not destroy '%s': "
1364 "could not unmount datasets\n"), zpool_get_name(zhp));
1365 return (1);
1366 }
1367
1368 /* The history must be logged as part of the export */
1369 log_history = B_FALSE;
1370
1371 ret = (zpool_destroy(zhp, history_str) != 0);
1372
1373 zpool_close(zhp);
1374
1375 return (ret);
1376 }
1377
1378 /*
1379 * zpool export [-f] <pool> ...
1380 *
1381 * -f Forcefully unmount datasets
1382 *
1383 * Export the given pools. By default, the command will attempt to cleanly
1384 * unmount any active datasets within the pool. If the '-f' flag is specified,
1385 * then the datasets will be forcefully unmounted.
1386 */
1387 int
1388 zpool_do_export(int argc, char **argv)
1389 {
1390 boolean_t force = B_FALSE;
1391 boolean_t hardforce = B_FALSE;
1392 boolean_t saveconfig = B_FALSE;
1393 int c;
1394 int n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
1395 zpool_handle_t *zhp;
1396 int ret;
1397 int i;
1398
1399 /* check options */
1400 while ((c = getopt(argc, argv, ":fFct:")) != -1) {
1401 switch (c) {
1402 case 'f':
1403 force = B_TRUE;
1404 break;
1405 case 'F':
1406 hardforce = B_TRUE;
1407 break;
1408 case 'c':
1409 saveconfig = B_TRUE;
1410 break;
1411 case 't':
1412 n_threads = atoi(optarg);
1413 break;
1414 case '?':
1415 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1416 optopt);
1417 usage(B_FALSE);
1418 break;
1419 case ':':
1420 (void) fprintf(stderr, gettext("missing argument "
1421 "for option '%c'\n"), optopt);
1422 usage(B_FALSE);
1423 break;
1424 }
1425 }
1426
1427 argc -= optind;
1428 argv += optind;
1429
1430 /* check arguments */
1431 if (argc < 1) {
1432 (void) fprintf(stderr, gettext("missing pool argument\n"));
1433 usage(B_FALSE);
1434 }
1435
1436 ret = 0;
1437 for (i = 0; i < argc; i++) {
1438 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1439 ret = 1;
1440 continue;
1441 }
1442
1443 ret = zfs_check_krrp(g_zfs, argv[0]);
1444 /*
1445 * ENOTSUP means that autosnaper doesn't handle this pool.
1446 */
1447 if (ret != ENOTSUP) {
1448 if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1449 ret = EBUSY;
1450
1451 if (ret) {
1452 (void) zpool_standard_error(g_zfs,
1453 ret, gettext("cannnot export pool because "
1454 "of krrp"));
1455 zpool_close(zhp);
1456 ret = 1;
1457 continue;
1458 }
1459 } else {
1460 ret = 0;
1461 }
1462
1463 if (zpool_disable_datasets_ex(zhp, force, n_threads) != 0) {
1464 ret = 1;
1465 zpool_close(zhp);
1466 continue;
1467 }
1468
1469 /* The history must be logged as part of the export */
1470 log_history = B_FALSE;
1471
1472 if (hardforce) {
1473 if (zpool_export_force(zhp, saveconfig, history_str)
1474 != 0)
1475 ret = 1;
1476 } else if (zpool_export(zhp, force, saveconfig, history_str)
1477 != 0) {
1478 ret = 1;
1479 }
1480
1481 zpool_close(zhp);
1482 }
1483
1484 return (ret);
1485 }
1486
1487 /*
1488 * Given a vdev configuration, determine the maximum width needed for the device
1489 * name column.
1490 */
1491 static int
1492 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1493 {
1494 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1495 nvlist_t **child;
1496 uint_t c, children;
1497 int ret;
1498
1499 if (strlen(name) + depth > max)
1500 max = strlen(name) + depth;
1501
1502 free(name);
1503
1504 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1505 &child, &children) == 0) {
1506 for (c = 0; c < children; c++)
1507 if ((ret = max_width(zhp, child[c], depth + 2,
1508 max)) > max)
1509 max = ret;
1510 }
1511
1512 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1513 &child, &children) == 0) {
1514 for (c = 0; c < children; c++)
1515 if ((ret = max_width(zhp, child[c], depth + 2,
1516 max)) > max)
1517 max = ret;
1518 }
1519
1520 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1521 &child, &children) == 0) {
1522 for (c = 0; c < children; c++)
1523 if ((ret = max_width(zhp, child[c], depth + 2,
1524 max)) > max)
1525 max = ret;
1526 }
1527
1528
1529 return (max);
1530 }
1531
1532 typedef struct spare_cbdata {
1533 uint64_t cb_guid;
1534 zpool_handle_t *cb_zhp;
1535 } spare_cbdata_t;
1536
1537 static boolean_t
1538 find_vdev(nvlist_t *nv, uint64_t search)
1539 {
1540 uint64_t guid;
1541 nvlist_t **child;
1542 uint_t c, children;
1543
1544 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1545 search == guid)
1546 return (B_TRUE);
1547
1548 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1549 &child, &children) == 0) {
1550 for (c = 0; c < children; c++)
1551 if (find_vdev(child[c], search))
1552 return (B_TRUE);
1553 }
1554
1555 return (B_FALSE);
1556 }
1557
1558 static int
1559 find_spare(zpool_handle_t *zhp, void *data)
1560 {
1561 spare_cbdata_t *cbp = data;
1562 nvlist_t *config, *nvroot;
1563
1564 config = zpool_get_config(zhp, NULL);
1565 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1566 &nvroot) == 0);
1567
1568 if (find_vdev(nvroot, cbp->cb_guid)) {
1569 cbp->cb_zhp = zhp;
1570 return (1);
1571 }
1572
1573 zpool_close(zhp);
1574 return (0);
1575 }
1576
1577 /*
1578 * Print out configuration state as requested by status_callback.
1579 */
1580 void
1581 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1582 int namewidth, int depth, boolean_t isspare)
1583 {
1584 nvlist_t **child;
1585 uint_t c, children;
1586 pool_scan_stat_t *ps = NULL;
1587 vdev_stat_t *vs;
1588 char rbuf[6], wbuf[6], cbuf[6];
1589 char *vname;
1590 uint64_t notpresent;
1591 spare_cbdata_t cb;
1592 const char *state;
1593
1594 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1595 &child, &children) != 0)
1596 children = 0;
1597
1598 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1599 (uint64_t **)&vs, &c) == 0);
1600
1601 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1602 if (isspare) {
1603 /*
1604 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1605 * online drives.
1606 */
1607 if (vs->vs_aux == VDEV_AUX_SPARED)
1608 state = "INUSE";
1609 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1610 state = "AVAIL";
1611 }
1612
1613 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1614 name, state);
1615
1616 if (!isspare) {
1617 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1618 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1619 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1620 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1621 }
1622
1623 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1624 ¬present) == 0) {
1625 char *path;
1626 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1627 (void) printf(" was %s", path);
1628 } else if (vs->vs_aux != 0) {
1629 (void) printf(" ");
1630
1631 switch (vs->vs_aux) {
1632 case VDEV_AUX_OPEN_FAILED:
1633 (void) printf(gettext("cannot open"));
1634 break;
1635
1636 case VDEV_AUX_BAD_GUID_SUM:
1637 (void) printf(gettext("missing device"));
1638 break;
1639
1640 case VDEV_AUX_NO_REPLICAS:
1641 (void) printf(gettext("insufficient replicas"));
1642 break;
1643
1644 case VDEV_AUX_VERSION_NEWER:
1645 (void) printf(gettext("newer version"));
1646 break;
1647
1648 case VDEV_AUX_UNSUP_FEAT:
1649 (void) printf(gettext("unsupported feature(s)"));
1650 break;
1651
1652 case VDEV_AUX_SPARED:
1653 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1654 &cb.cb_guid) == 0);
1655 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1656 if (strcmp(zpool_get_name(cb.cb_zhp),
1657 zpool_get_name(zhp)) == 0)
1658 (void) printf(gettext("currently in "
1659 "use"));
1660 else
1661 (void) printf(gettext("in use by "
1662 "pool '%s'"),
1663 zpool_get_name(cb.cb_zhp));
1664 zpool_close(cb.cb_zhp);
1665 } else {
1666 (void) printf(gettext("currently in use"));
1667 }
1668 break;
1669
1670 case VDEV_AUX_ERR_EXCEEDED:
1671 (void) printf(gettext("too many errors"));
1672 break;
1673
1674 case VDEV_AUX_IO_FAILURE:
1675 (void) printf(gettext("experienced I/O failures"));
1676 break;
1677
1678 case VDEV_AUX_BAD_LOG:
1679 (void) printf(gettext("bad intent log"));
1680 break;
1681
1682 case VDEV_AUX_EXTERNAL:
1683 (void) printf(gettext("external device fault"));
1684 break;
1685
1686 case VDEV_AUX_SPLIT_POOL:
1687 (void) printf(gettext("split into new pool"));
1688 break;
1689
1690 default:
1691 (void) printf(gettext("corrupted data"));
1692 break;
1693 }
1694 }
1695
1696 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1697 (uint64_t **)&ps, &c);
1698
1699 if (ps != NULL && (ps->pss_state == DSS_SCANNING ||
1700 ps->pss_state == DSS_FINISHING) && vs->vs_scan_processed != 0 &&
1701 children == 0) {
1702 (void) printf(gettext(" (%s)"),
1703 (ps->pss_func == POOL_SCAN_RESILVER) ?
1704 "resilvering" : "repairing");
1705 }
1706
1707 (void) printf("\n");
1708
1709 for (c = 0; c < children; c++) {
1710 uint64_t islog = B_FALSE, ishole = B_FALSE, isspecial = B_FALSE;
1711
1712 /* Don't print logs or holes here */
1713 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1714 &islog);
1715 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1716 &ishole);
1717 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1718 &isspecial);
1719 if (islog || ishole || isspecial)
1720 continue;
1721 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1722 print_status_config(zhp, vname, child[c],
1723 namewidth, depth + 2, isspare);
1724 free(vname);
1725 }
1726 }
1727
1728
1729 /*
1730 * Print the configuration of an exported pool. Iterate over all vdevs in the
1731 * pool, printing out the name and status for each one.
1732 */
1733 void
1734 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1735 {
1736 nvlist_t **child;
1737 uint_t c, children;
1738 vdev_stat_t *vs;
1739 char *type, *vname;
1740
1741 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1742 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1743 strcmp(type, VDEV_TYPE_HOLE) == 0)
1744 return;
1745
1746 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1747 (uint64_t **)&vs, &c) == 0);
1748
1749 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1750 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1751
1752 if (vs->vs_aux != 0) {
1753 (void) printf(" ");
1754
1755 switch (vs->vs_aux) {
1756 case VDEV_AUX_OPEN_FAILED:
1757 (void) printf(gettext("cannot open"));
1758 break;
1759
1760 case VDEV_AUX_BAD_GUID_SUM:
1761 (void) printf(gettext("missing device"));
1762 break;
1763
1764 case VDEV_AUX_NO_REPLICAS:
1765 (void) printf(gettext("insufficient replicas"));
1766 break;
1767
1768 case VDEV_AUX_VERSION_NEWER:
1769 (void) printf(gettext("newer version"));
1770 break;
1771
1772 case VDEV_AUX_UNSUP_FEAT:
1773 (void) printf(gettext("unsupported feature(s)"));
1774 break;
1775
1776 case VDEV_AUX_ERR_EXCEEDED:
1777 (void) printf(gettext("too many errors"));
1778 break;
1779
1780 default:
1781 (void) printf(gettext("corrupted data"));
1782 break;
1783 }
1784 }
1785 (void) printf("\n");
1786
1787 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1788 &child, &children) != 0)
1789 return;
1790
1791 for (c = 0; c < children; c++) {
1792 uint64_t is_log = B_FALSE, is_special = B_FALSE;
1793
1794 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1795 &is_log);
1796 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1797 &is_special);
1798 if (is_log || is_special)
1799 continue;
1800
1801 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1802 print_import_config(vname, child[c], namewidth, depth + 2);
1803 free(vname);
1804 }
1805
1806 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1807 &child, &children) == 0) {
1808 (void) printf(gettext("\tcache\n"));
1809 for (c = 0; c < children; c++) {
1810 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1811 (void) printf("\t %s\n", vname);
1812 free(vname);
1813 }
1814 }
1815
1816 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1817 &child, &children) == 0) {
1818 (void) printf(gettext("\tspares\n"));
1819 for (c = 0; c < children; c++) {
1820 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1821 (void) printf("\t %s\n", vname);
1822 free(vname);
1823 }
1824 }
1825 }
1826
1827 /*
1828 * Print log vdevs.
1829 * Logs are recorded as top level vdevs in the main pool child array
1830 * but with "is_log" set to 1. We use either print_status_config() or
1831 * print_import_config() to print the top level logs then any log
1832 * children (eg mirrored slogs) are printed recursively - which
1833 * works because only the top level vdev is marked "is_log"
1834 */
1835 static void
1836 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1837 {
1838 uint_t c, children;
1839 nvlist_t **child;
1840
1841 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1842 &children) != 0)
1843 return;
1844
1845 (void) printf(gettext("\tlogs\n"));
1846
1847 for (c = 0; c < children; c++) {
1848 uint64_t is_log = B_FALSE;
1849 char *name;
1850
1851 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1852 &is_log);
1853 if (!is_log)
1854 continue;
1855 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1856 if (verbose)
1857 print_status_config(zhp, name, child[c], namewidth,
1858 2, B_FALSE);
1859 else
1860 print_import_config(name, child[c], namewidth, 2);
1861 free(name);
1862 }
1863 }
1864
1865 /*
1866 * Print special vdevs.
1867 * Special vdevs are recorded as top level vdevs in the main pool child array
1868 * but with "is_special" set to 1. We use either print_status_config() or
1869 * print_import_config() to print the top level logs then any log
1870 * children (eg mirrored slogs) are printed recursively - which
1871 * works because only the top level vdev is marked "is_special"
1872 */
1873 static void
1874 print_special(zpool_handle_t *zhp, nvlist_t *nv, int namewidth,
1875 boolean_t verbose)
1876 {
1877 uint_t c, children;
1878 nvlist_t **child;
1879
1880 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1881 &children) != 0)
1882 return;
1883
1884 (void) printf(gettext("\tspecial\n"));
1885
1886 for (c = 0; c < children; c++) {
1887 uint64_t is_special = B_FALSE;
1888 char *name;
1889
1890 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1891 &is_special);
1892 if (!is_special)
1893 continue;
1894 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1895 if (verbose)
1896 print_status_config(zhp, name, child[c], namewidth,
1897 2, B_FALSE);
1898 else
1899 print_import_config(name, child[c], namewidth, 2);
1900 free(name);
1901 }
1902 }
1903
1904 /*
1905 * Display the status for the given pool.
1906 */
1907 static void
1908 show_import(nvlist_t *config)
1909 {
1910 uint64_t pool_state;
1911 vdev_stat_t *vs;
1912 char *name;
1913 uint64_t guid;
1914 char *msgid;
1915 nvlist_t *nvroot;
1916 int reason;
1917 const char *health;
1918 uint_t vsc;
1919 int namewidth;
1920 char *comment;
1921
1922 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1923 &name) == 0);
1924 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1925 &guid) == 0);
1926 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1927 &pool_state) == 0);
1928 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1929 &nvroot) == 0);
1930
1931 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1932 (uint64_t **)&vs, &vsc) == 0);
1933 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1934
1935 reason = zpool_import_status(config, &msgid);
1936
1937 (void) printf(gettext(" pool: %s\n"), name);
1938 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1939 (void) printf(gettext(" state: %s"), health);
1940 if (pool_state == POOL_STATE_DESTROYED)
1941 (void) printf(gettext(" (DESTROYED)"));
1942 (void) printf("\n");
1943
1944 switch (reason) {
1945 case ZPOOL_STATUS_MISSING_DEV_R:
1946 case ZPOOL_STATUS_MISSING_DEV_NR:
1947 case ZPOOL_STATUS_BAD_GUID_SUM:
1948 (void) printf(gettext(" status: One or more devices are "
1949 "missing from the system.\n"));
1950 break;
1951
1952 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1953 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1954 (void) printf(gettext(" status: One or more devices contains "
1955 "corrupted data.\n"));
1956 break;
1957
1958 case ZPOOL_STATUS_CORRUPT_DATA:
1959 (void) printf(
1960 gettext(" status: The pool data is corrupted.\n"));
1961 break;
1962
1963 case ZPOOL_STATUS_OFFLINE_DEV:
1964 (void) printf(gettext(" status: One or more devices "
1965 "are offlined.\n"));
1966 break;
1967
1968 case ZPOOL_STATUS_CORRUPT_POOL:
1969 (void) printf(gettext(" status: The pool metadata is "
1970 "corrupted.\n"));
1971 break;
1972
1973 case ZPOOL_STATUS_VERSION_OLDER:
1974 (void) printf(gettext(" status: The pool is formatted using a "
1975 "legacy on-disk version.\n"));
1976 break;
1977
1978 case ZPOOL_STATUS_VERSION_NEWER:
1979 (void) printf(gettext(" status: The pool is formatted using an "
1980 "incompatible version.\n"));
1981 break;
1982
1983 case ZPOOL_STATUS_FEAT_DISABLED:
1984 (void) printf(gettext(" status: Some supported features are "
1985 "not enabled on the pool.\n"));
1986 break;
1987
1988 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1989 (void) printf(gettext("status: The pool uses the following "
1990 "feature(s) not supported on this sytem:\n"));
1991 zpool_print_unsup_feat(config);
1992 break;
1993
1994 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1995 (void) printf(gettext("status: The pool can only be accessed "
1996 "in read-only mode on this system. It\n\tcannot be "
1997 "accessed in read-write mode because it uses the "
1998 "following\n\tfeature(s) not supported on this system:\n"));
1999 zpool_print_unsup_feat(config);
2000 break;
2001
2002 case ZPOOL_STATUS_HOSTID_MISMATCH:
2003 (void) printf(gettext(" status: The pool was last accessed by "
2004 "another system.\n"));
2005 break;
2006
2007 case ZPOOL_STATUS_FAULTED_DEV_R:
2008 case ZPOOL_STATUS_FAULTED_DEV_NR:
2009 (void) printf(gettext(" status: One or more devices are "
2010 "faulted.\n"));
2011 break;
2012
2013 case ZPOOL_STATUS_BAD_LOG:
2014 (void) printf(gettext(" status: An intent log record cannot be "
2015 "read.\n"));
2016 break;
2017
2018 case ZPOOL_STATUS_RESILVERING:
2019 (void) printf(gettext(" status: One or more devices were being "
2020 "resilvered.\n"));
2021 break;
2022
2023 default:
2024 /*
2025 * No other status can be seen when importing pools.
2026 */
2027 assert(reason == ZPOOL_STATUS_OK);
2028 }
2029
2030 /*
2031 * Print out an action according to the overall state of the pool.
2032 */
2033 if (vs->vs_state == VDEV_STATE_HEALTHY) {
2034 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2035 reason == ZPOOL_STATUS_FEAT_DISABLED) {
2036 (void) printf(gettext(" action: The pool can be "
2037 "imported using its name or numeric identifier, "
2038 "though\n\tsome features will not be available "
2039 "without an explicit 'zpool upgrade'.\n"));
2040 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
2041 (void) printf(gettext(" action: The pool can be "
2042 "imported using its name or numeric "
2043 "identifier and\n\tthe '-f' flag.\n"));
2044 } else {
2045 (void) printf(gettext(" action: The pool can be "
2046 "imported using its name or numeric "
2047 "identifier.\n"));
2048 }
2049 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2050 (void) printf(gettext(" action: The pool can be imported "
2051 "despite missing or damaged devices. The\n\tfault "
2052 "tolerance of the pool may be compromised if imported.\n"));
2053 } else {
2054 switch (reason) {
2055 case ZPOOL_STATUS_VERSION_NEWER:
2056 (void) printf(gettext(" action: The pool cannot be "
2057 "imported. Access the pool on a system running "
2058 "newer\n\tsoftware, or recreate the pool from "
2059 "backup.\n"));
2060 break;
2061 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2062 (void) printf(gettext("action: The pool cannot be "
2063 "imported. Access the pool on a system that "
2064 "supports\n\tthe required feature(s), or recreate "
2065 "the pool from backup.\n"));
2066 break;
2067 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2068 (void) printf(gettext("action: The pool cannot be "
2069 "imported in read-write mode. Import the pool "
2070 "with\n"
2071 "\t\"-o readonly=on\", access the pool on a system "
2072 "that supports the\n\trequired feature(s), or "
2073 "recreate the pool from backup.\n"));
2074 break;
2075 case ZPOOL_STATUS_MISSING_DEV_R:
2076 case ZPOOL_STATUS_MISSING_DEV_NR:
2077 case ZPOOL_STATUS_BAD_GUID_SUM:
2078 (void) printf(gettext(" action: The pool cannot be "
2079 "imported. Attach the missing\n\tdevices and try "
2080 "again.\n"));
2081 break;
2082 default:
2083 (void) printf(gettext(" action: The pool cannot be "
2084 "imported due to damaged devices or data.\n"));
2085 }
2086 }
2087
2088 /* Print the comment attached to the pool. */
2089 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2090 (void) printf(gettext("comment: %s\n"), comment);
2091
2092 /*
2093 * If the state is "closed" or "can't open", and the aux state
2094 * is "corrupt data":
2095 */
2096 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2097 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2098 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2099 if (pool_state == POOL_STATE_DESTROYED)
2100 (void) printf(gettext("\tThe pool was destroyed, "
2101 "but can be imported using the '-Df' flags.\n"));
2102 else if (pool_state != POOL_STATE_EXPORTED)
2103 (void) printf(gettext("\tThe pool may be active on "
2104 "another system, but can be imported using\n\t"
2105 "the '-f' flag.\n"));
2106 }
2107
2108 if (msgid != NULL)
2109 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
2110 msgid);
2111
2112 (void) printf(gettext(" config:\n\n"));
2113
2114 namewidth = max_width(NULL, nvroot, 0, 0);
2115 if (namewidth < 10)
2116 namewidth = 10;
2117
2118 print_import_config(name, nvroot, namewidth, 0);
2119 if (num_special(nvroot) > 0)
2120 print_special(NULL, nvroot, namewidth, B_FALSE);
2121
2122 if (num_logs(nvroot) > 0)
2123 print_logs(NULL, nvroot, namewidth, B_FALSE);
2124
2125 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2126 (void) printf(gettext("\n\tAdditional devices are known to "
2127 "be part of this pool, though their\n\texact "
2128 "configuration cannot be determined.\n"));
2129 }
2130 }
2131
2132 /*
2133 * Perform the import for the given configuration. This passes the heavy
2134 * lifting off to zpool_import_props(), and then mounts the datasets contained
2135 * within the pool.
2136 */
2137 static int
2138 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2139 nvlist_t *props, int flags, int n_threads)
2140 {
2141 zpool_handle_t *zhp;
2142 char *name;
2143 uint64_t state;
2144 uint64_t version;
2145
2146 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2147 &name) == 0);
2148
2149 verify(nvlist_lookup_uint64(config,
2150 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2151 verify(nvlist_lookup_uint64(config,
2152 ZPOOL_CONFIG_VERSION, &version) == 0);
2153 if (!SPA_VERSION_IS_SUPPORTED(version)) {
2154 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2155 "is formatted using an unsupported ZFS version\n"), name);
2156 return (1);
2157 } else if (state != POOL_STATE_EXPORTED &&
2158 !(flags & ZFS_IMPORT_ANY_HOST)) {
2159 uint64_t hostid;
2160
2161 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
2162 &hostid) == 0) {
2163 if ((unsigned long)hostid != gethostid()) {
2164 char *hostname;
2165 uint64_t timestamp;
2166 time_t t;
2167
2168 verify(nvlist_lookup_string(config,
2169 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2170 verify(nvlist_lookup_uint64(config,
2171 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0);
2172 t = timestamp;
2173 (void) fprintf(stderr, gettext("cannot import "
2174 "'%s': pool may be in use from other "
2175 "system, it was last accessed by %s "
2176 "(hostid: 0x%lx) on %s"), name, hostname,
2177 (unsigned long)hostid,
2178 asctime(localtime(&t)));
2179 (void) fprintf(stderr, gettext("use '-f' to "
2180 "import anyway\n"));
2181 return (1);
2182 }
2183 } else {
2184 (void) fprintf(stderr, gettext("cannot import '%s': "
2185 "pool may be in use from other system\n"), name);
2186 (void) fprintf(stderr, gettext("use '-f' to import "
2187 "anyway\n"));
2188 return (1);
2189 }
2190 }
2191
2192 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2193 return (1);
2194
2195 if (newname != NULL)
2196 name = (char *)newname;
2197
2198 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2199 return (1);
2200
2201 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2202 !(flags & ZFS_IMPORT_ONLY) &&
2203 zpool_enable_datasets_ex(zhp, mntopts, 0, n_threads) != 0) {
2204 zpool_close(zhp);
2205 return (1);
2206 }
2207
2208 zpool_close(zhp);
2209 return (0);
2210 }
2211
2212 /*
2213 * zpool import [-d dir] [-D]
2214 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2215 * [-d dir | -c cachefile] [-f] -a
2216 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2217 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2218 *
2219 * -c Read pool information from a cachefile instead of searching
2220 * devices.
2221 *
2222 * -d Scan in a specific directory, other than /dev/dsk. More than
2223 * one directory can be specified using multiple '-d' options.
2224 *
2225 * -D Scan for previously destroyed pools or import all or only
2226 * specified destroyed pools.
2227 *
2228 * -R Temporarily import the pool, with all mountpoints relative to
2229 * the given root. The pool will remain exported when the machine
2230 * is rebooted.
2231 *
2232 * -V Import even in the presence of faulted vdevs. This is an
2233 * intentionally undocumented option for testing purposes, and
2234 * treats the pool configuration as complete, leaving any bad
2235 * vdevs in the FAULTED state. In other words, it does verbatim
2236 * import.
2237 *
2238 * -f Force import, even if it appears that the pool is active.
2239 *
2240 * -F Attempt rewind if necessary.
2241 *
2242 * -n See if rewind would work, but don't actually rewind.
2243 *
2244 * -N Import the pool but don't mount datasets.
2245 *
2246 * -t Use up to num threads to mount datasets in parallel.
2247 *
2248 * -T Specify a starting txg to use for import. This option is
2249 * intentionally undocumented option for testing purposes.
2250 *
2251 * -a Import all pools found.
2252 *
2253 * -o Set property=value and/or temporary mount options (without '=').
2254 *
2255 * The import command scans for pools to import, and import pools based on pool
2256 * name and GUID. The pool can also be renamed as part of the import process.
2257 */
2258 int
2259 zpool_do_import(int argc, char **argv)
2260 {
2261 char **searchdirs = NULL;
2262 int nsearch = 0;
2263 int c;
2264 int err = 0;
2265 nvlist_t *pools = NULL;
2266 boolean_t do_all = B_FALSE;
2267 boolean_t do_destroyed = B_FALSE;
2268 char *mntopts = NULL;
2269 nvpair_t *elem;
2270 nvlist_t *config;
2271 uint64_t searchguid = 0;
2272 char *searchname = NULL;
2273 char *propval;
2274 nvlist_t *found_config;
2275 nvlist_t *policy = NULL;
2276 nvlist_t *props = NULL;
2277 boolean_t first;
2278 int flags = ZFS_IMPORT_NORMAL;
2279 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2280 boolean_t dryrun = B_FALSE;
2281 boolean_t do_rewind = B_FALSE;
2282 boolean_t xtreme_rewind = B_FALSE;
2283 uint64_t pool_state, txg = -1ULL;
2284 char *cachefile = NULL;
2285 importargs_t idata = { 0 };
2286 unsigned long n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
2287 char *endptr;
2288
2289 /* check options */
2290 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:t:T:VX")) != -1) {
2291 switch (c) {
2292 case 'a':
2293 do_all = B_TRUE;
2294 break;
2295 case 'c':
2296 cachefile = optarg;
2297 break;
2298 case 'd':
2299 if (searchdirs == NULL) {
2300 searchdirs = safe_malloc(sizeof (char *));
2301 } else {
2302 char **tmp = safe_malloc((nsearch + 1) *
2303 sizeof (char *));
2304 bcopy(searchdirs, tmp, nsearch *
2305 sizeof (char *));
2306 free(searchdirs);
2307 searchdirs = tmp;
2308 }
2309 searchdirs[nsearch++] = optarg;
2310 break;
2311 case 'D':
2312 do_destroyed = B_TRUE;
2313 break;
2314 case 'f':
2315 flags |= ZFS_IMPORT_ANY_HOST;
2316 break;
2317 case 'F':
2318 do_rewind = B_TRUE;
2319 break;
2320 case 'm':
2321 flags |= ZFS_IMPORT_MISSING_LOG;
2322 break;
2323 case 'n':
2324 dryrun = B_TRUE;
2325 break;
2326 case 'N':
2327 flags |= ZFS_IMPORT_ONLY;
2328 break;
2329 case 'o':
2330 if ((propval = strchr(optarg, '=')) != NULL) {
2331 *propval = '\0';
2332 propval++;
2333 if (add_prop_list(optarg, propval,
2334 &props, B_TRUE))
2335 goto error;
2336 } else {
2337 mntopts = optarg;
2338 }
2339 break;
2340 case 'R':
2341 if (add_prop_list(zpool_prop_to_name(
2342 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2343 goto error;
2344 if (nvlist_lookup_string(props,
2345 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2346 &propval) == 0)
2347 break;
2348 if (add_prop_list(zpool_prop_to_name(
2349 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2350 goto error;
2351 break;
2352 case 't':
2353 errno = 0;
2354 n_threads = strtol(optarg, &endptr, 10);
2355 if (errno != 0 || *endptr != '\0') {
2356 (void) fprintf(stderr,
2357 gettext("invalid num value\n"));
2358 usage(B_FALSE);
2359 }
2360 break;
2361 case 'T':
2362 errno = 0;
2363 txg = strtoull(optarg, &endptr, 0);
2364 if (errno != 0 || *endptr != '\0') {
2365 (void) fprintf(stderr,
2366 gettext("invalid txg value\n"));
2367 usage(B_FALSE);
2368 }
2369 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2370 break;
2371 case 'V':
2372 flags |= ZFS_IMPORT_VERBATIM;
2373 break;
2374 case 'X':
2375 xtreme_rewind = B_TRUE;
2376 break;
2377 case ':':
2378 (void) fprintf(stderr, gettext("missing argument for "
2379 "'%c' option\n"), optopt);
2380 usage(B_FALSE);
2381 break;
2382 case '?':
2383 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2384 optopt);
2385 usage(B_FALSE);
2386 }
2387 }
2388
2389 argc -= optind;
2390 argv += optind;
2391
2392 if (cachefile && nsearch != 0) {
2393 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2394 usage(B_FALSE);
2395 }
2396
2397 if ((dryrun || xtreme_rewind) && !do_rewind) {
2398 (void) fprintf(stderr,
2399 gettext("-n or -X only meaningful with -F\n"));
2400 usage(B_FALSE);
2401 }
2402 if (dryrun)
2403 rewind_policy = ZPOOL_TRY_REWIND;
2404 else if (do_rewind)
2405 rewind_policy = ZPOOL_DO_REWIND;
2406 if (xtreme_rewind)
2407 rewind_policy |= ZPOOL_EXTREME_REWIND;
2408
2409 /* In the future, we can capture further policy and include it here */
2410 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2411 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
2412 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2413 goto error;
2414
2415 if (searchdirs == NULL) {
2416 searchdirs = safe_malloc(sizeof (char *));
2417 searchdirs[0] = ZFS_DISK_ROOT;
2418 nsearch = 1;
2419 }
2420
2421 /* check argument count */
2422 if (do_all) {
2423 if (argc != 0) {
2424 (void) fprintf(stderr, gettext("too many arguments\n"));
2425 usage(B_FALSE);
2426 }
2427 } else {
2428 if (argc > 2) {
2429 (void) fprintf(stderr, gettext("too many arguments\n"));
2430 usage(B_FALSE);
2431 }
2432
2433 /*
2434 * Check for the SYS_CONFIG privilege. We do this explicitly
2435 * here because otherwise any attempt to discover pools will
2436 * silently fail.
2437 */
2438 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2439 (void) fprintf(stderr, gettext("cannot "
2440 "discover pools: permission denied\n"));
2441 free(searchdirs);
2442 nvlist_free(policy);
2443 return (1);
2444 }
2445 }
2446
2447 /*
2448 * Depending on the arguments given, we do one of the following:
2449 *
2450 * <none> Iterate through all pools and display information about
2451 * each one.
2452 *
2453 * -a Iterate through all pools and try to import each one.
2454 *
2455 * <id> Find the pool that corresponds to the given GUID/pool
2456 * name and import that one.
2457 *
2458 * -D Above options applies only to destroyed pools.
2459 */
2460 if (argc != 0) {
2461 char *endptr;
2462
2463 errno = 0;
2464 searchguid = strtoull(argv[0], &endptr, 10);
2465 if (errno != 0 || *endptr != '\0') {
2466 searchname = argv[0];
2467 searchguid = 0;
2468 }
2469 found_config = NULL;
2470
2471 /*
2472 * User specified a name or guid. Ensure it's unique.
2473 */
2474 idata.unique = B_TRUE;
2475 }
2476
2477
2478 idata.path = searchdirs;
2479 idata.paths = nsearch;
2480 idata.poolname = searchname;
2481 idata.guid = searchguid;
2482 idata.cachefile = cachefile;
2483
2484 pools = zpool_search_import(g_zfs, &idata);
2485
2486 if (pools != NULL && idata.exists &&
2487 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2488 (void) fprintf(stderr, gettext("cannot import '%s': "
2489 "a pool with that name already exists\n"),
2490 argv[0]);
2491 (void) fprintf(stderr, gettext("use the form '%s "
2492 "<pool | id> <newpool>' to give it a new name\n"),
2493 "zpool import");
2494 err = 1;
2495 } else if (pools == NULL && idata.exists) {
2496 (void) fprintf(stderr, gettext("cannot import '%s': "
2497 "a pool with that name is already created/imported,\n"),
2498 argv[0]);
2499 (void) fprintf(stderr, gettext("and no additional pools "
2500 "with that name were found\n"));
2501 err = 1;
2502 } else if (pools == NULL) {
2503 if (argc != 0) {
2504 (void) fprintf(stderr, gettext("cannot import '%s': "
2505 "no such pool available\n"), argv[0]);
2506 }
2507 err = 1;
2508 }
2509
2510 if (err == 1) {
2511 free(searchdirs);
2512 nvlist_free(policy);
2513 return (1);
2514 }
2515
2516 /*
2517 * At this point we have a list of import candidate configs. Even if
2518 * we were searching by pool name or guid, we still need to
2519 * post-process the list to deal with pool state and possible
2520 * duplicate names.
2521 */
2522 err = 0;
2523 elem = NULL;
2524 first = B_TRUE;
2525 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2526
2527 verify(nvpair_value_nvlist(elem, &config) == 0);
2528
2529 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2530 &pool_state) == 0);
2531 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2532 continue;
2533 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2534 continue;
2535
2536 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2537 policy) == 0);
2538
2539 if (argc == 0) {
2540 if (first)
2541 first = B_FALSE;
2542 else if (!do_all)
2543 (void) printf("\n");
2544
2545 if (do_all) {
2546 err |= do_import(config, NULL, mntopts,
2547 props, flags, n_threads);
2548 } else {
2549 show_import(config);
2550 }
2551 } else if (searchname != NULL) {
2552 char *name;
2553
2554 /*
2555 * We are searching for a pool based on name.
2556 */
2557 verify(nvlist_lookup_string(config,
2558 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2559
2560 if (strcmp(name, searchname) == 0) {
2561 if (found_config != NULL) {
2562 (void) fprintf(stderr, gettext(
2563 "cannot import '%s': more than "
2564 "one matching pool\n"), searchname);
2565 (void) fprintf(stderr, gettext(
2566 "import by numeric ID instead\n"));
2567 err = B_TRUE;
2568 }
2569 found_config = config;
2570 }
2571 } else {
2572 uint64_t guid;
2573
2574 /*
2575 * Search for a pool by guid.
2576 */
2577 verify(nvlist_lookup_uint64(config,
2578 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2579
2580 if (guid == searchguid)
2581 found_config = config;
2582 }
2583 }
2584
2585 /*
2586 * If we were searching for a specific pool, verify that we found a
2587 * pool, and then do the import.
2588 */
2589 if (argc != 0 && err == 0) {
2590 if (found_config == NULL) {
2591 (void) fprintf(stderr, gettext("cannot import '%s': "
2592 "no such pool available\n"), argv[0]);
2593 err = B_TRUE;
2594 } else {
2595 err |= do_import(found_config, argc == 1 ? NULL :
2596 argv[1], mntopts, props, flags, n_threads);
2597 }
2598 }
2599
2600 /*
2601 * If we were just looking for pools, report an error if none were
2602 * found.
2603 */
2604 if (argc == 0 && first)
2605 (void) fprintf(stderr,
2606 gettext("no pools available to import\n"));
2607
2608 error:
2609 nvlist_free(props);
2610 nvlist_free(pools);
2611 nvlist_free(policy);
2612 free(searchdirs);
2613
2614 return (err ? 1 : 0);
2615 }
2616
2617 typedef struct iostat_cbdata {
2618 boolean_t cb_verbose;
2619 int cb_namewidth;
2620 int cb_iteration;
2621 zpool_list_t *cb_list;
2622 } iostat_cbdata_t;
2623
2624 static void
2625 print_iostat_separator(iostat_cbdata_t *cb)
2626 {
2627 int i = 0;
2628
2629 for (i = 0; i < cb->cb_namewidth; i++)
2630 (void) printf("-");
2631 (void) printf(" ----- ----- ----- ----- ----- ----- ----- "
2632 "-----\n");
2633 }
2634
2635 static void
2636 print_iostat_header(iostat_cbdata_t *cb)
2637 {
2638 (void) printf("%*s capacity operations bandwidth "
2639 "latency\n", cb->cb_namewidth, "");
2640 (void) printf("%-*s alloc free read write read write read "
2641 "write\n", cb->cb_namewidth, "pool");
2642 print_iostat_separator(cb);
2643 }
2644
2645 /*
2646 * Display a single statistic.
2647 */
2648 static void
2649 print_one_stat(uint64_t value)
2650 {
2651 char buf[64];
2652
2653 zfs_nicenum(value, buf, sizeof (buf));
2654 (void) printf(" %5s", buf);
2655 }
2656
2657 /*
2658 * Display latency statistic (extra care needed)
2659 */
2660 static void
2661 print_one_latency_stat(uint64_t iotime, uint64_t ops)
2662 {
2663 char buf[64];
2664 double value = 0.0; /* latency in milliseconds */
2665
2666 if (ops != 0) {
2667 value = (double)iotime;
2668 value /= (double)ops;
2669 value /= (double)(MICROSEC / MILLISEC);
2670 }
2671
2672 (void) sprintf(buf, "%.2f", value);
2673 (void) printf(" %5s", buf);
2674 }
2675
2676 /*
2677 * Print out all the statistics for the given vdev. This can either be the
2678 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2679 * is a verbose output, and we don't want to display the toplevel pool stats.
2680 */
2681 void
2682 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2683 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2684 {
2685 nvlist_t **oldchild, **newchild;
2686 uint_t c, children;
2687 vdev_stat_t *oldvs, *newvs;
2688 vdev_stat_t zerovs = { 0 };
2689 uint64_t tdelta;
2690 double scale;
2691 char *vname;
2692
2693 if (oldnv != NULL) {
2694 verify(nvlist_lookup_uint64_array(oldnv,
2695 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2696 } else {
2697 oldvs = &zerovs;
2698 }
2699
2700 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2701 (uint64_t **)&newvs, &c) == 0);
2702
2703 if (strlen(name) + depth > cb->cb_namewidth)
2704 (void) printf("%*s%s", depth, "", name);
2705 else
2706 (void) printf("%*s%s%*s", depth, "", name,
2707 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2708
2709 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2710
2711 if (tdelta == 0)
2712 scale = 1.0;
2713 else
2714 scale = (double)NANOSEC / tdelta;
2715
2716 /* only toplevel vdevs have capacity stats */
2717 if (newvs->vs_space == 0) {
2718 (void) printf(" - -");
2719 } else {
2720 print_one_stat(newvs->vs_alloc);
2721 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2722 }
2723
2724 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2725 oldvs->vs_ops[ZIO_TYPE_READ])));
2726
2727 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2728 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2729
2730 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2731 oldvs->vs_bytes[ZIO_TYPE_READ])));
2732
2733 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2734 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2735
2736 /*
2737 * No scale needed here since we are dividing in
2738 * print_one_latency_stat()
2739 */
2740
2741 print_one_latency_stat(
2742 newvs->vs_iotime[ZIO_TYPE_READ] - oldvs->vs_iotime[ZIO_TYPE_READ],
2743 newvs->vs_ops[ZIO_TYPE_READ] - oldvs->vs_ops[ZIO_TYPE_READ]);
2744
2745 print_one_latency_stat(
2746 newvs->vs_iotime[ZIO_TYPE_WRITE] - oldvs->vs_iotime[ZIO_TYPE_WRITE],
2747 newvs->vs_ops[ZIO_TYPE_WRITE] - oldvs->vs_ops[ZIO_TYPE_WRITE]);
2748
2749 (void) printf("\n");
2750
2751 if (!cb->cb_verbose)
2752 return;
2753
2754 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2755 &newchild, &children) != 0)
2756 return;
2757
2758 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2759 &oldchild, &c) != 0)
2760 return;
2761
2762 for (c = 0; c < children; c++) {
2763 uint64_t ishole = B_FALSE, islog = B_FALSE, isspec = B_FALSE;
2764
2765 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2766 &ishole);
2767
2768 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2769 &islog);
2770
2771 (void) nvlist_lookup_uint64(newchild[c],
2772 ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2773
2774 if (ishole || islog || isspec)
2775 continue;
2776
2777 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2778 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2779 newchild[c], cb, depth + 2);
2780 free(vname);
2781 }
2782
2783 /*
2784 * Log device section
2785 */
2786
2787 if (num_logs(newnv) > 0) {
2788 (void) printf("%-*s - - - - - "
2789 "-\n", cb->cb_namewidth, "logs");
2790
2791 for (c = 0; c < children; c++) {
2792 uint64_t islog = B_FALSE;
2793 (void) nvlist_lookup_uint64(newchild[c],
2794 ZPOOL_CONFIG_IS_LOG, &islog);
2795
2796 if (islog) {
2797 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2798 B_FALSE);
2799 print_vdev_stats(zhp, vname, oldnv ?
2800 oldchild[c] : NULL, newchild[c],
2801 cb, depth + 2);
2802 free(vname);
2803 }
2804 }
2805 }
2806
2807 /*
2808 * Special device section
2809 */
2810
2811 if (num_special(newnv) > 0) {
2812 (void) printf("%-*s - - - - - "
2813 "-\n", cb->cb_namewidth, "special");
2814
2815 for (c = 0; c < children; c++) {
2816 uint64_t isspec = B_FALSE;
2817 (void) nvlist_lookup_uint64(newchild[c],
2818 ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2819
2820 if (isspec) {
2821 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2822 B_FALSE);
2823 print_vdev_stats(zhp, vname, oldnv ?
2824 oldchild[c] : NULL, newchild[c],
2825 cb, depth + 2);
2826 free(vname);
2827 }
2828 }
2829 }
2830
2831 /*
2832 * Include level 2 ARC devices in iostat output
2833 */
2834 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2835 &newchild, &children) != 0)
2836 return;
2837
2838 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2839 &oldchild, &c) != 0)
2840 return;
2841
2842 if (children > 0) {
2843 (void) printf("%-*s - - - - - "
2844 "-\n", cb->cb_namewidth, "cache");
2845 for (c = 0; c < children; c++) {
2846 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2847 B_FALSE);
2848 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2849 newchild[c], cb, depth + 2);
2850 free(vname);
2851 }
2852 }
2853 }
2854
2855 static int
2856 refresh_iostat(zpool_handle_t *zhp, void *data)
2857 {
2858 iostat_cbdata_t *cb = data;
2859 boolean_t missing;
2860
2861 /*
2862 * If the pool has disappeared, remove it from the list and continue.
2863 */
2864 if (zpool_refresh_stats(zhp, &missing) != 0)
2865 return (-1);
2866
2867 if (missing)
2868 pool_list_remove(cb->cb_list, zhp);
2869
2870 return (0);
2871 }
2872
2873 /*
2874 * Callback to print out the iostats for the given pool.
2875 */
2876 int
2877 print_iostat(zpool_handle_t *zhp, void *data)
2878 {
2879 iostat_cbdata_t *cb = data;
2880 nvlist_t *oldconfig, *newconfig;
2881 nvlist_t *oldnvroot, *newnvroot;
2882
2883 newconfig = zpool_get_config(zhp, &oldconfig);
2884
2885 if (cb->cb_iteration == 1)
2886 oldconfig = NULL;
2887
2888 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2889 &newnvroot) == 0);
2890
2891 if (oldconfig == NULL)
2892 oldnvroot = NULL;
2893 else
2894 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2895 &oldnvroot) == 0);
2896
2897 /*
2898 * Print out the statistics for the pool.
2899 */
2900 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2901
2902 if (cb->cb_verbose)
2903 print_iostat_separator(cb);
2904
2905 return (0);
2906 }
2907
2908 int
2909 get_namewidth(zpool_handle_t *zhp, void *data)
2910 {
2911 iostat_cbdata_t *cb = data;
2912 nvlist_t *config, *nvroot;
2913
2914 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2915 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2916 &nvroot) == 0);
2917 if (!cb->cb_verbose)
2918 cb->cb_namewidth = strlen(zpool_get_name(zhp));
2919 else
2920 cb->cb_namewidth = max_width(zhp, nvroot, 0,
2921 cb->cb_namewidth);
2922 }
2923
2924 /*
2925 * The width must fall into the range [10,38]. The upper limit is the
2926 * maximum we can have and still fit in 80 columns.
2927 */
2928 if (cb->cb_namewidth < 10)
2929 cb->cb_namewidth = 10;
2930 if (cb->cb_namewidth > 38)
2931 cb->cb_namewidth = 38;
2932
2933 return (0);
2934 }
2935
2936 /*
2937 * Parse the input string, get the 'interval' and 'count' value if there is one.
2938 */
2939 static void
2940 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2941 unsigned long *cnt)
2942 {
2943 unsigned long interval = 0, count = 0;
2944 int argc = *argcp, errno;
2945
2946 /*
2947 * Determine if the last argument is an integer or a pool name
2948 */
2949 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2950 char *end;
2951
2952 errno = 0;
2953 interval = strtoul(argv[argc - 1], &end, 10);
2954
2955 if (*end == '\0' && errno == 0) {
2956 if (interval == 0) {
2957 (void) fprintf(stderr, gettext("interval "
2958 "cannot be zero\n"));
2959 usage(B_FALSE);
2960 }
2961 /*
2962 * Ignore the last parameter
2963 */
2964 argc--;
2965 } else {
2966 /*
2967 * If this is not a valid number, just plow on. The
2968 * user will get a more informative error message later
2969 * on.
2970 */
2971 interval = 0;
2972 }
2973 }
2974
2975 /*
2976 * If the last argument is also an integer, then we have both a count
2977 * and an interval.
2978 */
2979 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2980 char *end;
2981
2982 errno = 0;
2983 count = interval;
2984 interval = strtoul(argv[argc - 1], &end, 10);
2985
2986 if (*end == '\0' && errno == 0) {
2987 if (interval == 0) {
2988 (void) fprintf(stderr, gettext("interval "
2989 "cannot be zero\n"));
2990 usage(B_FALSE);
2991 }
2992
2993 /*
2994 * Ignore the last parameter
2995 */
2996 argc--;
2997 } else {
2998 interval = 0;
2999 }
3000 }
3001
3002 *iv = interval;
3003 *cnt = count;
3004 *argcp = argc;
3005 }
3006
3007 static void
3008 get_timestamp_arg(char c)
3009 {
3010 if (c == 'u')
3011 timestamp_fmt = UDATE;
3012 else if (c == 'd')
3013 timestamp_fmt = DDATE;
3014 else
3015 usage(B_FALSE);
3016 }
3017
3018 /*
3019 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
3020 *
3021 * -v Display statistics for individual vdevs
3022 * -T Display a timestamp in date(1) or Unix format
3023 *
3024 * This command can be tricky because we want to be able to deal with pool
3025 * creation/destruction as well as vdev configuration changes. The bulk of this
3026 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
3027 * on pool_list_update() to detect the addition of new pools. Configuration
3028 * changes are all handled within libzfs.
3029 */
3030 int
3031 zpool_do_iostat(int argc, char **argv)
3032 {
3033 int c;
3034 int ret;
3035 int npools;
3036 unsigned long interval = 0, count = 0;
3037 zpool_list_t *list;
3038 boolean_t verbose = B_FALSE;
3039 iostat_cbdata_t cb;
3040
3041 /* check options */
3042 while ((c = getopt(argc, argv, "T:v")) != -1) {
3043 switch (c) {
3044 case 'T':
3045 get_timestamp_arg(*optarg);
3046 break;
3047 case 'v':
3048 verbose = B_TRUE;
3049 break;
3050 case '?':
3051 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3052 optopt);
3053 usage(B_FALSE);
3054 }
3055 }
3056
3057 argc -= optind;
3058 argv += optind;
3059
3060 get_interval_count(&argc, argv, &interval, &count);
3061
3062 /*
3063 * Construct the list of all interesting pools.
3064 */
3065 ret = 0;
3066 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
3067 return (1);
3068
3069 if (pool_list_count(list) == 0 && argc != 0) {
3070 pool_list_free(list);
3071 return (1);
3072 }
3073
3074 if (pool_list_count(list) == 0 && interval == 0) {
3075 pool_list_free(list);
3076 (void) fprintf(stderr, gettext("no pools available\n"));
3077 return (1);
3078 }
3079
3080 /*
3081 * Enter the main iostat loop.
3082 */
3083 cb.cb_list = list;
3084 cb.cb_verbose = verbose;
3085 cb.cb_iteration = 0;
3086 cb.cb_namewidth = 0;
3087
3088 for (;;) {
3089 pool_list_update(list);
3090
3091 if ((npools = pool_list_count(list)) == 0)
3092 break;
3093
3094 /*
3095 * Refresh all statistics. This is done as an explicit step
3096 * before calculating the maximum name width, so that any
3097 * configuration changes are properly accounted for.
3098 */
3099 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
3100
3101 /*
3102 * Iterate over all pools to determine the maximum width
3103 * for the pool / device name column across all pools.
3104 */
3105 cb.cb_namewidth = 0;
3106 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3107
3108 if (timestamp_fmt != NODATE)
3109 print_timestamp(timestamp_fmt);
3110
3111 /*
3112 * If it's the first time, or verbose mode, print the header.
3113 */
3114 if (++cb.cb_iteration == 1 || verbose)
3115 print_iostat_header(&cb);
3116
3117 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
3118
3119 /*
3120 * If there's more than one pool, and we're not in verbose mode
3121 * (which prints a separator for us), then print a separator.
3122 */
3123 if (npools > 1 && !verbose)
3124 print_iostat_separator(&cb);
3125
3126 if (verbose)
3127 (void) printf("\n");
3128
3129 /*
3130 * Flush the output so that redirection to a file isn't buffered
3131 * indefinitely.
3132 */
3133 (void) fflush(stdout);
3134
3135 if (interval == 0)
3136 break;
3137
3138 if (count != 0 && --count == 0)
3139 break;
3140
3141 (void) sleep(interval);
3142 }
3143
3144 pool_list_free(list);
3145
3146 return (ret);
3147 }
3148
3149 typedef struct list_cbdata {
3150 boolean_t cb_verbose;
3151 int cb_namewidth;
3152 boolean_t cb_scripted;
3153 zprop_list_t *cb_proplist;
3154 boolean_t cb_literal;
3155 } list_cbdata_t;
3156
3157 /*
3158 * Given a list of columns to display, output appropriate headers for each one.
3159 */
3160 static void
3161 print_header(list_cbdata_t *cb)
3162 {
3163 zprop_list_t *pl = cb->cb_proplist;
3164 char headerbuf[ZPOOL_MAXPROPLEN];
3165 const char *header;
3166 boolean_t first = B_TRUE;
3167 boolean_t right_justify;
3168 size_t width = 0;
3169
3170 for (; pl != NULL; pl = pl->pl_next) {
3171 width = pl->pl_width;
3172 if (first && cb->cb_verbose) {
3173 /*
3174 * Reset the width to accommodate the verbose listing
3175 * of devices.
3176 */
3177 width = cb->cb_namewidth;
3178 }
3179
3180 if (!first)
3181 (void) printf(" ");
3182 else
3183 first = B_FALSE;
3184
3185 right_justify = B_FALSE;
3186 if (pl->pl_prop != ZPROP_INVAL) {
3187 header = zpool_prop_column_name(pl->pl_prop);
3188 right_justify = zpool_prop_align_right(pl->pl_prop);
3189 } else {
3190 int i;
3191
3192 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3193 headerbuf[i] = toupper(pl->pl_user_prop[i]);
3194 headerbuf[i] = '\0';
3195 header = headerbuf;
3196 }
3197
3198 if (pl->pl_next == NULL && !right_justify)
3199 (void) printf("%s", header);
3200 else if (right_justify)
3201 (void) printf("%*s", width, header);
3202 else
3203 (void) printf("%-*s", width, header);
3204
3205 }
3206
3207 (void) printf("\n");
3208 }
3209
3210 /*
3211 * Given a pool and a list of properties, print out all the properties according
3212 * to the described layout.
3213 */
3214 static void
3215 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3216 {
3217 zprop_list_t *pl = cb->cb_proplist;
3218 boolean_t first = B_TRUE;
3219 char property[ZPOOL_MAXPROPLEN];
3220 char *propstr;
3221 boolean_t right_justify;
3222 size_t width;
3223
3224 for (; pl != NULL; pl = pl->pl_next) {
3225
3226 width = pl->pl_width;
3227 if (first && cb->cb_verbose) {
3228 /*
3229 * Reset the width to accommodate the verbose listing
3230 * of devices.
3231 */
3232 width = cb->cb_namewidth;
3233 }
3234
3235 if (!first) {
3236 if (cb->cb_scripted)
3237 (void) printf("\t");
3238 else
3239 (void) printf(" ");
3240 } else {
3241 first = B_FALSE;
3242 }
3243
3244 right_justify = B_FALSE;
3245 if (pl->pl_prop != ZPROP_INVAL) {
3246 if (zpool_get_prop(zhp, pl->pl_prop, property,
3247 sizeof (property), NULL, cb->cb_literal) != 0)
3248 propstr = "-";
3249 else
3250 propstr = property;
3251
3252 right_justify = zpool_prop_align_right(pl->pl_prop);
3253 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
3254 zpool_prop_unsupported(pl->pl_user_prop)) &&
3255 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3256 sizeof (property)) == 0) {
3257 propstr = property;
3258 } else {
3259 propstr = "-";
3260 }
3261
3262
3263 /*
3264 * If this is being called in scripted mode, or if this is the
3265 * last column and it is left-justified, don't include a width
3266 * format specifier.
3267 */
3268 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3269 (void) printf("%s", propstr);
3270 else if (right_justify)
3271 (void) printf("%*s", width, propstr);
3272 else
3273 (void) printf("%-*s", width, propstr);
3274 }
3275
3276 (void) printf("\n");
3277 }
3278
3279 static void
3280 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3281 boolean_t valid)
3282 {
3283 char propval[64];
3284 boolean_t fixed;
3285 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3286
3287 switch (prop) {
3288 case ZPOOL_PROP_EXPANDSZ:
3289 if (value == 0)
3290 (void) strlcpy(propval, "-", sizeof (propval));
3291 else
3292 zfs_nicenum(value, propval, sizeof (propval));
3293 break;
3294 case ZPOOL_PROP_FRAGMENTATION:
3295 if (value == ZFS_FRAG_INVALID) {
3296 (void) strlcpy(propval, "-", sizeof (propval));
3297 } else {
3298 (void) snprintf(propval, sizeof (propval), "%llu%%",
3299 value);
3300 }
3301 break;
3302 case ZPOOL_PROP_CAPACITY:
3303 (void) snprintf(propval, sizeof (propval), "%llu%%", value);
3304 break;
3305 default:
3306 zfs_nicenum(value, propval, sizeof (propval));
3307 }
3308
3309 if (!valid)
3310 (void) strlcpy(propval, "-", sizeof (propval));
3311
3312 if (scripted)
3313 (void) printf("\t%s", propval);
3314 else
3315 (void) printf(" %*s", width, propval);
3316 }
3317
3318 void
3319 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3320 list_cbdata_t *cb, int depth)
3321 {
3322 nvlist_t **child;
3323 vdev_stat_t *vs;
3324 uint_t c, children;
3325 char *vname;
3326 boolean_t scripted = cb->cb_scripted;
3327 uint64_t islog = B_FALSE;
3328 boolean_t haslog = B_FALSE;
3329 char *dashes = "%-*s - - - - - -\n";
3330
3331 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3332 (uint64_t **)&vs, &c) == 0);
3333
3334 if (name != NULL) {
3335 boolean_t toplevel = (vs->vs_space != 0);
3336 uint64_t cap;
3337
3338 if (scripted)
3339 (void) printf("\t%s", name);
3340 else if (strlen(name) + depth > cb->cb_namewidth)
3341 (void) printf("%*s%s", depth, "", name);
3342 else
3343 (void) printf("%*s%s%*s", depth, "", name,
3344 (int)(cb->cb_namewidth - strlen(name) - depth), "");
3345
3346 /*
3347 * Print the properties for the individual vdevs. Some
3348 * properties are only applicable to toplevel vdevs. The
3349 * 'toplevel' boolean value is passed to the print_one_column()
3350 * to indicate that the value is valid.
3351 */
3352 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3353 toplevel);
3354 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3355 toplevel);
3356 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3357 scripted, toplevel);
3358 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3359 B_TRUE);
3360 print_one_column(ZPOOL_PROP_FRAGMENTATION,
3361 vs->vs_fragmentation, scripted,
3362 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3363 cap = (vs->vs_space == 0) ? 0 :
3364 (vs->vs_alloc * 100 / vs->vs_space);
3365 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3366 (void) printf("\n");
3367 }
3368
3369 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3370 &child, &children) != 0)
3371 return;
3372
3373 for (c = 0; c < children; c++) {
3374 uint64_t ishole = B_FALSE;
3375
3376 if (nvlist_lookup_uint64(child[c],
3377 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3378 continue;
3379
3380 if (nvlist_lookup_uint64(child[c],
3381 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3382 haslog = B_TRUE;
3383 continue;
3384 }
3385
3386 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3387 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3388 free(vname);
3389 }
3390
3391 if (haslog == B_TRUE) {
3392 /* LINTED E_SEC_PRINTF_VAR_FMT */
3393 (void) printf(dashes, cb->cb_namewidth, "log");
3394 for (c = 0; c < children; c++) {
3395 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3396 &islog) != 0 || !islog)
3397 continue;
3398 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3399 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3400 free(vname);
3401 }
3402 }
3403
3404 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3405 &child, &children) == 0 && children > 0) {
3406 /* LINTED E_SEC_PRINTF_VAR_FMT */
3407 (void) printf(dashes, cb->cb_namewidth, "cache");
3408 for (c = 0; c < children; c++) {
3409 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3410 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3411 free(vname);
3412 }
3413 }
3414
3415 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3416 &children) == 0 && children > 0) {
3417 /* LINTED E_SEC_PRINTF_VAR_FMT */
3418 (void) printf(dashes, cb->cb_namewidth, "spare");
3419 for (c = 0; c < children; c++) {
3420 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3421 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3422 free(vname);
3423 }
3424 }
3425 }
3426
3427
3428 /*
3429 * Generic callback function to list a pool.
3430 */
3431 int
3432 list_callback(zpool_handle_t *zhp, void *data)
3433 {
3434 list_cbdata_t *cbp = data;
3435 nvlist_t *config;
3436 nvlist_t *nvroot;
3437
3438 config = zpool_get_config(zhp, NULL);
3439
3440 print_pool(zhp, cbp);
3441 if (!cbp->cb_verbose)
3442 return (0);
3443
3444 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3445 &nvroot) == 0);
3446 print_list_stats(zhp, NULL, nvroot, cbp, 0);
3447
3448 return (0);
3449 }
3450
3451 /*
3452 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3453 *
3454 * -H Scripted mode. Don't display headers, and separate properties
3455 * by a single tab.
3456 * -o List of properties to display. Defaults to
3457 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
3458 * "dedupratio,health,altroot"
3459 * -p Diplay values in parsable (exact) format.
3460 * -T Display a timestamp in date(1) or Unix format
3461 *
3462 * List all pools in the system, whether or not they're healthy. Output space
3463 * statistics for each one, as well as health status summary.
3464 */
3465 int
3466 zpool_do_list(int argc, char **argv)
3467 {
3468 int c;
3469 int ret = 0;
3470 list_cbdata_t cb = { 0 };
3471 static char default_props[] =
3472 "name,size,allocated,free,expandsize,fragmentation,capacity,"
3473 "dedupratio,health,altroot";
3474 char *props = default_props;
3475 unsigned long interval = 0, count = 0;
3476 zpool_list_t *list;
3477 boolean_t first = B_TRUE;
3478
3479 /* check options */
3480 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3481 switch (c) {
3482 case 'H':
3483 cb.cb_scripted = B_TRUE;
3484 break;
3485 case 'o':
3486 props = optarg;
3487 break;
3488 case 'p':
3489 cb.cb_literal = B_TRUE;
3490 break;
3491 case 'T':
3492 get_timestamp_arg(*optarg);
3493 break;
3494 case 'v':
3495 cb.cb_verbose = B_TRUE;
3496 break;
3497 case ':':
3498 (void) fprintf(stderr, gettext("missing argument for "
3499 "'%c' option\n"), optopt);
3500 usage(B_FALSE);
3501 break;
3502 case '?':
3503 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3504 optopt);
3505 usage(B_FALSE);
3506 }
3507 }
3508
3509 argc -= optind;
3510 argv += optind;
3511
3512 get_interval_count(&argc, argv, &interval, &count);
3513
3514 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3515 usage(B_FALSE);
3516
3517 for (;;) {
3518 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3519 &ret)) == NULL)
3520 return (1);
3521
3522 if (pool_list_count(list) == 0)
3523 break;
3524
3525 cb.cb_namewidth = 0;
3526 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3527
3528 if (timestamp_fmt != NODATE)
3529 print_timestamp(timestamp_fmt);
3530
3531 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3532 print_header(&cb);
3533 first = B_FALSE;
3534 }
3535 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3536
3537 if (interval == 0)
3538 break;
3539
3540 if (count != 0 && --count == 0)
3541 break;
3542
3543 pool_list_free(list);
3544 (void) sleep(interval);
3545 }
3546
3547 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3548 (void) printf(gettext("no pools available\n"));
3549 ret = 0;
3550 }
3551
3552 pool_list_free(list);
3553 zprop_free_list(cb.cb_proplist);
3554 return (ret);
3555 }
3556
3557 static int
3558 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3559 {
3560 boolean_t force = B_FALSE;
3561 int c;
3562 nvlist_t *nvroot;
3563 char *poolname, *old_disk, *new_disk;
3564 zpool_handle_t *zhp;
3565 zpool_boot_label_t boot_type;
3566 uint64_t boot_size;
3567 int ret;
3568
3569 /* check options */
3570 while ((c = getopt(argc, argv, "f")) != -1) {
3571 switch (c) {
3572 case 'f':
3573 force = B_TRUE;
3574 break;
3575 case '?':
3576 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3577 optopt);
3578 usage(B_FALSE);
3579 }
3580 }
3581
3582 argc -= optind;
3583 argv += optind;
3584
3585 /* get pool name and check number of arguments */
3586 if (argc < 1) {
3587 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3588 usage(B_FALSE);
3589 }
3590
3591 poolname = argv[0];
3592
3593 if (argc < 2) {
3594 (void) fprintf(stderr,
3595 gettext("missing <device> specification\n"));
3596 usage(B_FALSE);
3597 }
3598
3599 old_disk = argv[1];
3600
3601 if (argc < 3) {
3602 if (!replacing) {
3603 (void) fprintf(stderr,
3604 gettext("missing <new_device> specification\n"));
3605 usage(B_FALSE);
3606 }
3607 new_disk = old_disk;
3608 argc -= 1;
3609 argv += 1;
3610 } else {
3611 new_disk = argv[2];
3612 argc -= 2;
3613 argv += 2;
3614 }
3615
3616 if (argc > 1) {
3617 (void) fprintf(stderr, gettext("too many arguments\n"));
3618 usage(B_FALSE);
3619 }
3620
3621 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3622 return (1);
3623
3624 if (zpool_get_config(zhp, NULL) == NULL) {
3625 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3626 poolname);
3627 zpool_close(zhp);
3628 return (1);
3629 }
3630
3631 if (zpool_is_bootable(zhp))
3632 boot_type = ZPOOL_COPY_BOOT_LABEL;
3633 else
3634 boot_type = ZPOOL_NO_BOOT_LABEL;
3635
3636 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3637 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3638 boot_type, boot_size, argc, argv);
3639 if (nvroot == NULL) {
3640 zpool_close(zhp);
3641 return (1);
3642 }
3643
3644 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3645
3646 nvlist_free(nvroot);
3647 zpool_close(zhp);
3648
3649 return (ret);
3650 }
3651
3652 /*
3653 * zpool replace [-f] <pool> <device> <new_device>
3654 *
3655 * -f Force attach, even if <new_device> appears to be in use.
3656 *
3657 * Replace <device> with <new_device>.
3658 */
3659 /* ARGSUSED */
3660 int
3661 zpool_do_replace(int argc, char **argv)
3662 {
3663 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3664 }
3665
3666 /*
3667 * zpool attach [-f] <pool> <device> <new_device>
3668 *
3669 * -f Force attach, even if <new_device> appears to be in use.
3670 *
3671 * Attach <new_device> to the mirror containing <device>. If <device> is not
3672 * part of a mirror, then <device> will be transformed into a mirror of
3673 * <device> and <new_device>. In either case, <new_device> will begin life
3674 * with a DTL of [0, now], and will immediately begin to resilver itself.
3675 */
3676 int
3677 zpool_do_attach(int argc, char **argv)
3678 {
3679 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3680 }
3681
3682 /*
3683 * zpool detach [-f] <pool> <device>
3684 *
3685 * -f Force detach of <device>, even if DTLs argue against it
3686 * (not supported yet)
3687 *
3688 * Detach a device from a mirror. The operation will be refused if <device>
3689 * is the last device in the mirror, or if the DTLs indicate that this device
3690 * has the only valid copy of some data.
3691 */
3692 /* ARGSUSED */
3693 int
3694 zpool_do_detach(int argc, char **argv)
3695 {
3696 int c;
3697 char *poolname, *path;
3698 zpool_handle_t *zhp;
3699 int ret;
3700
3701 /* check options */
3702 while ((c = getopt(argc, argv, "f")) != -1) {
3703 switch (c) {
3704 case 'f':
3705 case '?':
3706 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3707 optopt);
3708 usage(B_FALSE);
3709 }
3710 }
3711
3712 argc -= optind;
3713 argv += optind;
3714
3715 /* get pool name and check number of arguments */
3716 if (argc < 1) {
3717 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3718 usage(B_FALSE);
3719 }
3720
3721 if (argc < 2) {
3722 (void) fprintf(stderr,
3723 gettext("missing <device> specification\n"));
3724 usage(B_FALSE);
3725 }
3726
3727 poolname = argv[0];
3728 path = argv[1];
3729
3730 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3731 return (1);
3732
3733 ret = zpool_vdev_detach(zhp, path);
3734
3735 zpool_close(zhp);
3736
3737 return (ret);
3738 }
3739
3740 /*
3741 * zpool split [-n] [-o prop=val] ...
3742 * [-o mntopt] ...
3743 * [-R altroot] <pool> <newpool> [<device> ...]
3744 *
3745 * -n Do not split the pool, but display the resulting layout if
3746 * it were to be split.
3747 * -o Set property=value, or set mount options.
3748 * -R Mount the split-off pool under an alternate root.
3749 *
3750 * Splits the named pool and gives it the new pool name. Devices to be split
3751 * off may be listed, provided that no more than one device is specified
3752 * per top-level vdev mirror. The newly split pool is left in an exported
3753 * state unless -R is specified.
3754 *
3755 * Restrictions: the top-level of the pool pool must only be made up of
3756 * mirrors; all devices in the pool must be healthy; no device may be
3757 * undergoing a resilvering operation.
3758 */
3759 int
3760 zpool_do_split(int argc, char **argv)
3761 {
3762 char *srcpool, *newpool, *propval;
3763 char *mntopts = NULL;
3764 splitflags_t flags;
3765 int c, ret = 0;
3766 zpool_handle_t *zhp;
3767 nvlist_t *config, *props = NULL;
3768
3769 flags.dryrun = B_FALSE;
3770 flags.import = B_FALSE;
3771
3772 /* check options */
3773 while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3774 switch (c) {
3775 case 'R':
3776 flags.import = B_TRUE;
3777 if (add_prop_list(
3778 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3779 &props, B_TRUE) != 0) {
3780 nvlist_free(props);
3781 usage(B_FALSE);
3782 }
3783 break;
3784 case 'n':
3785 flags.dryrun = B_TRUE;
3786 break;
3787 case 'o':
3788 if ((propval = strchr(optarg, '=')) != NULL) {
3789 *propval = '\0';
3790 propval++;
3791 if (add_prop_list(optarg, propval,
3792 &props, B_TRUE) != 0) {
3793 nvlist_free(props);
3794 usage(B_FALSE);
3795 }
3796 } else {
3797 mntopts = optarg;
3798 }
3799 break;
3800 case ':':
3801 (void) fprintf(stderr, gettext("missing argument for "
3802 "'%c' option\n"), optopt);
3803 usage(B_FALSE);
3804 break;
3805 case '?':
3806 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3807 optopt);
3808 usage(B_FALSE);
3809 break;
3810 }
3811 }
3812
3813 if (!flags.import && mntopts != NULL) {
3814 (void) fprintf(stderr, gettext("setting mntopts is only "
3815 "valid when importing the pool\n"));
3816 usage(B_FALSE);
3817 }
3818
3819 argc -= optind;
3820 argv += optind;
3821
3822 if (argc < 1) {
3823 (void) fprintf(stderr, gettext("Missing pool name\n"));
3824 usage(B_FALSE);
3825 }
3826 if (argc < 2) {
3827 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3828 usage(B_FALSE);
3829 }
3830
3831 srcpool = argv[0];
3832 newpool = argv[1];
3833
3834 argc -= 2;
3835 argv += 2;
3836
3837 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3838 return (1);
3839
3840 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3841 if (config == NULL) {
3842 ret = 1;
3843 } else {
3844 if (flags.dryrun) {
3845 (void) printf(gettext("would create '%s' with the "
3846 "following layout:\n\n"), newpool);
3847 print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3848 }
3849 nvlist_free(config);
3850 }
3851
3852 zpool_close(zhp);
3853
3854 if (ret != 0 || flags.dryrun || !flags.import)
3855 return (ret);
3856
3857 /*
3858 * The split was successful. Now we need to open the new
3859 * pool and import it.
3860 */
3861 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3862 return (1);
3863 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3864 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3865 ret = 1;
3866 (void) fprintf(stderr, gettext("Split was successful, but "
3867 "the datasets could not all be mounted\n"));
3868 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3869 "different altroot\n"), "zpool import");
3870 }
3871 zpool_close(zhp);
3872
3873 return (ret);
3874 }
3875
3876
3877
3878 /*
3879 * zpool online <pool> <device> ...
3880 */
3881 int
3882 zpool_do_online(int argc, char **argv)
3883 {
3884 int c, i;
3885 char *poolname;
3886 zpool_handle_t *zhp;
3887 int ret = 0;
3888 vdev_state_t newstate;
3889 int flags = 0;
3890
3891 /* check options */
3892 while ((c = getopt(argc, argv, "et")) != -1) {
3893 switch (c) {
3894 case 'e':
3895 flags |= ZFS_ONLINE_EXPAND;
3896 break;
3897 case 't':
3898 case '?':
3899 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3900 optopt);
3901 usage(B_FALSE);
3902 }
3903 }
3904
3905 argc -= optind;
3906 argv += optind;
3907
3908 /* get pool name and check number of arguments */
3909 if (argc < 1) {
3910 (void) fprintf(stderr, gettext("missing pool name\n"));
3911 usage(B_FALSE);
3912 }
3913 if (argc < 2) {
3914 (void) fprintf(stderr, gettext("missing device name\n"));
3915 usage(B_FALSE);
3916 }
3917
3918 poolname = argv[0];
3919
3920 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3921 return (1);
3922
3923 for (i = 1; i < argc; i++) {
3924 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3925 if (newstate != VDEV_STATE_HEALTHY) {
3926 (void) printf(gettext("warning: device '%s' "
3927 "onlined, but remains in faulted state\n"),
3928 argv[i]);
3929 if (newstate == VDEV_STATE_FAULTED)
3930 (void) printf(gettext("use 'zpool "
3931 "clear' to restore a faulted "
3932 "device\n"));
3933 else
3934 (void) printf(gettext("use 'zpool "
3935 "replace' to replace devices "
3936 "that are no longer present\n"));
3937 }
3938 } else {
3939 ret = 1;
3940 }
3941 }
3942
3943 zpool_close(zhp);
3944
3945 return (ret);
3946 }
3947
3948 /*
3949 * zpool offline [-ft] <pool> <device> ...
3950 *
3951 * -f Force the device into the offline state, even if doing
3952 * so would appear to compromise pool availability.
3953 * (not supported yet)
3954 *
3955 * -t Only take the device off-line temporarily. The offline
3956 * state will not be persistent across reboots.
3957 */
3958 /* ARGSUSED */
3959 int
3960 zpool_do_offline(int argc, char **argv)
3961 {
3962 int c, i;
3963 char *poolname;
3964 zpool_handle_t *zhp;
3965 int ret = 0;
3966 boolean_t istmp = B_FALSE;
3967
3968 /* check options */
3969 while ((c = getopt(argc, argv, "ft")) != -1) {
3970 switch (c) {
3971 case 't':
3972 istmp = B_TRUE;
3973 break;
3974 case 'f':
3975 case '?':
3976 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3977 optopt);
3978 usage(B_FALSE);
3979 }
3980 }
3981
3982 argc -= optind;
3983 argv += optind;
3984
3985 /* get pool name and check number of arguments */
3986 if (argc < 1) {
3987 (void) fprintf(stderr, gettext("missing pool name\n"));
3988 usage(B_FALSE);
3989 }
3990 if (argc < 2) {
3991 (void) fprintf(stderr, gettext("missing device name\n"));
3992 usage(B_FALSE);
3993 }
3994
3995 poolname = argv[0];
3996
3997 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3998 return (1);
3999
4000 for (i = 1; i < argc; i++) {
4001 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
4002 ret = 1;
4003 }
4004
4005 zpool_close(zhp);
4006
4007 return (ret);
4008 }
4009
4010 /*
4011 * zpool clear <pool> [device]
4012 *
4013 * Clear all errors associated with a pool or a particular device.
4014 */
4015 int
4016 zpool_do_clear(int argc, char **argv)
4017 {
4018 int c;
4019 int ret = 0;
4020 boolean_t dryrun = B_FALSE;
4021 boolean_t do_rewind = B_FALSE;
4022 boolean_t xtreme_rewind = B_FALSE;
4023 uint32_t rewind_policy = ZPOOL_NO_REWIND;
4024 nvlist_t *policy = NULL;
4025 zpool_handle_t *zhp;
4026 char *pool, *device;
4027
4028 /* check options */
4029 while ((c = getopt(argc, argv, "FnX")) != -1) {
4030 switch (c) {
4031 case 'F':
4032 do_rewind = B_TRUE;
4033 break;
4034 case 'n':
4035 dryrun = B_TRUE;
4036 break;
4037 case 'X':
4038 xtreme_rewind = B_TRUE;
4039 break;
4040 case '?':
4041 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4042 optopt);
4043 usage(B_FALSE);
4044 }
4045 }
4046
4047 argc -= optind;
4048 argv += optind;
4049
4050 if (argc < 1) {
4051 (void) fprintf(stderr, gettext("missing pool name\n"));
4052 usage(B_FALSE);
4053 }
4054
4055 if (argc > 2) {
4056 (void) fprintf(stderr, gettext("too many arguments\n"));
4057 usage(B_FALSE);
4058 }
4059
4060 if ((dryrun || xtreme_rewind) && !do_rewind) {
4061 (void) fprintf(stderr,
4062 gettext("-n or -X only meaningful with -F\n"));
4063 usage(B_FALSE);
4064 }
4065 if (dryrun)
4066 rewind_policy = ZPOOL_TRY_REWIND;
4067 else if (do_rewind)
4068 rewind_policy = ZPOOL_DO_REWIND;
4069 if (xtreme_rewind)
4070 rewind_policy |= ZPOOL_EXTREME_REWIND;
4071
4072 /* In future, further rewind policy choices can be passed along here */
4073 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
4074 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
4075 return (1);
4076
4077 pool = argv[0];
4078 device = argc == 2 ? argv[1] : NULL;
4079
4080 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
4081 nvlist_free(policy);
4082 return (1);
4083 }
4084
4085 if (zpool_clear(zhp, device, policy) != 0)
4086 ret = 1;
4087
4088 zpool_close(zhp);
4089
4090 nvlist_free(policy);
4091
4092 return (ret);
4093 }
4094
4095 /*
4096 * zpool reguid <pool>
4097 */
4098 int
4099 zpool_do_reguid(int argc, char **argv)
4100 {
4101 int c;
4102 char *poolname;
4103 zpool_handle_t *zhp;
4104 int ret = 0;
4105
4106 /* check options */
4107 while ((c = getopt(argc, argv, "")) != -1) {
4108 switch (c) {
4109 case '?':
4110 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4111 optopt);
4112 usage(B_FALSE);
4113 }
4114 }
4115
4116 argc -= optind;
4117 argv += optind;
4118
4119 /* get pool name and check number of arguments */
4120 if (argc < 1) {
4121 (void) fprintf(stderr, gettext("missing pool name\n"));
4122 usage(B_FALSE);
4123 }
4124
4125 if (argc > 1) {
4126 (void) fprintf(stderr, gettext("too many arguments\n"));
4127 usage(B_FALSE);
4128 }
4129
4130 poolname = argv[0];
4131 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4132 return (1);
4133
4134 ret = zpool_reguid(zhp);
4135
4136 zpool_close(zhp);
4137 return (ret);
4138 }
4139
4140
4141 /*
4142 * zpool reopen <pool>
4143 *
4144 * Reopen the pool so that the kernel can update the sizes of all vdevs.
4145 */
4146 int
4147 zpool_do_reopen(int argc, char **argv)
4148 {
4149 int c;
4150 int ret = 0;
4151 zpool_handle_t *zhp;
4152 char *pool;
4153
4154 /* check options */
4155 while ((c = getopt(argc, argv, "")) != -1) {
4156 switch (c) {
4157 case '?':
4158 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4159 optopt);
4160 usage(B_FALSE);
4161 }
4162 }
4163
4164 argc--;
4165 argv++;
4166
4167 if (argc < 1) {
4168 (void) fprintf(stderr, gettext("missing pool name\n"));
4169 usage(B_FALSE);
4170 }
4171
4172 if (argc > 1) {
4173 (void) fprintf(stderr, gettext("too many arguments\n"));
4174 usage(B_FALSE);
4175 }
4176
4177 pool = argv[0];
4178 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4179 return (1);
4180
4181 ret = zpool_reopen(zhp);
4182 zpool_close(zhp);
4183 return (ret);
4184 }
4185
4186 typedef struct scrub_cbdata {
4187 int cb_type;
4188 int cb_argc;
4189 char **cb_argv;
4190 pool_scrub_cmd_t cb_scrub_cmd;
4191 } scrub_cbdata_t;
4192
4193 int
4194 scrub_callback(zpool_handle_t *zhp, void *data)
4195 {
4196 scrub_cbdata_t *cb = data;
4197 int err;
4198
4199 /*
4200 * Ignore faulted pools.
4201 */
4202 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4203 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4204 "currently unavailable\n"), zpool_get_name(zhp));
4205 return (1);
4206 }
4207
4208 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4209
4210 return (err != 0);
4211 }
4212
4213 typedef struct trim_cbdata {
4214 boolean_t cb_start;
4215 uint64_t cb_rate;
4216 } trim_cbdata_t;
4217
4218 int
4219 trim_callback(zpool_handle_t *zhp, void *data)
4220 {
4221 trim_cbdata_t *cb = data;
4222 int err;
4223
4224 /*
4225 * Ignore faulted pools.
4226 */
4227 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4228 (void) fprintf(stderr, gettext("cannot trim '%s': pool is "
4229 "currently unavailable\n"), zpool_get_name(zhp));
4230 return (1);
4231 }
4232
4233 err = zpool_trim(zhp, cb->cb_start, cb->cb_rate);
4234
4235 return (err != 0);
4236 }
4237
4238 /*
4239 * zpool scrub [-s | -p] <pool> ...
4240 *
4241 * -s Stop. Stops any in-progress scrub.
4242 * -p Pause. Pause in-progress scrub.
4243 */
4244 int
4245 zpool_do_scrub(int argc, char **argv)
4246 {
4247 int c;
4248 scrub_cbdata_t cb;
4249
4250 cb.cb_type = POOL_SCAN_SCRUB;
4251 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4252
4253 /* check options */
4254 while ((c = getopt(argc, argv, "mMps")) != -1) {
4255 switch (c) {
4256 case 's':
4257 if (cb.cb_type != POOL_SCAN_SCRUB) {
4258 (void) fprintf(stderr,
4259 gettext("incompatible options\n"));
4260 usage(B_FALSE);
4261 } else
4262 cb.cb_type = POOL_SCAN_NONE;
4263 break;
4264 case 'M':
4265 if (cb.cb_type != POOL_SCAN_SCRUB) {
4266 (void) fprintf(stderr,
4267 gettext("incompatible options\n"));
4268 usage(B_FALSE);
4269 } else
4270 cb.cb_type = POOL_SCAN_MOS;
4271 break;
4272 case 'm':
4273 if (cb.cb_type != POOL_SCAN_SCRUB) {
4274 (void) fprintf(stderr,
4275 gettext("incompatible options\n"));
4276 usage(B_FALSE);
4277 } else
4278 cb.cb_type = POOL_SCAN_META;
4279 break;
4280 case 'p':
4281 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4282 break;
4283 case '?':
4284 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4285 optopt);
4286 usage(B_FALSE);
4287 }
4288 }
4289
4290 if (cb.cb_type == POOL_SCAN_NONE &&
4291 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4292 (void) fprintf(stderr, gettext("invalid option combination: "
4293 "-s and -p are mutually exclusive\n"));
4294 usage(B_FALSE);
4295 }
4296
4297 cb.cb_argc = argc;
4298 cb.cb_argv = argv;
4299 argc -= optind;
4300 argv += optind;
4301
4302 if (argc < 1) {
4303 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4304 usage(B_FALSE);
4305 }
4306
4307 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4308 }
4309
4310 /*
4311 * zpool trim [-s|-r <rate>] <pool> ...
4312 *
4313 * -s Stop. Stops any in-progress trim.
4314 * -r <rate> Sets the TRIM rate.
4315 */
4316 int
4317 zpool_do_trim(int argc, char **argv)
4318 {
4319 int c;
4320 trim_cbdata_t cb;
4321
4322 cb.cb_start = B_TRUE;
4323 cb.cb_rate = 0;
4324
4325 /* check options */
4326 while ((c = getopt(argc, argv, "sr:")) != -1) {
4327 switch (c) {
4328 case 's':
4329 cb.cb_start = B_FALSE;
4330 break;
4331 case 'r':
4332 if (zfs_nicestrtonum(NULL, optarg, &cb.cb_rate) == -1) {
4333 (void) fprintf(stderr,
4334 gettext("invalid value for rate\n"));
4335 usage(B_FALSE);
4336 }
4337 break;
4338 case '?':
4339 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4340 optopt);
4341 usage(B_FALSE);
4342 }
4343 }
4344
4345 argc -= optind;
4346 argv += optind;
4347
4348 if (argc < 1) {
4349 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4350 usage(B_FALSE);
4351 }
4352
4353 return (for_each_pool(argc, argv, B_TRUE, NULL, trim_callback, &cb));
4354 }
4355
4356 typedef struct status_cbdata {
4357 int cb_count;
4358 boolean_t cb_allpools;
4359 boolean_t cb_verbose;
4360 boolean_t cb_explain;
4361 boolean_t cb_first;
4362 boolean_t cb_dedup_stats;
4363 } status_cbdata_t;
4364
4365 /*
4366 * Print out detailed scrub status.
4367 */
4368 void
4369 print_scan_status(pool_scan_stat_t *ps)
4370 {
4371 time_t start, end, pause;
4372 uint64_t elapsed, mins_left, hours_left;
4373 uint64_t examined, total;
4374 uint64_t rate, proc_rate;
4375 double fraction_done;
4376 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7],
4377 issued_buf[7];
4378
4379 (void) printf(gettext(" scan: "));
4380
4381 /* If there's never been a scan, there's not much to say. */
4382 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4383 ps->pss_func >= POOL_SCAN_FUNCS) {
4384 (void) printf(gettext("none requested\n"));
4385 return;
4386 }
4387
4388 start = ps->pss_start_time;
4389 end = ps->pss_end_time;
4390 pause = ps->pss_pass_scrub_pause;
4391 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4392
4393 assert(ps->pss_func == POOL_SCAN_SCRUB ||
4394 ps->pss_func == POOL_SCAN_RESILVER ||
4395 ps->pss_func == POOL_SCAN_MOS ||
4396 ps->pss_func == POOL_SCAN_META);
4397 /*
4398 * Scan is finished or canceled.
4399 */
4400 if (ps->pss_state == DSS_FINISHED) {
4401 uint64_t minutes_taken = (end - start) / 60;
4402 char *fmt = NULL;
4403
4404 if (ps->pss_func == POOL_SCAN_SCRUB) {
4405 fmt = gettext("scrub repaired %s in %lluh%um with "
4406 "%llu errors on %s");
4407 } else if (ps->pss_func == POOL_SCAN_MOS) {
4408 fmt = gettext("MOS scrub repaired %s in %lluh%um with "
4409 "%llu errors on %s");
4410 } else if (ps->pss_func == POOL_SCAN_META) {
4411 fmt = gettext("meta scrub repaired %s in %lluh%um with "
4412 "%llu errors on %s");
4413 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4414 fmt = gettext("resilvered %s in %lluh%um with "
4415 "%llu errors on %s");
4416 }
4417 /* LINTED */
4418 (void) printf(fmt, processed_buf,
4419 (u_longlong_t)(minutes_taken / 60),
4420 (uint_t)(minutes_taken % 60),
4421 (u_longlong_t)ps->pss_errors,
4422 ctime((time_t *)&end));
4423 return;
4424 } else if (ps->pss_state == DSS_CANCELED) {
4425 if (ps->pss_func == POOL_SCAN_SCRUB) {
4426 (void) printf(gettext("scrub canceled on %s"),
4427 ctime(&end));
4428 } else if (ps->pss_func == POOL_SCAN_MOS) {
4429 (void) printf(gettext("MOS scrub canceled on %s"),
4430 ctime(&end));
4431 } else if (ps->pss_func == POOL_SCAN_META) {
4432 (void) printf(gettext("meta scrub canceled on %s"),
4433 ctime(&end));
4434 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4435 (void) printf(gettext("resilver canceled on %s"),
4436 ctime(&end));
4437 }
4438 return;
4439 }
4440
4441 assert(ps->pss_state == DSS_SCANNING || ps->pss_state == DSS_FINISHING);
4442
4443 /*
4444 * Scan is in progress.
4445 */
4446 if (ps->pss_func == POOL_SCAN_SCRUB) {
4447 if (pause == 0) {
4448 (void) printf(gettext("scrub in progress since %s"),
4449 ctime(&start));
4450 } else {
4451 char buf[32];
4452 struct tm *p = localtime(&pause);
4453 (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4454 (void) printf(gettext("scrub paused since %s\n"), buf);
4455 (void) printf(gettext("\tscrub started on %s"),
4456 ctime(&start));
4457 }
4458 } else if (ps->pss_func == POOL_SCAN_MOS) {
4459 (void) printf(gettext("MOS scrub in progress since %s"),
4460 ctime(&start));
4461 } else if (ps->pss_func == POOL_SCAN_META) {
4462 (void) printf(gettext("meta scrub in progress since %s"),
4463 ctime(&start));
4464 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4465 (void) printf(gettext("resilver in progress since %s"),
4466 ctime(&start));
4467 }
4468
4469 examined = ps->pss_examined;
4470 total = ps->pss_to_examine;
4471 fraction_done = (double)ps->pss_issued / total;
4472
4473 /* elapsed time for this pass */
4474 elapsed = MAX(time(NULL) - ps->pss_start_time -
4475 ps->pss_pass_scrub_spent_paused, 1);
4476 if (ps->pss_func == POOL_SCAN_RESILVER) {
4477 rate = MAX(((ps->pss_issued + ps->pss_processed) / 2) /
4478 elapsed, 1);
4479 } else {
4480 rate = MAX(ps->pss_issued / elapsed, 1);
4481 }
4482 proc_rate = MAX(ps->pss_processed / elapsed, 1);
4483 if (ps->pss_func == POOL_SCAN_RESILVER)
4484 mins_left = ((total - ps->pss_issued) / proc_rate) / 60;
4485 else
4486 mins_left = ((total - ps->pss_issued) / rate) / 60;
4487 hours_left = mins_left / 60;
4488
4489 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4490 zfs_nicenum(ps->pss_issued, issued_buf, sizeof (issued_buf));
4491 zfs_nicenum(total, total_buf, sizeof (total_buf));
4492 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4493
4494 if (pause == 0) {
4495 (void) printf(gettext(" %s scanned, %s verified "
4496 "out of %s at %s/s, %.2f%% done\n"), examined_buf,
4497 issued_buf, total_buf, rate_buf, 100 * fraction_done);
4498 }
4499
4500 if (ps->pss_func == POOL_SCAN_RESILVER) {
4501 char proc_rate_buf[7];
4502 zfs_nicenum(proc_rate, proc_rate_buf,
4503 sizeof (proc_rate_buf));
4504 (void) printf(gettext(" %s resilvered at %s/s"),
4505 processed_buf, proc_rate_buf);
4506 } else if (ps->pss_func == POOL_SCAN_SCRUB ||
4507 ps->pss_func == POOL_SCAN_MOS ||
4508 ps->pss_func == POOL_SCAN_META) {
4509 (void) printf(gettext(" %s repaired"),
4510 processed_buf);
4511 }
4512
4513 /*
4514 * do not print estimated time if hours_left is more than 30 days
4515 * or we have a paused scrub
4516 */
4517 if (pause == 0) {
4518 if (hours_left < (30 * 24)) {
4519 (void) printf(gettext(", %lluh%um to go\n"),
4520 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4521 } else {
4522 (void) printf(gettext(
4523 ", (scan is slow, no estimated time)\n"));
4524 }
4525 } else {
4526 (void) printf(gettext("\t%s scanned, %s verified out of %s\n"),
4527 examined_buf, issued_buf, total_buf);
4528 }
4529 }
4530
4531 static void
4532 print_trim_status(uint64_t trim_prog, uint64_t total_size, uint64_t rate,
4533 uint64_t start_time_u64, uint64_t end_time_u64)
4534 {
4535 time_t start_time = start_time_u64, end_time = end_time_u64;
4536 char *buf;
4537
4538 assert(trim_prog <= total_size);
4539 if (trim_prog != 0 && trim_prog != total_size) {
4540 buf = ctime(&start_time);
4541 buf[strlen(buf) - 1] = '\0'; /* strip trailing newline */
4542 if (rate != 0) {
4543 char rate_str[32];
4544 zfs_nicenum(rate, rate_str, sizeof (rate_str));
4545 (void) printf(" trim: %.02f%%\tstarted: %s\t"
4546 "(rate: %s/s)\n", (((double)trim_prog) /
4547 total_size) * 100, buf, rate_str);
4548 } else {
4549 (void) printf(" trim: %.02f%%\tstarted: %s\t"
4550 "(rate: max)\n", (((double)trim_prog) /
4551 total_size) * 100, buf);
4552 }
4553 } else {
4554 if (start_time != 0) {
4555 /*
4556 * Non-zero start time means we were run at some point
4557 * in the past.
4558 */
4559 if (end_time != 0) {
4560 /* Non-zero end time means we completed */
4561 time_t diff = end_time - start_time;
4562 int hrs, mins;
4563
4564 buf = ctime(&end_time);
4565 buf[strlen(buf) - 1] = '\0';
4566 hrs = diff / 3600;
4567 mins = (diff % 3600) / 60;
4568 (void) printf(gettext(" trim: completed on %s "
4569 "(after %dh%dm)\n"), buf, hrs, mins);
4570 } else {
4571 buf = ctime(&start_time);
4572 buf[strlen(buf) - 1] = '\0';
4573 /* Zero end time means we were interrupted */
4574 (void) printf(gettext(" trim: interrupted\t"
4575 "(started %s)\n"), buf);
4576 }
4577 } else {
4578 /* trim was never run */
4579 (void) printf(gettext(" trim: none requested\n"));
4580 }
4581 }
4582 }
4583
4584 static void
4585 print_error_log(zpool_handle_t *zhp)
4586 {
4587 nvlist_t *nverrlist = NULL;
4588 nvpair_t *elem;
4589 char *pathname;
4590 size_t len = MAXPATHLEN * 2;
4591
4592 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4593 (void) printf("errors: List of errors unavailable "
4594 "(insufficient privileges)\n");
4595 return;
4596 }
4597
4598 (void) printf("errors: Permanent errors have been "
4599 "detected in the following files:\n\n");
4600
4601 pathname = safe_malloc(len);
4602 elem = NULL;
4603 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4604 nvlist_t *nv;
4605 uint64_t dsobj, obj;
4606
4607 verify(nvpair_value_nvlist(elem, &nv) == 0);
4608 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4609 &dsobj) == 0);
4610 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4611 &obj) == 0);
4612 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4613 (void) printf("%7s %s\n", "", pathname);
4614 }
4615 free(pathname);
4616 nvlist_free(nverrlist);
4617 }
4618
4619 static void
4620 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4621 int namewidth)
4622 {
4623 uint_t i;
4624 char *name;
4625
4626 if (nspares == 0)
4627 return;
4628
4629 (void) printf(gettext("\tspares\n"));
4630
4631 for (i = 0; i < nspares; i++) {
4632 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4633 print_status_config(zhp, name, spares[i],
4634 namewidth, 2, B_TRUE);
4635 free(name);
4636 }
4637 }
4638
4639 static void
4640 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4641 int namewidth)
4642 {
4643 uint_t i;
4644 char *name;
4645
4646 if (nl2cache == 0)
4647 return;
4648
4649 (void) printf(gettext("\tcache\n"));
4650
4651 for (i = 0; i < nl2cache; i++) {
4652 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4653 print_status_config(zhp, name, l2cache[i],
4654 namewidth, 2, B_FALSE);
4655 free(name);
4656 }
4657 }
4658
4659 static void
4660 print_dedup_stats(nvlist_t *config)
4661 {
4662 ddt_histogram_t *ddh;
4663 ddt_stat_t *dds;
4664 ddt_object_t *ddo;
4665 uint_t c;
4666
4667 /*
4668 * If the pool was faulted then we may not have been able to
4669 * obtain the config. Otherwise, if we have anything in the dedup
4670 * table continue processing the stats.
4671 */
4672 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4673 (uint64_t **)&ddo, &c) != 0)
4674 return;
4675
4676 (void) printf("\n");
4677 (void) printf(gettext(" dedup: "));
4678 if (ddo->ddo_count == 0) {
4679 (void) printf(gettext("no DDT entries\n"));
4680 return;
4681 }
4682
4683 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4684 (u_longlong_t)ddo->ddo_count,
4685 (u_longlong_t)ddo->ddo_dspace,
4686 (u_longlong_t)ddo->ddo_mspace);
4687
4688 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4689 (uint64_t **)&dds, &c) == 0);
4690 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4691 (uint64_t **)&ddh, &c) == 0);
4692 zpool_dump_ddt(dds, ddh);
4693 }
4694
4695 /*
4696 * Calculates the total space available on log devices on the pool.
4697 * For whatever reason, this is not counted in the root vdev's space stats.
4698 */
4699 static uint64_t
4700 zpool_slog_space(nvlist_t *nvroot)
4701 {
4702 nvlist_t **newchild;
4703 uint_t c, children;
4704 uint64_t space = 0;
4705
4706 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4707 &newchild, &children) == 0);
4708
4709 for (c = 0; c < children; c++) {
4710 uint64_t islog = B_FALSE;
4711 vdev_stat_t *vs;
4712 uint_t n;
4713 uint_t n_subchildren = 1;
4714 nvlist_t **subchild;
4715
4716 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4717 &islog);
4718 if (!islog)
4719 continue;
4720 verify(nvlist_lookup_uint64_array(newchild[c],
4721 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &n) == 0);
4722
4723 /* vdev can be non-leaf, so multiply by number of children */
4724 (void) nvlist_lookup_nvlist_array(newchild[c],
4725 ZPOOL_CONFIG_CHILDREN, &subchild, &n_subchildren);
4726 space += n_subchildren * vs->vs_space;
4727 }
4728
4729 return (space);
4730 }
4731
4732 /*
4733 * Display a summary of pool status. Displays a summary such as:
4734 *
4735 * pool: tank
4736 * status: DEGRADED
4737 * reason: One or more devices ...
4738 * see: http://illumos.org/msg/ZFS-xxxx-01
4739 * config:
4740 * mirror DEGRADED
4741 * c1t0d0 OK
4742 * c2t0d0 UNAVAIL
4743 *
4744 * When given the '-v' option, we print out the complete config. If the '-e'
4745 * option is specified, then we print out error rate information as well.
4746 */
4747 int
4748 status_callback(zpool_handle_t *zhp, void *data)
4749 {
4750 status_cbdata_t *cbp = data;
4751 nvlist_t *config, *nvroot;
4752 char *msgid;
4753 int reason;
4754 const char *health;
4755 uint_t c;
4756 vdev_stat_t *vs;
4757
4758 config = zpool_get_config(zhp, NULL);
4759 reason = zpool_get_status(zhp, &msgid);
4760
4761 cbp->cb_count++;
4762
4763 /*
4764 * If we were given 'zpool status -x', only report those pools with
4765 * problems.
4766 */
4767 if (cbp->cb_explain &&
4768 (reason == ZPOOL_STATUS_OK ||
4769 reason == ZPOOL_STATUS_VERSION_OLDER ||
4770 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4771 if (!cbp->cb_allpools) {
4772 (void) printf(gettext("pool '%s' is healthy\n"),
4773 zpool_get_name(zhp));
4774 if (cbp->cb_first)
4775 cbp->cb_first = B_FALSE;
4776 }
4777 return (0);
4778 }
4779
4780 if (cbp->cb_first)
4781 cbp->cb_first = B_FALSE;
4782 else
4783 (void) printf("\n");
4784
4785 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4786 &nvroot) == 0);
4787 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4788 (uint64_t **)&vs, &c) == 0);
4789 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4790
4791 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
4792 (void) printf(gettext(" state: %s\n"), health);
4793
4794 switch (reason) {
4795 case ZPOOL_STATUS_MISSING_DEV_R:
4796 (void) printf(gettext("status: One or more devices could not "
4797 "be opened. Sufficient replicas exist for\n\tthe pool to "
4798 "continue functioning in a degraded state.\n"));
4799 (void) printf(gettext("action: Attach the missing device and "
4800 "online it using 'zpool online'.\n"));
4801 break;
4802
4803 case ZPOOL_STATUS_MISSING_DEV_NR:
4804 (void) printf(gettext("status: One or more devices could not "
4805 "be opened. There are insufficient\n\treplicas for the "
4806 "pool to continue functioning.\n"));
4807 (void) printf(gettext("action: Attach the missing device and "
4808 "online it using 'zpool online'.\n"));
4809 break;
4810
4811 case ZPOOL_STATUS_CORRUPT_LABEL_R:
4812 (void) printf(gettext("status: One or more devices could not "
4813 "be used because the label is missing or\n\tinvalid. "
4814 "Sufficient replicas exist for the pool to continue\n\t"
4815 "functioning in a degraded state.\n"));
4816 (void) printf(gettext("action: Replace the device using "
4817 "'zpool replace'.\n"));
4818 break;
4819
4820 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4821 (void) printf(gettext("status: One or more devices could not "
4822 "be used because the label is missing \n\tor invalid. "
4823 "There are insufficient replicas for the pool to "
4824 "continue\n\tfunctioning.\n"));
4825 zpool_explain_recover(zpool_get_handle(zhp),
4826 zpool_get_name(zhp), reason, config);
4827 break;
4828
4829 case ZPOOL_STATUS_FAILING_DEV:
4830 (void) printf(gettext("status: One or more devices has "
4831 "experienced an unrecoverable error. An\n\tattempt was "
4832 "made to correct the error. Applications are "
4833 "unaffected.\n"));
4834 (void) printf(gettext("action: Determine if the device needs "
4835 "to be replaced, and clear the errors\n\tusing "
4836 "'zpool clear' or replace the device with 'zpool "
4837 "replace'.\n"));
4838 break;
4839
4840 case ZPOOL_STATUS_OFFLINE_DEV:
4841 (void) printf(gettext("status: One or more devices has "
4842 "been taken offline by the administrator.\n\tSufficient "
4843 "replicas exist for the pool to continue functioning in "
4844 "a\n\tdegraded state.\n"));
4845 (void) printf(gettext("action: Online the device using "
4846 "'zpool online' or replace the device with\n\t'zpool "
4847 "replace'.\n"));
4848 break;
4849
4850 case ZPOOL_STATUS_REMOVED_DEV:
4851 (void) printf(gettext("status: One or more devices has "
4852 "been removed by the administrator.\n\tSufficient "
4853 "replicas exist for the pool to continue functioning in "
4854 "a\n\tdegraded state.\n"));
4855 (void) printf(gettext("action: Online the device using "
4856 "'zpool online' or replace the device with\n\t'zpool "
4857 "replace'.\n"));
4858 break;
4859
4860 case ZPOOL_STATUS_RESILVERING:
4861 (void) printf(gettext("status: One or more devices is "
4862 "currently being resilvered. The pool will\n\tcontinue "
4863 "to function, possibly in a degraded state.\n"));
4864 (void) printf(gettext("action: Wait for the resilver to "
4865 "complete.\n"));
4866 break;
4867
4868 case ZPOOL_STATUS_CORRUPT_DATA:
4869 (void) printf(gettext("status: One or more devices has "
4870 "experienced an error resulting in data\n\tcorruption. "
4871 "Applications may be affected.\n"));
4872 (void) printf(gettext("action: Restore the file in question "
4873 "if possible. Otherwise restore the\n\tentire pool from "
4874 "backup.\n"));
4875 break;
4876
4877 case ZPOOL_STATUS_CORRUPT_POOL:
4878 (void) printf(gettext("status: The pool metadata is corrupted "
4879 "and the pool cannot be opened.\n"));
4880 zpool_explain_recover(zpool_get_handle(zhp),
4881 zpool_get_name(zhp), reason, config);
4882 break;
4883
4884 case ZPOOL_STATUS_VERSION_OLDER:
4885 (void) printf(gettext("status: The pool is formatted using a "
4886 "legacy on-disk format. The pool can\n\tstill be used, "
4887 "but some features are unavailable.\n"));
4888 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4889 "upgrade'. Once this is done, the\n\tpool will no longer "
4890 "be accessible on software that does not support feature\n"
4891 "\tflags.\n"));
4892 break;
4893
4894 case ZPOOL_STATUS_VERSION_NEWER:
4895 (void) printf(gettext("status: The pool has been upgraded to a "
4896 "newer, incompatible on-disk version.\n\tThe pool cannot "
4897 "be accessed on this system.\n"));
4898 (void) printf(gettext("action: Access the pool from a system "
4899 "running more recent software, or\n\trestore the pool from "
4900 "backup.\n"));
4901 break;
4902
4903 case ZPOOL_STATUS_FEAT_DISABLED:
4904 (void) printf(gettext("status: Some supported features are not "
4905 "enabled on the pool. The pool can\n\tstill be used, but "
4906 "some features are unavailable.\n"));
4907 (void) printf(gettext("action: Enable all features using "
4908 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4909 "longer be accessible by software that does not support\n\t"
4910 "the features. See zpool-features(5) for details.\n"));
4911 break;
4912
4913 case ZPOOL_STATUS_UNSUP_FEAT_READ:
4914 (void) printf(gettext("status: The pool cannot be accessed on "
4915 "this system because it uses the\n\tfollowing feature(s) "
4916 "not supported on this system:\n"));
4917 zpool_print_unsup_feat(config);
4918 (void) printf("\n");
4919 (void) printf(gettext("action: Access the pool from a system "
4920 "that supports the required feature(s),\n\tor restore the "
4921 "pool from backup.\n"));
4922 break;
4923
4924 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4925 (void) printf(gettext("status: The pool can only be accessed "
4926 "in read-only mode on this system. It\n\tcannot be "
4927 "accessed in read-write mode because it uses the "
4928 "following\n\tfeature(s) not supported on this system:\n"));
4929 zpool_print_unsup_feat(config);
4930 (void) printf("\n");
4931 (void) printf(gettext("action: The pool cannot be accessed in "
4932 "read-write mode. Import the pool with\n"
4933 "\t\"-o readonly=on\", access the pool from a system that "
4934 "supports the\n\trequired feature(s), or restore the "
4935 "pool from backup.\n"));
4936 break;
4937
4938 case ZPOOL_STATUS_FAULTED_DEV_R:
4939 (void) printf(gettext("status: One or more devices are "
4940 "faulted in response to persistent errors.\n\tSufficient "
4941 "replicas exist for the pool to continue functioning "
4942 "in a\n\tdegraded state.\n"));
4943 (void) printf(gettext("action: Replace the faulted device, "
4944 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4945 break;
4946
4947 case ZPOOL_STATUS_FAULTED_DEV_NR:
4948 (void) printf(gettext("status: One or more devices are "
4949 "faulted in response to persistent errors. There are "
4950 "insufficient replicas for the pool to\n\tcontinue "
4951 "functioning.\n"));
4952 (void) printf(gettext("action: Destroy and re-create the pool "
4953 "from a backup source. Manually marking the device\n"
4954 "\trepaired using 'zpool clear' may allow some data "
4955 "to be recovered.\n"));
4956 break;
4957
4958 case ZPOOL_STATUS_IO_FAILURE_WAIT:
4959 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4960 (void) printf(gettext("status: One or more devices are "
4961 "faulted in response to IO failures.\n"));
4962 (void) printf(gettext("action: Make sure the affected devices "
4963 "are connected, then run 'zpool clear'.\n"));
4964 break;
4965
4966 case ZPOOL_STATUS_BAD_LOG:
4967 (void) printf(gettext("status: An intent log record "
4968 "could not be read.\n"
4969 "\tWaiting for adminstrator intervention to fix the "
4970 "faulted pool.\n"));
4971 (void) printf(gettext("action: Either restore the affected "
4972 "device(s) and run 'zpool online',\n"
4973 "\tor ignore the intent log records by running "
4974 "'zpool clear'.\n"));
4975 break;
4976
4977 default:
4978 /*
4979 * The remaining errors can't actually be generated, yet.
4980 */
4981 assert(reason == ZPOOL_STATUS_OK);
4982 }
4983
4984 if (msgid != NULL)
4985 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4986 msgid);
4987
4988 if (config != NULL) {
4989 int namewidth;
4990 uint64_t nerr;
4991 nvlist_t **spares, **l2cache;
4992 uint_t nspares, nl2cache;
4993 pool_scan_stat_t *ps = NULL;
4994 uint64_t trim_prog, trim_rate, trim_start_time, trim_stop_time;
4995
4996 (void) nvlist_lookup_uint64_array(nvroot,
4997 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4998 print_scan_status(ps);
4999
5000 /* Grab trim stats if the pool supports it */
5001 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_PROG,
5002 &trim_prog) == 0 &&
5003 nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_RATE,
5004 &trim_rate) == 0 &&
5005 nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_START_TIME,
5006 &trim_start_time) == 0 &&
5007 nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_STOP_TIME,
5008 &trim_stop_time) == 0) {
5009 /*
5010 * For whatever reason, root vdev_stats_t don't
5011 * include log devices.
5012 */
5013 print_trim_status(trim_prog, vs->vs_space +
5014 zpool_slog_space(nvroot), trim_rate,
5015 trim_start_time, trim_stop_time);
5016 }
5017
5018 namewidth = max_width(zhp, nvroot, 0, 0);
5019 if (namewidth < 10)
5020 namewidth = 10;
5021
5022 (void) printf(gettext("config:\n\n"));
5023 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
5024 "NAME", "STATE", "READ", "WRITE", "CKSUM");
5025 print_status_config(zhp, zpool_get_name(zhp), nvroot,
5026 namewidth, 0, B_FALSE);
5027
5028 if (num_special(nvroot) > 0)
5029 print_special(zhp, nvroot, namewidth, B_TRUE);
5030 if (num_logs(nvroot) > 0)
5031 print_logs(zhp, nvroot, namewidth, B_TRUE);
5032 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5033 &l2cache, &nl2cache) == 0)
5034 print_l2cache(zhp, l2cache, nl2cache, namewidth);
5035
5036 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5037 &spares, &nspares) == 0)
5038 print_spares(zhp, spares, nspares, namewidth);
5039
5040 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5041 &nerr) == 0) {
5042 nvlist_t *nverrlist = NULL;
5043
5044 /*
5045 * If the approximate error count is small, get a
5046 * precise count by fetching the entire log and
5047 * uniquifying the results.
5048 */
5049 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
5050 zpool_get_errlog(zhp, &nverrlist) == 0) {
5051 nvpair_t *elem;
5052
5053 elem = NULL;
5054 nerr = 0;
5055 while ((elem = nvlist_next_nvpair(nverrlist,
5056 elem)) != NULL) {
5057 nerr++;
5058 }
5059 }
5060 nvlist_free(nverrlist);
5061
5062 (void) printf("\n");
5063
5064 if (nerr == 0)
5065 (void) printf(gettext("errors: No known data "
5066 "errors\n"));
5067 else if (!cbp->cb_verbose)
5068 (void) printf(gettext("errors: %llu data "
5069 "errors, use '-v' for a list\n"),
5070 (u_longlong_t)nerr);
5071 else
5072 print_error_log(zhp);
5073 }
5074
5075 if (cbp->cb_dedup_stats)
5076 print_dedup_stats(config);
5077 } else {
5078 (void) printf(gettext("config: The configuration cannot be "
5079 "determined.\n"));
5080 }
5081
5082 return (0);
5083 }
5084
5085 /*
5086 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
5087 *
5088 * -v Display complete error logs
5089 * -x Display only pools with potential problems
5090 * -D Display dedup status (undocumented)
5091 * -T Display a timestamp in date(1) or Unix format
5092 *
5093 * Describes the health status of all pools or some subset.
5094 */
5095 int
5096 zpool_do_status(int argc, char **argv)
5097 {
5098 int c;
5099 int ret;
5100 unsigned long interval = 0, count = 0;
5101 status_cbdata_t cb = { 0 };
5102
5103 /* check options */
5104 while ((c = getopt(argc, argv, "vxDT:")) != -1) {
5105 switch (c) {
5106 case 'v':
5107 cb.cb_verbose = B_TRUE;
5108 break;
5109 case 'x':
5110 cb.cb_explain = B_TRUE;
5111 break;
5112 case 'D':
5113 cb.cb_dedup_stats = B_TRUE;
5114 break;
5115 case 'T':
5116 get_timestamp_arg(*optarg);
5117 break;
5118 case '?':
5119 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5120 optopt);
5121 usage(B_FALSE);
5122 }
5123 }
5124
5125 argc -= optind;
5126 argv += optind;
5127
5128 get_interval_count(&argc, argv, &interval, &count);
5129
5130 if (argc == 0)
5131 cb.cb_allpools = B_TRUE;
5132
5133 cb.cb_first = B_TRUE;
5134
5135 for (;;) {
5136 if (timestamp_fmt != NODATE)
5137 print_timestamp(timestamp_fmt);
5138
5139 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5140 status_callback, &cb);
5141
5142 if (argc == 0 && cb.cb_count == 0)
5143 (void) printf(gettext("no pools available\n"));
5144 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5145 (void) printf(gettext("all pools are healthy\n"));
5146
5147 if (ret != 0)
5148 return (ret);
5149
5150 if (interval == 0)
5151 break;
5152
5153 if (count != 0 && --count == 0)
5154 break;
5155
5156 (void) sleep(interval);
5157 }
5158
5159 return (0);
5160 }
5161
5162 typedef struct upgrade_cbdata {
5163 int cb_first;
5164 int cb_argc;
5165 uint64_t cb_version;
5166 char **cb_argv;
5167 } upgrade_cbdata_t;
5168
5169 static int
5170 upgrade_version(zpool_handle_t *zhp, uint64_t version)
5171 {
5172 int ret;
5173 nvlist_t *config;
5174 uint64_t oldversion;
5175
5176 config = zpool_get_config(zhp, NULL);
5177 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5178 &oldversion) == 0);
5179
5180 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5181 assert(oldversion < version);
5182
5183 ret = zpool_upgrade(zhp, version);
5184 if (ret != 0)
5185 return (ret);
5186
5187 if (version >= SPA_VERSION_FEATURES) {
5188 (void) printf(gettext("Successfully upgraded "
5189 "'%s' from version %llu to feature flags.\n"),
5190 zpool_get_name(zhp), oldversion);
5191 } else {
5192 (void) printf(gettext("Successfully upgraded "
5193 "'%s' from version %llu to version %llu.\n"),
5194 zpool_get_name(zhp), oldversion, version);
5195 }
5196
5197 return (0);
5198 }
5199
5200 static int
5201 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5202 {
5203 int i, ret, count;
5204 boolean_t firstff = B_TRUE;
5205 nvlist_t *enabled = zpool_get_features(zhp);
5206
5207 count = 0;
5208 for (i = 0; i < SPA_FEATURES; i++) {
5209 zfeature_info_t *finfo = &spa_feature_table[i];
5210 const char *fname = finfo->fi_uname;
5211 const char *fguid = finfo->fi_guid;
5212 if (!nvlist_exists(enabled, fguid)) {
5213 char *propname;
5214
5215 /*
5216 * SPA_FEATURE_WBC can be enabled only
5217 * if 'special' vdev available
5218 */
5219 if (finfo->fi_feature == SPA_FEATURE_WBC)
5220 continue;
5221
5222 verify(-1 != asprintf(&propname, "feature@%s", fname));
5223 ret = zpool_set_prop(zhp, propname,
5224 ZFS_FEATURE_ENABLED);
5225 if (ret != 0) {
5226 free(propname);
5227 return (ret);
5228 }
5229 count++;
5230
5231 if (firstff) {
5232 (void) printf(gettext("Enabled the "
5233 "following features on '%s':\n"),
5234 zpool_get_name(zhp));
5235 firstff = B_FALSE;
5236 }
5237 (void) printf(gettext(" %s\n"), fname);
5238 free(propname);
5239 }
5240 }
5241
5242 if (countp != NULL)
5243 *countp = count;
5244 return (0);
5245 }
5246
5247 static int
5248 upgrade_cb(zpool_handle_t *zhp, void *arg)
5249 {
5250 upgrade_cbdata_t *cbp = arg;
5251 nvlist_t *config;
5252 uint64_t version;
5253 boolean_t printnl = B_FALSE;
5254 int ret;
5255
5256 config = zpool_get_config(zhp, NULL);
5257 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5258 &version) == 0);
5259
5260 assert(SPA_VERSION_IS_SUPPORTED(version));
5261
5262 if (version < cbp->cb_version) {
5263 cbp->cb_first = B_FALSE;
5264 ret = upgrade_version(zhp, cbp->cb_version);
5265 if (ret != 0)
5266 return (ret);
5267 printnl = B_TRUE;
5268
5269 /*
5270 * If they did "zpool upgrade -a", then we could
5271 * be doing ioctls to different pools. We need
5272 * to log this history once to each pool, and bypass
5273 * the normal history logging that happens in main().
5274 */
5275 (void) zpool_log_history(g_zfs, history_str);
5276 log_history = B_FALSE;
5277 }
5278
5279 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5280 int count;
5281 ret = upgrade_enable_all(zhp, &count);
5282 if (ret != 0)
5283 return (ret);
5284
5285 if (count > 0) {
5286 cbp->cb_first = B_FALSE;
5287 printnl = B_TRUE;
5288 }
5289 }
5290
5291 if (printnl) {
5292 (void) printf(gettext("\n"));
5293 }
5294
5295 return (0);
5296 }
5297
5298 static int
5299 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5300 {
5301 upgrade_cbdata_t *cbp = arg;
5302 nvlist_t *config;
5303 uint64_t version;
5304
5305 config = zpool_get_config(zhp, NULL);
5306 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5307 &version) == 0);
5308
5309 assert(SPA_VERSION_IS_SUPPORTED(version));
5310
5311 if (version < SPA_VERSION_FEATURES) {
5312 if (cbp->cb_first) {
5313 (void) printf(gettext("The following pools are "
5314 "formatted with legacy version numbers and can\n"
5315 "be upgraded to use feature flags. After "
5316 "being upgraded, these pools\nwill no "
5317 "longer be accessible by software that does not "
5318 "support feature\nflags.\n\n"));
5319 (void) printf(gettext("VER POOL\n"));
5320 (void) printf(gettext("--- ------------\n"));
5321 cbp->cb_first = B_FALSE;
5322 }
5323
5324 (void) printf("%2llu %s\n", (u_longlong_t)version,
5325 zpool_get_name(zhp));
5326 }
5327
5328 return (0);
5329 }
5330
5331 static int
5332 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5333 {
5334 upgrade_cbdata_t *cbp = arg;
5335 nvlist_t *config;
5336 uint64_t version;
5337
5338 config = zpool_get_config(zhp, NULL);
5339 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5340 &version) == 0);
5341
5342 if (version >= SPA_VERSION_FEATURES) {
5343 int i;
5344 boolean_t poolfirst = B_TRUE;
5345 nvlist_t *enabled = zpool_get_features(zhp);
5346
5347 for (i = 0; i < SPA_FEATURES; i++) {
5348 const char *fguid = spa_feature_table[i].fi_guid;
5349 const char *fname = spa_feature_table[i].fi_uname;
5350 if (!nvlist_exists(enabled, fguid)) {
5351 if (cbp->cb_first) {
5352 (void) printf(gettext("\nSome "
5353 "supported features are not "
5354 "enabled on the following pools. "
5355 "Once a\nfeature is enabled the "
5356 "pool may become incompatible with "
5357 "software\nthat does not support "
5358 "the feature. See "
5359 "zpool-features(5) for "
5360 "details.\n\n"));
5361 (void) printf(gettext("POOL "
5362 "FEATURE\n"));
5363 (void) printf(gettext("------"
5364 "---------\n"));
5365 cbp->cb_first = B_FALSE;
5366 }
5367
5368 if (poolfirst) {
5369 (void) printf(gettext("%s\n"),
5370 zpool_get_name(zhp));
5371 poolfirst = B_FALSE;
5372 }
5373
5374 (void) printf(gettext(" %s\n"), fname);
5375 }
5376 }
5377 }
5378
5379 return (0);
5380 }
5381
5382 /* ARGSUSED */
5383 static int
5384 upgrade_one(zpool_handle_t *zhp, void *data)
5385 {
5386 boolean_t printnl = B_FALSE;
5387 upgrade_cbdata_t *cbp = data;
5388 uint64_t cur_version;
5389 int ret;
5390
5391 if (strcmp("log", zpool_get_name(zhp)) == 0) {
5392 (void) printf(gettext("'log' is now a reserved word\n"
5393 "Pool 'log' must be renamed using export and import"
5394 " to upgrade.\n"));
5395 return (1);
5396 }
5397
5398 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5399 if (cur_version > cbp->cb_version) {
5400 (void) printf(gettext("Pool '%s' is already formatted "
5401 "using more current version '%llu'.\n\n"),
5402 zpool_get_name(zhp), cur_version);
5403 return (0);
5404 }
5405
5406 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5407 (void) printf(gettext("Pool '%s' is already formatted "
5408 "using version %llu.\n\n"), zpool_get_name(zhp),
5409 cbp->cb_version);
5410 return (0);
5411 }
5412
5413 if (cur_version != cbp->cb_version) {
5414 printnl = B_TRUE;
5415 ret = upgrade_version(zhp, cbp->cb_version);
5416 if (ret != 0)
5417 return (ret);
5418 }
5419
5420 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5421 int count = 0;
5422 ret = upgrade_enable_all(zhp, &count);
5423 if (ret != 0)
5424 return (ret);
5425
5426 if (count != 0) {
5427 printnl = B_TRUE;
5428 } else if (cur_version == SPA_VERSION) {
5429 (void) printf(gettext("Pool '%s' already has all "
5430 "supported features enabled.\n"),
5431 zpool_get_name(zhp));
5432 }
5433 }
5434
5435 if (printnl) {
5436 (void) printf(gettext("\n"));
5437 }
5438
5439 return (0);
5440 }
5441
5442 /*
5443 * zpool upgrade
5444 * zpool upgrade -v
5445 * zpool upgrade [-V version] <-a | pool ...>
5446 *
5447 * With no arguments, display downrev'd ZFS pool available for upgrade.
5448 * Individual pools can be upgraded by specifying the pool, and '-a' will
5449 * upgrade all pools.
5450 */
5451 int
5452 zpool_do_upgrade(int argc, char **argv)
5453 {
5454 int c;
5455 upgrade_cbdata_t cb = { 0 };
5456 int ret = 0;
5457 boolean_t showversions = B_FALSE;
5458 boolean_t upgradeall = B_FALSE;
5459 char *end;
5460
5461
5462 /* check options */
5463 while ((c = getopt(argc, argv, ":avV:")) != -1) {
5464 switch (c) {
5465 case 'a':
5466 upgradeall = B_TRUE;
5467 break;
5468 case 'v':
5469 showversions = B_TRUE;
5470 break;
5471 case 'V':
5472 cb.cb_version = strtoll(optarg, &end, 10);
5473 if (*end != '\0' ||
5474 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5475 (void) fprintf(stderr,
5476 gettext("invalid version '%s'\n"), optarg);
5477 usage(B_FALSE);
5478 }
5479 break;
5480 case ':':
5481 (void) fprintf(stderr, gettext("missing argument for "
5482 "'%c' option\n"), optopt);
5483 usage(B_FALSE);
5484 break;
5485 case '?':
5486 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5487 optopt);
5488 usage(B_FALSE);
5489 }
5490 }
5491
5492 cb.cb_argc = argc;
5493 cb.cb_argv = argv;
5494 argc -= optind;
5495 argv += optind;
5496
5497 if (cb.cb_version == 0) {
5498 cb.cb_version = SPA_VERSION;
5499 } else if (!upgradeall && argc == 0) {
5500 (void) fprintf(stderr, gettext("-V option is "
5501 "incompatible with other arguments\n"));
5502 usage(B_FALSE);
5503 }
5504
5505 if (showversions) {
5506 if (upgradeall || argc != 0) {
5507 (void) fprintf(stderr, gettext("-v option is "
5508 "incompatible with other arguments\n"));
5509 usage(B_FALSE);
5510 }
5511 } else if (upgradeall) {
5512 if (argc != 0) {
5513 (void) fprintf(stderr, gettext("-a option should not "
5514 "be used along with a pool name\n"));
5515 usage(B_FALSE);
5516 }
5517 }
5518
5519 (void) printf(gettext("This system supports ZFS pool feature "
5520 "flags.\n\n"));
5521 if (showversions) {
5522 int i;
5523
5524 (void) printf(gettext("The following features are "
5525 "supported:\n\n"));
5526 (void) printf(gettext("FEAT DESCRIPTION\n"));
5527 (void) printf("----------------------------------------------"
5528 "---------------\n");
5529 for (i = 0; i < SPA_FEATURES; i++) {
5530 zfeature_info_t *fi = &spa_feature_table[i];
5531 const char *ro =
5532 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5533 " (read-only compatible)" : "";
5534
5535 (void) printf("%-37s%s\n", fi->fi_uname, ro);
5536 (void) printf(" %s\n", fi->fi_desc);
5537 }
5538 (void) printf("\n");
5539
5540 (void) printf(gettext("The following legacy versions are also "
5541 "supported:\n\n"));
5542 (void) printf(gettext("VER DESCRIPTION\n"));
5543 (void) printf("--- -----------------------------------------"
5544 "---------------\n");
5545 (void) printf(gettext(" 1 Initial ZFS version\n"));
5546 (void) printf(gettext(" 2 Ditto blocks "
5547 "(replicated metadata)\n"));
5548 (void) printf(gettext(" 3 Hot spares and double parity "
5549 "RAID-Z\n"));
5550 (void) printf(gettext(" 4 zpool history\n"));
5551 (void) printf(gettext(" 5 Compression using the gzip "
5552 "algorithm\n"));
5553 (void) printf(gettext(" 6 bootfs pool property\n"));
5554 (void) printf(gettext(" 7 Separate intent log devices\n"));
5555 (void) printf(gettext(" 8 Delegated administration\n"));
5556 (void) printf(gettext(" 9 refquota and refreservation "
5557 "properties\n"));
5558 (void) printf(gettext(" 10 Cache devices\n"));
5559 (void) printf(gettext(" 11 Improved scrub performance\n"));
5560 (void) printf(gettext(" 12 Snapshot properties\n"));
5561 (void) printf(gettext(" 13 snapused property\n"));
5562 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
5563 (void) printf(gettext(" 15 user/group space accounting\n"));
5564 (void) printf(gettext(" 16 stmf property support\n"));
5565 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
5566 (void) printf(gettext(" 18 Snapshot user holds\n"));
5567 (void) printf(gettext(" 19 Log device removal\n"));
5568 (void) printf(gettext(" 20 Compression using zle "
5569 "(zero-length encoding)\n"));
5570 (void) printf(gettext(" 21 Deduplication\n"));
5571 (void) printf(gettext(" 22 Received properties\n"));
5572 (void) printf(gettext(" 23 Slim ZIL\n"));
5573 (void) printf(gettext(" 24 System attributes\n"));
5574 (void) printf(gettext(" 25 Improved scrub stats\n"));
5575 (void) printf(gettext(" 26 Improved snapshot deletion "
5576 "performance\n"));
5577 (void) printf(gettext(" 27 Improved snapshot creation "
5578 "performance\n"));
5579 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
5580 (void) printf(gettext("\nFor more information on a particular "
5581 "version, including supported releases,\n"));
5582 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5583 } else if (argc == 0 && upgradeall) {
5584 cb.cb_first = B_TRUE;
5585 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5586 if (ret == 0 && cb.cb_first) {
5587 if (cb.cb_version == SPA_VERSION) {
5588 (void) printf(gettext("All pools are already "
5589 "formatted using feature flags.\n\n"));
5590 (void) printf(gettext("Every feature flags "
5591 "pool already has all supported features "
5592 "enabled.\n"));
5593 } else {
5594 (void) printf(gettext("All pools are already "
5595 "formatted with version %llu or higher.\n"),
5596 cb.cb_version);
5597 }
5598 }
5599 } else if (argc == 0) {
5600 cb.cb_first = B_TRUE;
5601 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5602 assert(ret == 0);
5603
5604 if (cb.cb_first) {
5605 (void) printf(gettext("All pools are formatted "
5606 "using feature flags.\n\n"));
5607 } else {
5608 (void) printf(gettext("\nUse 'zpool upgrade -v' "
5609 "for a list of available legacy versions.\n"));
5610 }
5611
5612 cb.cb_first = B_TRUE;
5613 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5614 assert(ret == 0);
5615
5616 if (cb.cb_first) {
5617 (void) printf(gettext("Every feature flags pool has "
5618 "all supported features enabled.\n"));
5619 } else {
5620 (void) printf(gettext("\n"));
5621 }
5622 } else {
5623 ret = for_each_pool(argc, argv, B_FALSE, NULL,
5624 upgrade_one, &cb);
5625 }
5626
5627 return (ret);
5628 }
5629
5630 typedef struct hist_cbdata {
5631 boolean_t first;
5632 boolean_t longfmt;
5633 boolean_t internal;
5634 } hist_cbdata_t;
5635
5636 /*
5637 * Print out the command history for a specific pool.
5638 */
5639 static int
5640 get_history_one(zpool_handle_t *zhp, void *data)
5641 {
5642 nvlist_t *nvhis;
5643 nvlist_t **records;
5644 uint_t numrecords;
5645 int ret, i;
5646 hist_cbdata_t *cb = (hist_cbdata_t *)data;
5647
5648 cb->first = B_FALSE;
5649
5650 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5651
5652 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5653 return (ret);
5654
5655 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5656 &records, &numrecords) == 0);
5657 for (i = 0; i < numrecords; i++) {
5658 nvlist_t *rec = records[i];
5659 char tbuf[30] = "";
5660
5661 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5662 time_t tsec;
5663 struct tm t;
5664
5665 tsec = fnvlist_lookup_uint64(records[i],
5666 ZPOOL_HIST_TIME);
5667 (void) localtime_r(&tsec, &t);
5668 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5669 }
5670
5671 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5672 (void) printf("%s %s", tbuf,
5673 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5674 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5675 int ievent =
5676 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5677 if (!cb->internal)
5678 continue;
5679 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5680 (void) printf("%s unrecognized record:\n",
5681 tbuf);
5682 dump_nvlist(rec, 4);
5683 continue;
5684 }
5685 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
5686 zfs_history_event_names[ievent],
5687 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5688 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5689 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5690 if (!cb->internal)
5691 continue;
5692 (void) printf("%s [txg:%lld] %s", tbuf,
5693 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5694 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5695 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5696 (void) printf(" %s (%llu)",
5697 fnvlist_lookup_string(rec,
5698 ZPOOL_HIST_DSNAME),
5699 fnvlist_lookup_uint64(rec,
5700 ZPOOL_HIST_DSID));
5701 }
5702 (void) printf(" %s", fnvlist_lookup_string(rec,
5703 ZPOOL_HIST_INT_STR));
5704 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5705 if (!cb->internal)
5706 continue;
5707 (void) printf("%s ioctl %s\n", tbuf,
5708 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5709 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5710 (void) printf(" input:\n");
5711 dump_nvlist(fnvlist_lookup_nvlist(rec,
5712 ZPOOL_HIST_INPUT_NVL), 8);
5713 }
5714 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5715 (void) printf(" output:\n");
5716 dump_nvlist(fnvlist_lookup_nvlist(rec,
5717 ZPOOL_HIST_OUTPUT_NVL), 8);
5718 }
5719 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5720 (void) printf(" errno: %lld\n",
5721 fnvlist_lookup_int64(rec,
5722 ZPOOL_HIST_ERRNO));
5723 }
5724 } else {
5725 if (!cb->internal)
5726 continue;
5727 (void) printf("%s unrecognized record:\n", tbuf);
5728 dump_nvlist(rec, 4);
5729 }
5730
5731 if (!cb->longfmt) {
5732 (void) printf("\n");
5733 continue;
5734 }
5735 (void) printf(" [");
5736 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5737 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5738 struct passwd *pwd = getpwuid(who);
5739 (void) printf("user %d ", (int)who);
5740 if (pwd != NULL)
5741 (void) printf("(%s) ", pwd->pw_name);
5742 }
5743 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5744 (void) printf("on %s",
5745 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5746 }
5747 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5748 (void) printf(":%s",
5749 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5750 }
5751 (void) printf("]");
5752 (void) printf("\n");
5753 }
5754 (void) printf("\n");
5755 nvlist_free(nvhis);
5756
5757 return (ret);
5758 }
5759
5760 /*
5761 * zpool history <pool>
5762 *
5763 * Displays the history of commands that modified pools.
5764 */
5765 int
5766 zpool_do_history(int argc, char **argv)
5767 {
5768 hist_cbdata_t cbdata = { 0 };
5769 int ret;
5770 int c;
5771
5772 cbdata.first = B_TRUE;
5773 /* check options */
5774 while ((c = getopt(argc, argv, "li")) != -1) {
5775 switch (c) {
5776 case 'l':
5777 cbdata.longfmt = B_TRUE;
5778 break;
5779 case 'i':
5780 cbdata.internal = B_TRUE;
5781 break;
5782 case '?':
5783 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5784 optopt);
5785 usage(B_FALSE);
5786 }
5787 }
5788 argc -= optind;
5789 argv += optind;
5790
5791 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
5792 &cbdata);
5793
5794 if (argc == 0 && cbdata.first == B_TRUE) {
5795 (void) printf(gettext("no pools available\n"));
5796 return (0);
5797 }
5798
5799 return (ret);
5800 }
5801
5802 static int
5803 get_callback(zpool_handle_t *zhp, void *data)
5804 {
5805 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5806 char value[MAXNAMELEN];
5807 zprop_source_t srctype;
5808 zprop_list_t *pl;
5809
5810 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5811
5812 /*
5813 * Skip the special fake placeholder. This will also skip
5814 * over the name property when 'all' is specified.
5815 */
5816 if (pl->pl_prop == ZPOOL_PROP_NAME &&
5817 pl == cbp->cb_proplist)
5818 continue;
5819
5820 if (pl->pl_prop == ZPROP_INVAL &&
5821 (zpool_prop_feature(pl->pl_user_prop) ||
5822 zpool_prop_unsupported(pl->pl_user_prop))) {
5823 srctype = ZPROP_SRC_LOCAL;
5824
5825 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5826 value, sizeof (value)) == 0) {
5827 zprop_print_one_property(zpool_get_name(zhp),
5828 cbp, pl->pl_user_prop, value, srctype,
5829 NULL, NULL);
5830 }
5831 } else {
5832 if (zpool_get_prop(zhp, pl->pl_prop, value,
5833 sizeof (value), &srctype, cbp->cb_literal) != 0)
5834 continue;
5835
5836 zprop_print_one_property(zpool_get_name(zhp), cbp,
5837 zpool_prop_to_name(pl->pl_prop), value, srctype,
5838 NULL, NULL);
5839 }
5840 }
5841 return (0);
5842 }
5843
5844 /*
5845 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5846 *
5847 * -H Scripted mode. Don't display headers, and separate properties
5848 * by a single tab.
5849 * -o List of columns to display. Defaults to
5850 * "name,property,value,source".
5851 * -p Diplay values in parsable (exact) format.
5852 *
5853 * Get properties of pools in the system. Output space statistics
5854 * for each one as well as other attributes.
5855 */
5856 int
5857 zpool_do_get(int argc, char **argv)
5858 {
5859 zprop_get_cbdata_t cb = { 0 };
5860 zprop_list_t fake_name = { 0 };
5861 int ret;
5862 int c, i;
5863 char *value;
5864
5865 cb.cb_first = B_TRUE;
5866
5867 /*
5868 * Set up default columns and sources.
5869 */
5870 cb.cb_sources = ZPROP_SRC_ALL;
5871 cb.cb_columns[0] = GET_COL_NAME;
5872 cb.cb_columns[1] = GET_COL_PROPERTY;
5873 cb.cb_columns[2] = GET_COL_VALUE;
5874 cb.cb_columns[3] = GET_COL_SOURCE;
5875 cb.cb_type = ZFS_TYPE_POOL;
5876
5877 /* check options */
5878 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5879 switch (c) {
5880 case 'p':
5881 cb.cb_literal = B_TRUE;
5882 break;
5883 case 'H':
5884 cb.cb_scripted = B_TRUE;
5885 break;
5886 case 'o':
5887 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5888 i = 0;
5889 while (*optarg != '\0') {
5890 static char *col_subopts[] =
5891 { "name", "property", "value", "source",
5892 "all", NULL };
5893
5894 if (i == ZFS_GET_NCOLS) {
5895 (void) fprintf(stderr, gettext("too "
5896 "many fields given to -o "
5897 "option\n"));
5898 usage(B_FALSE);
5899 }
5900
5901 switch (getsubopt(&optarg, col_subopts,
5902 &value)) {
5903 case 0:
5904 cb.cb_columns[i++] = GET_COL_NAME;
5905 break;
5906 case 1:
5907 cb.cb_columns[i++] = GET_COL_PROPERTY;
5908 break;
5909 case 2:
5910 cb.cb_columns[i++] = GET_COL_VALUE;
5911 break;
5912 case 3:
5913 cb.cb_columns[i++] = GET_COL_SOURCE;
5914 break;
5915 case 4:
5916 if (i > 0) {
5917 (void) fprintf(stderr,
5918 gettext("\"all\" conflicts "
5919 "with specific fields "
5920 "given to -o option\n"));
5921 usage(B_FALSE);
5922 }
5923 cb.cb_columns[0] = GET_COL_NAME;
5924 cb.cb_columns[1] = GET_COL_PROPERTY;
5925 cb.cb_columns[2] = GET_COL_VALUE;
5926 cb.cb_columns[3] = GET_COL_SOURCE;
5927 i = ZFS_GET_NCOLS;
5928 break;
5929 default:
5930 (void) fprintf(stderr,
5931 gettext("invalid column name "
5932 "'%s'\n"), value);
5933 usage(B_FALSE);
5934 }
5935 }
5936 break;
5937 case '?':
5938 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5939 optopt);
5940 usage(B_FALSE);
5941 }
5942 }
5943
5944 argc -= optind;
5945 argv += optind;
5946
5947 if (argc < 1) {
5948 (void) fprintf(stderr, gettext("missing property "
5949 "argument\n"));
5950 usage(B_FALSE);
5951 }
5952
5953 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5954 ZFS_TYPE_POOL) != 0)
5955 usage(B_FALSE);
5956
5957 argc--;
5958 argv++;
5959
5960 if (cb.cb_proplist != NULL) {
5961 fake_name.pl_prop = ZPOOL_PROP_NAME;
5962 fake_name.pl_width = strlen(gettext("NAME"));
5963 fake_name.pl_next = cb.cb_proplist;
5964 cb.cb_proplist = &fake_name;
5965 }
5966
5967 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5968 get_callback, &cb);
5969
5970 if (cb.cb_proplist == &fake_name)
5971 zprop_free_list(fake_name.pl_next);
5972 else
5973 zprop_free_list(cb.cb_proplist);
5974
5975 return (ret);
5976 }
5977
5978 typedef struct set_cbdata {
5979 nvlist_t *cb_nvl;
5980 boolean_t cb_any_successful;
5981 } set_cbdata_t;
5982
5983 int
5984 set_callback(zpool_handle_t *zhp, void *data)
5985 {
5986 int error;
5987 set_cbdata_t *cb = (set_cbdata_t *)data;
5988
5989 error = zpool_set_proplist(zhp, cb->cb_nvl);
5990 if (!error)
5991 cb->cb_any_successful = B_TRUE;
5992
5993 return (error);
5994 }
5995
5996 static void
5997 parse_props(char *propname, nvlist_t **nvl, zfs_type_t prop_type)
5998 {
5999 char *propval;
6000 char *delim;
6001 int err;
6002
6003 do {
6004 delim = strchr(propname, ',');
6005 if (delim != NULL)
6006 *delim++ = '\0';
6007
6008 propval = strchr(propname, '=');
6009 if (propval == NULL) {
6010 (void) fprintf(stderr, gettext("missing value "
6011 "in property=value argument\n"));
6012 if (*nvl != NULL)
6013 nvlist_free(*nvl);
6014 usage(B_FALSE);
6015 }
6016 *propval++ = '\0';
6017 switch (prop_type) {
6018 case ZFS_TYPE_VDEV:
6019 err = add_vdev_prop_list(propname, propval, nvl);
6020 break;
6021 case ZFS_TYPE_COS:
6022 err = add_cos_prop_list(propname, propval, nvl);
6023 break;
6024 default:
6025 err = add_prop_list(propname, propval, nvl, B_TRUE);
6026 }
6027
6028 if (err) {
6029 if (*nvl != NULL)
6030 nvlist_free(*nvl);
6031 usage(B_FALSE);
6032 }
6033
6034 propname = delim;
6035 } while (delim != NULL);
6036 }
6037
6038 int
6039 zpool_do_set(int argc, char **argv)
6040 {
6041 set_cbdata_t cb = { 0 };
6042 int error;
6043
6044 if (argc > 1 && argv[1][0] == '-') {
6045 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6046 argv[1][1]);
6047 usage(B_FALSE);
6048 }
6049
6050 if (argc < 2) {
6051 (void) fprintf(stderr, gettext("missing property=value "
6052 "argument\n"));
6053 usage(B_FALSE);
6054 }
6055
6056 if (argc < 3) {
6057 (void) fprintf(stderr, gettext("missing pool name\n"));
6058 usage(B_FALSE);
6059 }
6060
6061 if (argc > 3) {
6062 (void) fprintf(stderr, gettext("too many pool names\n"));
6063 usage(B_FALSE);
6064 }
6065
6066 parse_props(argv[1], &cb.cb_nvl, ZFS_TYPE_POOL);
6067
6068 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6069 set_callback, &cb);
6070
6071 return (error);
6072 }
6073
6074 typedef struct vdev_cbdata {
6075 char *vcb_vdev;
6076 nvlist_t *vcb_nvl; /* values */
6077 boolean_t vcb_any_successful;
6078 } vdev_cbdata_t;
6079
6080 typedef struct vdev_get_cbdata {
6081 zprop_get_cbdata_t vcb_zprop_get_cbdata;
6082 char *vcb_vdev;
6083 nvlist_t *vcb_nvl; /* values */
6084 boolean_t vcb_any_successful;
6085 } vdev_get_cbdata_t;
6086
6087 static int
6088 vdev_get_callback(zpool_handle_t *zhp, void *data)
6089 {
6090 int err;
6091 boolean_t l2cache, avail_space;
6092 vdev_get_cbdata_t *vcb = (vdev_get_cbdata_t *)data;
6093 zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6094 char value[MAXNAMELEN];
6095 zprop_list_t *pl;
6096
6097 (void) zpool_find_vdev(zhp, vcb->vcb_vdev, &avail_space,
6098 &l2cache, NULL, NULL);
6099 for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6100 if ((err = vdev_get_prop(zhp, vcb->vcb_vdev,
6101 pl->pl_prop, value, sizeof (value))) != 0)
6102 return (err);
6103
6104 /* don't show L2ARC prop for non L2ARC dev, can't set anyway */
6105 if (!l2cache && pl->pl_prop == VDEV_PROP_L2ADDDT)
6106 continue;
6107 vdev_print_one_property(zpool_get_name(zhp), vcb->vcb_vdev, cb,
6108 vdev_prop_to_name(pl->pl_prop), value);
6109 }
6110
6111 return (0);
6112 }
6113
6114
6115 int
6116 zpool_do_vdev_get(int argc, char **argv)
6117 {
6118 vdev_get_cbdata_t vcb = { 0 };
6119 zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6120 int error;
6121
6122 if (argc > 1 && argv[1][0] == '-') {
6123 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6124 argv[1][1]);
6125 usage(B_FALSE);
6126 }
6127
6128 if (argc < 2) {
6129 (void) fprintf(stderr, gettext("missing property name\n"));
6130 usage(B_FALSE);
6131 }
6132
6133 if (argc < 3) {
6134 (void) fprintf(stderr, gettext("missing pool name\n"));
6135 usage(B_FALSE);
6136 }
6137
6138 if (argc < 4) {
6139 (void) fprintf(stderr,
6140 gettext("at least one vdev name or guid is required\n"));
6141 usage(B_FALSE);
6142 }
6143
6144 cb->cb_first = B_TRUE;
6145 cb->cb_sources = ZPROP_SRC_ALL;
6146 cb->cb_columns[0] = GET_COL_NAME;
6147 cb->cb_columns[1] = GET_COL_SOURCE;
6148 cb->cb_columns[2] = GET_COL_PROPERTY;
6149 cb->cb_columns[3] = GET_COL_VALUE;
6150 cb->cb_type = ZFS_TYPE_VDEV;
6151
6152 if (vdev_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6153 usage(B_FALSE);
6154
6155 vcb.vcb_vdev = argv[3];
6156 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6157 vdev_get_callback, &vcb);
6158
6159 zprop_free_list(cb->cb_proplist);
6160
6161 return (error);
6162 }
6163
6164 int
6165 vdev_set_callback(zpool_handle_t *zhp, void *data)
6166 {
6167 int error;
6168 vdev_cbdata_t *cb = (vdev_cbdata_t *)data;
6169
6170 error = vdev_set_proplist(zhp, cb->vcb_vdev, cb->vcb_nvl);
6171 if (!error)
6172 cb->vcb_any_successful = B_TRUE;
6173
6174 return (error);
6175 }
6176
6177 int
6178 zpool_do_vdev_set(int argc, char **argv)
6179 {
6180 vdev_cbdata_t cb = { 0 };
6181 int error;
6182
6183 if (argc > 1 && argv[1][0] == '-') {
6184 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6185 argv[1][1]);
6186 usage(B_FALSE);
6187 }
6188
6189 if (argc < 2) {
6190 (void) fprintf(stderr, gettext("missing property=value "
6191 "argument\n"));
6192 usage(B_FALSE);
6193 }
6194
6195 if (argc < 3) {
6196 (void) fprintf(stderr, gettext("missing pool name\n"));
6197 usage(B_FALSE);
6198 }
6199
6200 if (argc < 4) {
6201 (void) fprintf(stderr,
6202 gettext("at least one vdev name or guid is required\n"));
6203 usage(B_FALSE);
6204 }
6205
6206 parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_VDEV);
6207
6208 cb.vcb_vdev = argv[3];
6209 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6210 vdev_set_callback, &cb);
6211
6212 return (error);
6213 }
6214
6215 typedef struct cos_af_cbdata {
6216 char *cb_cos;
6217 uint64_t cb_guid;
6218 boolean_t cb_alloc;
6219 boolean_t cb_any_successful;
6220 boolean_t cb_force;
6221 nvlist_t *cb_nvl;
6222 } cos_af_cbdata_t;
6223
6224 int
6225 cos_alloc_callback(zpool_handle_t *zhp, void *data)
6226 {
6227 int error;
6228 cos_af_cbdata_t *cb = (cos_af_cbdata_t *)data;
6229
6230 if (cb->cb_alloc)
6231 error = cos_alloc(zhp, cb->cb_cos, cb->cb_nvl);
6232 else
6233 error = cos_free(zhp, cb->cb_cos, cb->cb_guid, cb->cb_force);
6234 if (!error)
6235 cb->cb_any_successful = B_TRUE;
6236
6237 if (error == ENOTSUP) {
6238 (void) fprintf(stderr, gettext("operation failed: "
6239 "CoS feature is disabled.\n"));
6240 }
6241
6242 return (error);
6243 }
6244
6245 int
6246 zpool_do_cos_alloc(int argc, char **argv)
6247 {
6248 nvlist_t *nvl;
6249 cos_af_cbdata_t cb = { 0 };
6250 int error;
6251
6252 if (!nexenta_meta_enable())
6253 return (-1);
6254
6255 if (argc < 2) {
6256 (void) fprintf(stderr, gettext("missing pool name\n"));
6257 usage(B_FALSE);
6258 }
6259
6260 if (argc < 3) {
6261 (void) fprintf(stderr,
6262 gettext("at least one cos name or id is required\n"));
6263 usage(B_FALSE);
6264 }
6265
6266 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6267 (void) fprintf(stderr,
6268 gettext("internal error: out of memory\n"));
6269 return (1);
6270 }
6271
6272 cb.cb_cos = argv[2];
6273 cb.cb_alloc = B_TRUE;
6274 cb.cb_nvl = nvl;
6275 error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6276 cos_alloc_callback, &cb);
6277
6278 nvlist_free(nvl);
6279
6280 return (error);
6281 }
6282
6283 int
6284 zpool_do_cos_free(int argc, char **argv)
6285 {
6286 cos_af_cbdata_t cb = { 0 };
6287 char *endp;
6288 int error;
6289
6290 if (!nexenta_meta_enable())
6291 return (-1);
6292
6293 if (argc > 1 && strncmp(argv[1], "-f", sizeof ("-f")) == 0) {
6294 /* -f - force option */
6295 cb.cb_force = B_TRUE;
6296 argc--;
6297 argv++;
6298 }
6299
6300 if (argc < 2) {
6301 (void) fprintf(stderr, gettext("missing pool name\n"));
6302 usage(B_FALSE);
6303 }
6304
6305 if (argc < 3) {
6306 (void) fprintf(stderr,
6307 gettext("at least one cos name or id is required\n"));
6308 usage(B_FALSE);
6309 }
6310
6311 cb.cb_guid = strtoll(argv[2], &endp, 10);
6312 if (endp < argv[2] + strlen(argv[2])) {
6313 cb.cb_guid = 0;
6314 }
6315
6316 if (cb.cb_guid == 0)
6317 cb.cb_cos = argv[2];
6318 else
6319 cb.cb_cos = "";
6320
6321 error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6322 cos_alloc_callback, &cb);
6323
6324 return (error);
6325 }
6326
6327
6328 static int
6329 cos_list_callback(zpool_handle_t *zhp, void *data)
6330 {
6331 int err, i;
6332 nvlist_t *nvl = (nvlist_t *)data;
6333 nvpair_t *nvp;
6334
6335 if ((err = cos_list(zhp, &nvl)) == 0) {
6336 (void) printf("%-*s %s\n", MAXCOSNAMELEN, gettext("COSNAME"),
6337 gettext("COSID"));
6338 for (i = 0, nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
6339 nvp = nvlist_next_nvpair(nvl, nvp), i++) {
6340 uint64_t cosid;
6341 char *cosname = nvpair_name(nvp);
6342 if (nvpair_value_uint64(nvp, &cosid) == 0)
6343 (void) printf("%-*s %llu\n", MAXCOSNAMELEN,
6344 cosname, cosid);
6345 }
6346
6347 if (!i)
6348 (void) printf("%s\n", gettext("<no classes found>"));
6349 }
6350 return (err);
6351 }
6352
6353 int
6354 zpool_do_cos_list(int argc, char **argv)
6355 {
6356 nvlist_t *nvl;
6357 int error;
6358
6359 if (!nexenta_meta_enable())
6360 return (-1);
6361
6362 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6363 (void) fprintf(stderr,
6364 gettext("internal error: out of memory\n"));
6365 return (1);
6366 }
6367
6368 if (argc < 2) {
6369 (void) fprintf(stderr, gettext("missing pool name\n"));
6370 usage(B_FALSE);
6371 }
6372
6373 error = for_each_pool(1, argv+1, B_TRUE, NULL,
6374 cos_list_callback, nvl);
6375
6376 nvlist_free(nvl);
6377
6378 return (error);
6379
6380 }
6381
6382 typedef struct cos_cbdata {
6383 char *vcb_cos;
6384 nvlist_t *vcb_nvl; /* values */
6385 boolean_t vcb_any_successful;
6386 } cos_cbdata_t;
6387
6388 typedef struct cos_get_cbdata {
6389 zprop_get_cbdata_t vcb_zprop_get_cbdata;
6390 char *vcb_cos;
6391 nvlist_t *vcb_nvl; /* values */
6392 boolean_t vcb_any_successful;
6393 } cos_get_cbdata_t;
6394
6395 static int
6396 cos_get_callback(zpool_handle_t *zhp, void *data)
6397 {
6398 int err;
6399 cos_get_cbdata_t *vcb = (cos_get_cbdata_t *)data;
6400 zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6401 char value[MAXNAMELEN];
6402 zprop_list_t *pl;
6403 nvlist_t *nvl = NULL;
6404
6405 for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6406 if ((err = cos_get_prop(zhp, vcb->vcb_cos,
6407 pl->pl_prop, value, sizeof (value), &nvl)) != 0)
6408 return (err);
6409
6410 cos_print_one_property(zpool_get_name(zhp), vcb->vcb_cos, cb,
6411 cos_prop_to_name(pl->pl_prop), value);
6412 }
6413
6414 return (0);
6415 }
6416
6417
6418 int
6419 zpool_do_cos_get(int argc, char **argv)
6420 {
6421 cos_get_cbdata_t vcb = { 0 };
6422 zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6423 int error;
6424
6425 if (!nexenta_meta_enable())
6426 return (-1);
6427
6428 if (argc > 1 && argv[1][0] == '-') {
6429 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6430 argv[1][1]);
6431 usage(B_FALSE);
6432 }
6433
6434 if (argc < 2) {
6435 (void) fprintf(stderr, gettext("missing property name\n"));
6436 usage(B_FALSE);
6437 }
6438
6439 if (argc < 3) {
6440 (void) fprintf(stderr, gettext("missing pool name\n"));
6441 usage(B_FALSE);
6442 }
6443
6444 if (argc < 4) {
6445 (void) fprintf(stderr,
6446 gettext("at least one cos name or guid is required\n"));
6447 usage(B_FALSE);
6448 }
6449
6450 cb->cb_first = B_TRUE;
6451 cb->cb_sources = ZPROP_SRC_ALL;
6452 cb->cb_columns[0] = GET_COL_NAME;
6453 cb->cb_columns[1] = GET_COL_SOURCE;
6454 cb->cb_columns[2] = GET_COL_PROPERTY;
6455 cb->cb_columns[3] = GET_COL_VALUE;
6456 cb->cb_type = ZFS_TYPE_COS;
6457
6458 if (cos_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6459 usage(B_FALSE);
6460
6461 vcb.vcb_cos = argv[3];
6462 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6463 cos_get_callback, &vcb);
6464
6465 zprop_free_list(cb->cb_proplist);
6466
6467 return (error);
6468
6469 }
6470
6471 int
6472 cos_set_callback(zpool_handle_t *zhp, void *data)
6473 {
6474 int error;
6475 cos_cbdata_t *cb = (cos_cbdata_t *)data;
6476
6477 error = cos_set_proplist(zhp, cb->vcb_cos, cb->vcb_nvl);
6478 if (!error)
6479 cb->vcb_any_successful = B_TRUE;
6480
6481 return (error);
6482 }
6483
6484 int
6485 zpool_do_cos_set(int argc, char **argv)
6486 {
6487 cos_cbdata_t cb = { 0 };
6488 int error;
6489
6490 if (!nexenta_meta_enable())
6491 return (-1);
6492
6493 if (argc > 1 && argv[1][0] == '-') {
6494 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6495 argv[1][1]);
6496 usage(B_FALSE);
6497 }
6498
6499 if (argc < 2) {
6500 (void) fprintf(stderr, gettext("missing property=value "
6501 "argument\n"));
6502 usage(B_FALSE);
6503 }
6504
6505 if (argc < 3) {
6506 (void) fprintf(stderr, gettext("missing pool name\n"));
6507 usage(B_FALSE);
6508 }
6509
6510 if (argc < 4) {
6511 (void) fprintf(stderr,
6512 gettext("at least one cos name or id is required\n"));
6513 usage(B_FALSE);
6514 }
6515
6516 parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_COS);
6517
6518 cb.vcb_cos = argv[3];
6519 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6520 cos_set_callback, &cb);
6521
6522 return (error);
6523 }
6524
6525 static int
6526 find_command_idx(char *command, int *idx)
6527 {
6528 int i;
6529
6530 for (i = 0; i < NCOMMAND; i++) {
6531 if (command_table[i].name == NULL)
6532 continue;
6533
6534 if (strcmp(command, command_table[i].name) == 0) {
6535 *idx = i;
6536 return (0);
6537 }
6538 }
6539 return (1);
6540 }
6541
6542 int
6543 main(int argc, char **argv)
6544 {
6545 int ret = 0;
6546 int i;
6547 char *cmdname;
6548
6549 (void) setlocale(LC_ALL, "");
6550 (void) textdomain(TEXT_DOMAIN);
6551
6552 if ((g_zfs = libzfs_init()) == NULL) {
6553 (void) fprintf(stderr, gettext("internal error: failed to "
6554 "initialize ZFS library\n"));
6555 return (1);
6556 }
6557
6558 libzfs_print_on_error(g_zfs, B_TRUE);
6559
6560 opterr = 0;
6561
6562 /*
6563 * Make sure the user has specified some command.
6564 */
6565 if (argc < 2) {
6566 (void) fprintf(stderr, gettext("missing command\n"));
6567 usage(B_FALSE);
6568 }
6569
6570 cmdname = argv[1];
6571
6572 /*
6573 * Special case '-?'
6574 */
6575 if (strcmp(cmdname, "-?") == 0)
6576 usage(B_TRUE);
6577
6578 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6579 verify(zpool_stage_history(g_zfs, history_str) == 0);
6580
6581 /*
6582 * Run the appropriate command.
6583 */
6584 if (find_command_idx(cmdname, &i) == 0) {
6585 current_command = &command_table[i];
6586 ret = command_table[i].func(argc - 1, argv + 1);
6587 } else if (strchr(cmdname, '=')) {
6588 verify(find_command_idx("set", &i) == 0);
6589 current_command = &command_table[i];
6590 ret = command_table[i].func(argc, argv);
6591 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6592 /*
6593 * 'freeze' is a vile debugging abomination, so we treat
6594 * it as such.
6595 */
6596 char buf[16384];
6597 int fd = open(ZFS_DEV, O_RDWR);
6598 (void) strcpy((void *)buf, argv[2]);
6599 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
6600 } else {
6601 (void) fprintf(stderr, gettext("unrecognized "
6602 "command '%s'\n"), cmdname);
6603 usage(B_FALSE);
6604 }
6605
6606 if (ret == 0 && log_history)
6607 (void) zpool_log_history(g_zfs, history_str);
6608
6609 libzfs_fini(g_zfs);
6610
6611 /*
6612 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
6613 * for the purposes of running ::findleaks.
6614 */
6615 if (getenv("ZFS_ABORT") != NULL) {
6616 (void) printf("dumping core by request\n");
6617 abort();
6618 }
6619
6620 return (ret);
6621 }