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 2011 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
27 */
28
29 #include <assert.h>
30 #include <ctype.h>
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <libgen.h>
35 #include <libintl.h>
36 #include <libuutil.h>
37 #include <locale.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <priv.h>
44 #include <pwd.h>
45 #include <zone.h>
46 #include <zfs_prop.h>
47 #include <sys/fs/zfs.h>
48 #include <sys/stat.h>
49
50 #include <libzfs.h>
51
52 #include "zpool_util.h"
53 #include "zfs_comutil.h"
54 #include "zfeature_common.h"
55
56 #include "statcommon.h"
57
58 static int zpool_do_create(int, char **);
59 static int zpool_do_destroy(int, char **);
60
61 static int zpool_do_add(int, char **);
62 static int zpool_do_remove(int, char **);
63
64 static int zpool_do_list(int, char **);
65 static int zpool_do_iostat(int, char **);
66 static int zpool_do_status(int, char **);
67
68 static int zpool_do_online(int, char **);
69 static int zpool_do_offline(int, char **);
70 static int zpool_do_clear(int, char **);
71 static int zpool_do_reopen(int, char **);
72
73 static int zpool_do_reguid(int, char **);
74
75 static int zpool_do_attach(int, char **);
76 static int zpool_do_detach(int, char **);
77 static int zpool_do_replace(int, char **);
78 static int zpool_do_split(int, char **);
79
80 static int zpool_do_scrub(int, char **);
81
82 static int zpool_do_import(int, char **);
83 static int zpool_do_export(int, char **);
84
85 static int zpool_do_upgrade(int, char **);
86
87 static int zpool_do_history(int, char **);
88
89 static int zpool_do_get(int, char **);
90 static int zpool_do_set(int, char **);
91
92 /*
93 * These libumem hooks provide a reasonable set of defaults for the allocator's
94 * debugging facilities.
95 */
96
97 #ifdef DEBUG
98 const char *
99 _umem_debug_init(void)
100 {
101 return ("default,verbose"); /* $UMEM_DEBUG setting */
102 }
103
104 const char *
105 _umem_logging_init(void)
106 {
107 return ("fail,contents"); /* $UMEM_LOGGING setting */
108 }
109 #endif
110
111 typedef enum {
112 HELP_ADD,
113 HELP_ATTACH,
114 HELP_CLEAR,
115 HELP_CREATE,
116 HELP_DESTROY,
117 HELP_DETACH,
118 HELP_EXPORT,
119 HELP_HISTORY,
120 HELP_IMPORT,
121 HELP_IOSTAT,
122 HELP_LIST,
123 HELP_OFFLINE,
124 HELP_ONLINE,
125 HELP_REPLACE,
126 HELP_REMOVE,
127 HELP_SCRUB,
128 HELP_STATUS,
129 HELP_UPGRADE,
130 HELP_GET,
131 HELP_SET,
132 HELP_SPLIT,
133 HELP_REGUID,
134 HELP_REOPEN
135 } zpool_help_t;
136
137
138 typedef struct zpool_command {
139 const char *name;
140 int (*func)(int, char **);
141 zpool_help_t usage;
142 } zpool_command_t;
143
144 /*
145 * Master command table. Each ZFS command has a name, associated function, and
146 * usage message. The usage messages need to be internationalized, so we have
147 * to have a function to return the usage message based on a command index.
148 *
149 * These commands are organized according to how they are displayed in the usage
150 * message. An empty command (one with a NULL name) indicates an empty line in
151 * the generic usage message.
152 */
153 static zpool_command_t command_table[] = {
154 { "create", zpool_do_create, HELP_CREATE },
155 { "destroy", zpool_do_destroy, HELP_DESTROY },
156 { NULL },
157 { "add", zpool_do_add, HELP_ADD },
158 { "remove", zpool_do_remove, HELP_REMOVE },
159 { NULL },
160 { "list", zpool_do_list, HELP_LIST },
161 { "iostat", zpool_do_iostat, HELP_IOSTAT },
162 { "status", zpool_do_status, HELP_STATUS },
163 { NULL },
164 { "online", zpool_do_online, HELP_ONLINE },
165 { "offline", zpool_do_offline, HELP_OFFLINE },
166 { "clear", zpool_do_clear, HELP_CLEAR },
167 { "reopen", zpool_do_reopen, HELP_REOPEN },
168 { NULL },
169 { "attach", zpool_do_attach, HELP_ATTACH },
170 { "detach", zpool_do_detach, HELP_DETACH },
171 { "replace", zpool_do_replace, HELP_REPLACE },
172 { "split", zpool_do_split, HELP_SPLIT },
173 { NULL },
174 { "scrub", zpool_do_scrub, HELP_SCRUB },
175 { NULL },
176 { "import", zpool_do_import, HELP_IMPORT },
177 { "export", zpool_do_export, HELP_EXPORT },
178 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
179 { "reguid", zpool_do_reguid, HELP_REGUID },
180 { NULL },
181 { "history", zpool_do_history, HELP_HISTORY },
182 { "get", zpool_do_get, HELP_GET },
183 { "set", zpool_do_set, HELP_SET },
184 };
185
186 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
187
188 static zpool_command_t *current_command;
189 static char history_str[HIS_MAX_RECORD_LEN];
190 static boolean_t log_history = B_TRUE;
191 static uint_t timestamp_fmt = NODATE;
192
193 static const char *
194 get_usage(zpool_help_t idx) {
195 switch (idx) {
196 case HELP_ADD:
197 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
198 case HELP_ATTACH:
199 return (gettext("\tattach [-f] <pool> <device> "
200 "<new-device>\n"));
201 case HELP_CLEAR:
202 return (gettext("\tclear [-nF] <pool> [device]\n"));
203 case HELP_CREATE:
204 return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
205 "\t [-O file-system-property=value] ... \n"
206 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
207 case HELP_DESTROY:
208 return (gettext("\tdestroy [-f] <pool>\n"));
209 case HELP_DETACH:
210 return (gettext("\tdetach <pool> <device>\n"));
211 case HELP_EXPORT:
212 return (gettext("\texport [-f] <pool> ...\n"));
213 case HELP_HISTORY:
214 return (gettext("\thistory [-il] [<pool>] ...\n"));
215 case HELP_IMPORT:
216 return (gettext("\timport [-d dir] [-D]\n"
217 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
218 "\timport [-o mntopts] [-o property=value] ... \n"
219 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
220 "[-R root] [-F [-n]] -a\n"
221 "\timport [-o mntopts] [-o property=value] ... \n"
222 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
223 "[-R root] [-F [-n]]\n"
224 "\t <pool | id> [newpool]\n"));
225 case HELP_IOSTAT:
226 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
227 "[count]]\n"));
228 case HELP_LIST:
229 return (gettext("\tlist [-H] [-o property[,...]] "
230 "[-T d|u] [pool] ... [interval [count]]\n"));
231 case HELP_OFFLINE:
232 return (gettext("\toffline [-t] <pool> <device> ...\n"));
233 case HELP_ONLINE:
234 return (gettext("\tonline <pool> <device> ...\n"));
235 case HELP_REPLACE:
236 return (gettext("\treplace [-f] <pool> <device> "
237 "[new-device]\n"));
238 case HELP_REMOVE:
239 return (gettext("\tremove <pool> <device> ...\n"));
240 case HELP_REOPEN:
241 return (gettext("\treopen <pool>\n"));
242 case HELP_SCRUB:
243 return (gettext("\tscrub [-s] <pool> ...\n"));
244 case HELP_STATUS:
245 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
246 "[count]]\n"));
247 case HELP_UPGRADE:
248 return (gettext("\tupgrade\n"
249 "\tupgrade -v\n"
250 "\tupgrade [-V version] <-a | pool ...>\n"));
251 case HELP_GET:
252 return (gettext("\tget <\"all\" | property[,...]> "
253 "<pool> ...\n"));
254 case HELP_SET:
255 return (gettext("\tset <property=value> <pool> \n"));
256 case HELP_SPLIT:
257 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
258 "\t [-o property=value] <pool> <newpool> "
259 "[<device> ...]\n"));
260 case HELP_REGUID:
261 return (gettext("\treguid <pool>\n"));
262 }
263
264 abort();
265 /* NOTREACHED */
266 }
267
268
269 /*
270 * Callback routine that will print out a pool property value.
271 */
272 static int
273 print_prop_cb(int prop, void *cb)
274 {
275 FILE *fp = cb;
276
277 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
278
279 if (zpool_prop_readonly(prop))
280 (void) fprintf(fp, " NO ");
281 else
282 (void) fprintf(fp, " YES ");
283
284 if (zpool_prop_values(prop) == NULL)
285 (void) fprintf(fp, "-\n");
286 else
287 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
288
289 return (ZPROP_CONT);
290 }
291
292 /*
293 * Display usage message. If we're inside a command, display only the usage for
294 * that command. Otherwise, iterate over the entire command table and display
295 * a complete usage message.
296 */
297 void
298 usage(boolean_t requested)
299 {
300 FILE *fp = requested ? stdout : stderr;
301
302 if (current_command == NULL) {
303 int i;
304
305 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
306 (void) fprintf(fp,
307 gettext("where 'command' is one of the following:\n\n"));
308
309 for (i = 0; i < NCOMMAND; i++) {
310 if (command_table[i].name == NULL)
311 (void) fprintf(fp, "\n");
312 else
313 (void) fprintf(fp, "%s",
314 get_usage(command_table[i].usage));
315 }
316 } else {
317 (void) fprintf(fp, gettext("usage:\n"));
318 (void) fprintf(fp, "%s", get_usage(current_command->usage));
319 }
320
321 if (current_command != NULL &&
322 ((strcmp(current_command->name, "set") == 0) ||
323 (strcmp(current_command->name, "get") == 0) ||
324 (strcmp(current_command->name, "list") == 0))) {
325
326 (void) fprintf(fp,
327 gettext("\nthe following properties are supported:\n"));
328
329 (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
330 "PROPERTY", "EDIT", "VALUES");
331
332 /* Iterate over all properties */
333 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
334 ZFS_TYPE_POOL);
335
336 (void) fprintf(fp, "\t%-15s ", "feature@...");
337 (void) fprintf(fp, "YES disabled | enabled | active\n");
338
339 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
340 "appended with a feature name.\nSee zpool-features(5).\n"));
341 }
342
343 /*
344 * See comments at end of main().
345 */
346 if (getenv("ZFS_ABORT") != NULL) {
347 (void) printf("dumping core by request\n");
348 abort();
349 }
350
351 exit(requested ? 0 : 2);
352 }
353
354 void
355 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
356 boolean_t print_logs)
357 {
358 nvlist_t **child;
359 uint_t c, children;
360 char *vname;
361
362 if (name != NULL)
363 (void) printf("\t%*s%s\n", indent, "", name);
364
365 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
366 &child, &children) != 0)
367 return;
368
369 for (c = 0; c < children; c++) {
370 uint64_t is_log = B_FALSE;
371
372 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
373 &is_log);
374 if ((is_log && !print_logs) || (!is_log && print_logs))
375 continue;
376
377 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
378 print_vdev_tree(zhp, vname, child[c], indent + 2,
379 B_FALSE);
380 free(vname);
381 }
382 }
383
384 static boolean_t
385 prop_list_contains_feature(nvlist_t *proplist)
386 {
387 nvpair_t *nvp;
388 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
389 nvp = nvlist_next_nvpair(proplist, nvp)) {
390 if (zpool_prop_feature(nvpair_name(nvp)))
391 return (B_TRUE);
392 }
393 return (B_FALSE);
394 }
395
396 /*
397 * Add a property pair (name, string-value) into a property nvlist.
398 */
399 static int
400 add_prop_list(const char *propname, char *propval, nvlist_t **props,
401 boolean_t poolprop)
402 {
403 zpool_prop_t prop = ZPROP_INVAL;
404 zfs_prop_t fprop;
405 nvlist_t *proplist;
406 const char *normnm;
407 char *strval;
408
409 if (*props == NULL &&
410 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
411 (void) fprintf(stderr,
412 gettext("internal error: out of memory\n"));
413 return (1);
414 }
415
416 proplist = *props;
417
418 if (poolprop) {
419 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
420
421 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
422 !zpool_prop_feature(propname)) {
423 (void) fprintf(stderr, gettext("property '%s' is "
424 "not a valid pool property\n"), propname);
425 return (2);
426 }
427
428 /*
429 * feature@ properties and version should not be specified
430 * at the same time.
431 */
432 if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
433 nvlist_exists(proplist, vname)) ||
434 (prop == ZPOOL_PROP_VERSION &&
435 prop_list_contains_feature(proplist))) {
436 (void) fprintf(stderr, gettext("'feature@' and "
437 "'version' properties cannot be specified "
438 "together\n"));
439 return (2);
440 }
441
442
443 if (zpool_prop_feature(propname))
444 normnm = propname;
445 else
446 normnm = zpool_prop_to_name(prop);
447 } else {
448 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
449 normnm = zfs_prop_to_name(fprop);
450 } else {
451 normnm = propname;
452 }
453 }
454
455 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
456 prop != ZPOOL_PROP_CACHEFILE) {
457 (void) fprintf(stderr, gettext("property '%s' "
458 "specified multiple times\n"), propname);
459 return (2);
460 }
461
462 if (nvlist_add_string(proplist, normnm, propval) != 0) {
463 (void) fprintf(stderr, gettext("internal "
464 "error: out of memory\n"));
465 return (1);
466 }
467
468 return (0);
469 }
470
471 /*
472 * zpool add [-fn] <pool> <vdev> ...
473 *
474 * -f Force addition of devices, even if they appear in use
475 * -n Do not add the devices, but display the resulting layout if
476 * they were to be added.
477 *
478 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
479 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
480 * libzfs.
481 */
482 int
483 zpool_do_add(int argc, char **argv)
484 {
485 boolean_t force = B_FALSE;
486 boolean_t dryrun = B_FALSE;
487 int c;
488 nvlist_t *nvroot;
489 char *poolname;
490 int ret;
491 zpool_handle_t *zhp;
492 nvlist_t *config;
493
494 /* check options */
495 while ((c = getopt(argc, argv, "fn")) != -1) {
496 switch (c) {
497 case 'f':
498 force = B_TRUE;
499 break;
500 case 'n':
501 dryrun = B_TRUE;
502 break;
503 case '?':
504 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
505 optopt);
506 usage(B_FALSE);
507 }
508 }
509
510 argc -= optind;
511 argv += optind;
512
513 /* get pool name and check number of arguments */
514 if (argc < 1) {
515 (void) fprintf(stderr, gettext("missing pool name argument\n"));
516 usage(B_FALSE);
517 }
518 if (argc < 2) {
519 (void) fprintf(stderr, gettext("missing vdev specification\n"));
520 usage(B_FALSE);
521 }
522
523 poolname = argv[0];
524
525 argc--;
526 argv++;
527
528 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
529 return (1);
530
531 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
532 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
533 poolname);
534 zpool_close(zhp);
535 return (1);
536 }
537
538 /* pass off to get_vdev_spec for processing */
539 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
540 argc, argv);
541 if (nvroot == NULL) {
542 zpool_close(zhp);
543 return (1);
544 }
545
546 if (dryrun) {
547 nvlist_t *poolnvroot;
548
549 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
550 &poolnvroot) == 0);
551
552 (void) printf(gettext("would update '%s' to the following "
553 "configuration:\n"), zpool_get_name(zhp));
554
555 /* print original main pool and new tree */
556 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
557 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
558
559 /* Do the same for the logs */
560 if (num_logs(poolnvroot) > 0) {
561 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
562 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
563 } else if (num_logs(nvroot) > 0) {
564 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
565 }
566
567 ret = 0;
568 } else {
569 ret = (zpool_add(zhp, nvroot) != 0);
570 }
571
572 nvlist_free(nvroot);
573 zpool_close(zhp);
574
575 return (ret);
576 }
577
578 /*
579 * zpool remove <pool> <vdev> ...
580 *
581 * Removes the given vdev from the pool. Currently, this supports removing
582 * spares, cache, and log devices from the pool.
583 */
584 int
585 zpool_do_remove(int argc, char **argv)
586 {
587 char *poolname;
588 int i, ret = 0;
589 zpool_handle_t *zhp;
590
591 argc--;
592 argv++;
593
594 /* get pool name and check number of arguments */
595 if (argc < 1) {
596 (void) fprintf(stderr, gettext("missing pool name argument\n"));
597 usage(B_FALSE);
598 }
599 if (argc < 2) {
600 (void) fprintf(stderr, gettext("missing device\n"));
601 usage(B_FALSE);
602 }
603
604 poolname = argv[0];
605
606 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
607 return (1);
608
609 for (i = 1; i < argc; i++) {
610 if (zpool_vdev_remove(zhp, argv[i]) != 0)
611 ret = 1;
612 }
613
614 return (ret);
615 }
616
617 /*
618 * zpool create [-fnd] [-o property=value] ...
619 * [-O file-system-property=value] ...
620 * [-R root] [-m mountpoint] <pool> <dev> ...
621 *
622 * -f Force creation, even if devices appear in use
623 * -n Do not create the pool, but display the resulting layout if it
624 * were to be created.
625 * -R Create a pool under an alternate root
626 * -m Set default mountpoint for the root dataset. By default it's
627 * '/<pool>'
628 * -o Set property=value.
629 * -d Don't automatically enable all supported pool features
630 * (individual features can be enabled with -o).
631 * -O Set fsproperty=value in the pool's root file system
632 *
633 * Creates the named pool according to the given vdev specification. The
634 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
635 * we get the nvlist back from get_vdev_spec(), we either print out the contents
636 * (if '-n' was specified), or pass it to libzfs to do the creation.
637 */
638 int
639 zpool_do_create(int argc, char **argv)
640 {
641 boolean_t force = B_FALSE;
642 boolean_t dryrun = B_FALSE;
643 boolean_t enable_all_pool_feat = B_TRUE;
644 int c;
645 nvlist_t *nvroot = NULL;
646 char *poolname;
647 int ret = 1;
648 char *altroot = NULL;
649 char *mountpoint = NULL;
650 nvlist_t *fsprops = NULL;
651 nvlist_t *props = NULL;
652 char *propval;
653
654 /* check options */
655 while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) {
656 switch (c) {
657 case 'f':
658 force = B_TRUE;
659 break;
660 case 'n':
661 dryrun = B_TRUE;
662 break;
663 case 'd':
664 enable_all_pool_feat = B_FALSE;
665 break;
666 case 'R':
667 altroot = optarg;
668 if (add_prop_list(zpool_prop_to_name(
669 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
670 goto errout;
671 if (nvlist_lookup_string(props,
672 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
673 &propval) == 0)
674 break;
675 if (add_prop_list(zpool_prop_to_name(
676 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
677 goto errout;
678 break;
679 case 'm':
680 /* Equivalent to -O mountpoint=optarg */
681 mountpoint = optarg;
682 break;
683 case 'o':
684 if ((propval = strchr(optarg, '=')) == NULL) {
685 (void) fprintf(stderr, gettext("missing "
686 "'=' for -o option\n"));
687 goto errout;
688 }
689 *propval = '\0';
690 propval++;
691
692 if (add_prop_list(optarg, propval, &props, B_TRUE))
693 goto errout;
694
695 /*
696 * If the user is creating a pool that doesn't support
697 * feature flags, don't enable any features.
698 */
699 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
700 char *end;
701 u_longlong_t ver;
702
703 ver = strtoull(propval, &end, 10);
704 if (*end == '\0' &&
705 ver < SPA_VERSION_FEATURES) {
706 enable_all_pool_feat = B_FALSE;
707 }
708 }
709 break;
710 case 'O':
711 if ((propval = strchr(optarg, '=')) == NULL) {
712 (void) fprintf(stderr, gettext("missing "
713 "'=' for -O option\n"));
714 goto errout;
715 }
716 *propval = '\0';
717 propval++;
718
719 /*
720 * Mountpoints are checked and then added later.
721 * Uniquely among properties, they can be specified
722 * more than once, to avoid conflict with -m.
723 */
724 if (!strcmp(optarg,
725 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT)))
726 mountpoint = propval;
727 if (add_prop_list(optarg, propval, &fsprops, B_FALSE))
728 goto errout;
729 break;
730 case ':':
731 (void) fprintf(stderr, gettext("missing argument for "
732 "'%c' option\n"), optopt);
733 goto badusage;
734 case '?':
735 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
736 optopt);
737 goto badusage;
738 }
739 }
740
741 argc -= optind;
742 argv += optind;
743
744 /* get pool name and check number of arguments */
745 if (argc < 1) {
746 (void) fprintf(stderr, gettext("missing pool name argument\n"));
747 goto badusage;
748 }
749 if (argc < 2) {
750 (void) fprintf(stderr, gettext("missing vdev specification\n"));
751 goto badusage;
752 }
753
754 poolname = argv[0];
755
756 /*
757 * As a special case, check for use of '/' in the name, and direct the
758 * user to use 'zfs create' instead.
759 */
760 if (strchr(poolname, '/') != NULL) {
761 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
762 "character '/' in pool name\n"), poolname);
763 (void) fprintf(stderr, gettext("use 'zfs create' to "
764 "create a dataset\n"));
765 goto errout;
766 }
767
768 /* pass off to get_vdev_spec for bulk processing */
769 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
770 argc - 1, argv + 1);
771 if (nvroot == NULL)
772 goto errout;
773
774 /* make_root_vdev() allows 0 toplevel children if there are spares */
775 if (!zfs_allocatable_devs(nvroot)) {
776 (void) fprintf(stderr, gettext("invalid vdev "
777 "specification: at least one toplevel vdev must be "
778 "specified\n"));
779 goto errout;
780 }
781
782 if (altroot != NULL && altroot[0] != '/') {
783 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
784 "must be an absolute path\n"), altroot);
785 goto errout;
786 }
787
788 /*
789 * Check the validity of the mountpoint and direct the user to use the
790 * '-m' mountpoint option if it looks like its in use.
791 */
792 if (mountpoint == NULL ||
793 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
794 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
795 char buf[MAXPATHLEN];
796 DIR *dirp;
797
798 if (mountpoint && mountpoint[0] != '/') {
799 (void) fprintf(stderr, gettext("invalid mountpoint "
800 "'%s': must be an absolute path, 'legacy', or "
801 "'none'\n"), mountpoint);
802 goto errout;
803 }
804
805 if (mountpoint == NULL) {
806 if (altroot != NULL)
807 (void) snprintf(buf, sizeof (buf), "%s/%s",
808 altroot, poolname);
809 else
810 (void) snprintf(buf, sizeof (buf), "/%s",
811 poolname);
812 } else {
813 if (altroot != NULL)
814 (void) snprintf(buf, sizeof (buf), "%s%s",
815 altroot, mountpoint);
816 else
817 (void) snprintf(buf, sizeof (buf), "%s",
818 mountpoint);
819 }
820
821 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
822 (void) fprintf(stderr, gettext("mountpoint '%s' : "
823 "%s\n"), buf, strerror(errno));
824 (void) fprintf(stderr, gettext("use '-m' "
825 "option to provide a different default\n"));
826 goto errout;
827 } else if (dirp) {
828 int count = 0;
829
830 while (count < 3 && readdir(dirp) != NULL)
831 count++;
832 (void) closedir(dirp);
833
834 if (count > 2) {
835 (void) fprintf(stderr, gettext("mountpoint "
836 "'%s' exists and is not empty\n"), buf);
837 (void) fprintf(stderr, gettext("use '-m' "
838 "option to provide a "
839 "different default\n"));
840 goto errout;
841 }
842 }
843 }
844
845 /*
846 * Now that the mountpoint's validity has been checked, ensure that
847 * the property is set appropriately prior to creating the pool.
848 */
849 if (mountpoint != NULL)
850 if (add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
851 mountpoint, &fsprops, B_FALSE))
852 goto errout;
853
854 if (dryrun) {
855 /*
856 * For a dry run invocation, print out a basic message and run
857 * through all the vdevs in the list and print out in an
858 * appropriate hierarchy.
859 */
860 (void) printf(gettext("would create '%s' with the "
861 "following layout:\n\n"), poolname);
862
863 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
864 if (num_logs(nvroot) > 0)
865 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
866
867 ret = 0;
868 } else {
869 /*
870 * Hand off to libzfs.
871 */
872 if (enable_all_pool_feat) {
873 int i;
874 for (i = 0; i < SPA_FEATURES; i++) {
875 char propname[MAXPATHLEN];
876 zfeature_info_t *feat = &spa_feature_table[i];
877
878 (void) snprintf(propname, sizeof (propname),
879 "feature@%s", feat->fi_uname);
880
881 /*
882 * Skip feature if user specified it manually
883 * on the command line.
884 */
885 if (nvlist_exists(props, propname))
886 continue;
887
888 if (add_prop_list(propname, ZFS_FEATURE_ENABLED,
889 &props, B_TRUE) != 0)
890 goto errout;
891 }
892 }
893 if (zpool_create(g_zfs, poolname,
894 nvroot, props, fsprops) == 0) {
895 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
896 ZFS_TYPE_FILESYSTEM);
897 if (pool != NULL) {
898 if (zfs_mount(pool, NULL, 0) == 0)
899 ret = zfs_shareall(pool);
900 zfs_close(pool);
901 }
902 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
903 (void) fprintf(stderr, gettext("pool name may have "
904 "been omitted\n"));
905 }
906 }
907
908 errout:
909 nvlist_free(nvroot);
910 nvlist_free(fsprops);
911 nvlist_free(props);
912 return (ret);
913 badusage:
914 nvlist_free(fsprops);
915 nvlist_free(props);
916 usage(B_FALSE);
917 return (2);
918 }
919
920 /*
921 * zpool destroy <pool>
922 *
923 * -f Forcefully unmount any datasets
924 *
925 * Destroy the given pool. Automatically unmounts any datasets in the pool.
926 */
927 int
928 zpool_do_destroy(int argc, char **argv)
929 {
930 boolean_t force = B_FALSE;
931 int c;
932 char *pool;
933 zpool_handle_t *zhp;
934 int ret;
935
936 /* check options */
937 while ((c = getopt(argc, argv, "f")) != -1) {
938 switch (c) {
939 case 'f':
940 force = B_TRUE;
941 break;
942 case '?':
943 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
944 optopt);
945 usage(B_FALSE);
946 }
947 }
948
949 argc -= optind;
950 argv += optind;
951
952 /* check arguments */
953 if (argc < 1) {
954 (void) fprintf(stderr, gettext("missing pool argument\n"));
955 usage(B_FALSE);
956 }
957 if (argc > 1) {
958 (void) fprintf(stderr, gettext("too many arguments\n"));
959 usage(B_FALSE);
960 }
961
962 pool = argv[0];
963
964 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
965 /*
966 * As a special case, check for use of '/' in the name, and
967 * direct the user to use 'zfs destroy' instead.
968 */
969 if (strchr(pool, '/') != NULL)
970 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
971 "destroy a dataset\n"));
972 return (1);
973 }
974
975 if (zpool_disable_datasets(zhp, force) != 0) {
976 (void) fprintf(stderr, gettext("could not destroy '%s': "
977 "could not unmount datasets\n"), zpool_get_name(zhp));
978 return (1);
979 }
980
981 /* The history must be logged as part of the export */
982 log_history = B_FALSE;
983
984 ret = (zpool_destroy(zhp, history_str) != 0);
985
986 zpool_close(zhp);
987
988 return (ret);
989 }
990
991 /*
992 * zpool export [-f] <pool> ...
993 *
994 * -f Forcefully unmount datasets
995 *
996 * Export the given pools. By default, the command will attempt to cleanly
997 * unmount any active datasets within the pool. If the '-f' flag is specified,
998 * then the datasets will be forcefully unmounted.
999 */
1000 int
1001 zpool_do_export(int argc, char **argv)
1002 {
1003 boolean_t force = B_FALSE;
1004 boolean_t hardforce = B_FALSE;
1005 int c;
1006 zpool_handle_t *zhp;
1007 int ret;
1008 int i;
1009
1010 /* check options */
1011 while ((c = getopt(argc, argv, "fF")) != -1) {
1012 switch (c) {
1013 case 'f':
1014 force = B_TRUE;
1015 break;
1016 case 'F':
1017 hardforce = B_TRUE;
1018 break;
1019 case '?':
1020 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1021 optopt);
1022 usage(B_FALSE);
1023 }
1024 }
1025
1026 argc -= optind;
1027 argv += optind;
1028
1029 /* check arguments */
1030 if (argc < 1) {
1031 (void) fprintf(stderr, gettext("missing pool argument\n"));
1032 usage(B_FALSE);
1033 }
1034
1035 ret = 0;
1036 for (i = 0; i < argc; i++) {
1037 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1038 ret = 1;
1039 continue;
1040 }
1041
1042 if (zpool_disable_datasets(zhp, force) != 0) {
1043 ret = 1;
1044 zpool_close(zhp);
1045 continue;
1046 }
1047
1048 /* The history must be logged as part of the export */
1049 log_history = B_FALSE;
1050
1051 if (hardforce) {
1052 if (zpool_export_force(zhp, history_str) != 0)
1053 ret = 1;
1054 } else if (zpool_export(zhp, force, history_str) != 0) {
1055 ret = 1;
1056 }
1057
1058 zpool_close(zhp);
1059 }
1060
1061 return (ret);
1062 }
1063
1064 /*
1065 * Given a vdev configuration, determine the maximum width needed for the device
1066 * name column.
1067 */
1068 static int
1069 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1070 {
1071 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1072 nvlist_t **child;
1073 uint_t c, children;
1074 int ret;
1075
1076 if (strlen(name) + depth > max)
1077 max = strlen(name) + depth;
1078
1079 free(name);
1080
1081 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1082 &child, &children) == 0) {
1083 for (c = 0; c < children; c++)
1084 if ((ret = max_width(zhp, child[c], depth + 2,
1085 max)) > max)
1086 max = ret;
1087 }
1088
1089 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1090 &child, &children) == 0) {
1091 for (c = 0; c < children; c++)
1092 if ((ret = max_width(zhp, child[c], depth + 2,
1093 max)) > max)
1094 max = ret;
1095 }
1096
1097 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1098 &child, &children) == 0) {
1099 for (c = 0; c < children; c++)
1100 if ((ret = max_width(zhp, child[c], depth + 2,
1101 max)) > max)
1102 max = ret;
1103 }
1104
1105
1106 return (max);
1107 }
1108
1109 typedef struct spare_cbdata {
1110 uint64_t cb_guid;
1111 zpool_handle_t *cb_zhp;
1112 } spare_cbdata_t;
1113
1114 static boolean_t
1115 find_vdev(nvlist_t *nv, uint64_t search)
1116 {
1117 uint64_t guid;
1118 nvlist_t **child;
1119 uint_t c, children;
1120
1121 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1122 search == guid)
1123 return (B_TRUE);
1124
1125 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1126 &child, &children) == 0) {
1127 for (c = 0; c < children; c++)
1128 if (find_vdev(child[c], search))
1129 return (B_TRUE);
1130 }
1131
1132 return (B_FALSE);
1133 }
1134
1135 static int
1136 find_spare(zpool_handle_t *zhp, void *data)
1137 {
1138 spare_cbdata_t *cbp = data;
1139 nvlist_t *config, *nvroot;
1140
1141 config = zpool_get_config(zhp, NULL);
1142 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1143 &nvroot) == 0);
1144
1145 if (find_vdev(nvroot, cbp->cb_guid)) {
1146 cbp->cb_zhp = zhp;
1147 return (1);
1148 }
1149
1150 zpool_close(zhp);
1151 return (0);
1152 }
1153
1154 /*
1155 * Print out configuration state as requested by status_callback.
1156 */
1157 void
1158 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1159 int namewidth, int depth, boolean_t isspare)
1160 {
1161 nvlist_t **child;
1162 uint_t c, children;
1163 pool_scan_stat_t *ps = NULL;
1164 vdev_stat_t *vs;
1165 char rbuf[6], wbuf[6], cbuf[6];
1166 char *vname;
1167 uint64_t notpresent;
1168 spare_cbdata_t cb;
1169 char *state;
1170
1171 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1172 &child, &children) != 0)
1173 children = 0;
1174
1175 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1176 (uint64_t **)&vs, &c) == 0);
1177
1178 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1179 if (isspare) {
1180 /*
1181 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1182 * online drives.
1183 */
1184 if (vs->vs_aux == VDEV_AUX_SPARED)
1185 state = "INUSE";
1186 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1187 state = "AVAIL";
1188 }
1189
1190 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1191 name, state);
1192
1193 if (!isspare) {
1194 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1195 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1196 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1197 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1198 }
1199
1200 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1201 ¬present) == 0) {
1202 char *path;
1203 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1204 (void) printf(" was %s", path);
1205 } else if (vs->vs_aux != 0) {
1206 (void) printf(" ");
1207
1208 switch (vs->vs_aux) {
1209 case VDEV_AUX_OPEN_FAILED:
1210 (void) printf(gettext("cannot open"));
1211 break;
1212
1213 case VDEV_AUX_BAD_GUID_SUM:
1214 (void) printf(gettext("missing device"));
1215 break;
1216
1217 case VDEV_AUX_NO_REPLICAS:
1218 (void) printf(gettext("insufficient replicas"));
1219 break;
1220
1221 case VDEV_AUX_VERSION_NEWER:
1222 (void) printf(gettext("newer version"));
1223 break;
1224
1225 case VDEV_AUX_UNSUP_FEAT:
1226 (void) printf(gettext("unsupported feature(s)"));
1227 break;
1228
1229 case VDEV_AUX_SPARED:
1230 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1231 &cb.cb_guid) == 0);
1232 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1233 if (strcmp(zpool_get_name(cb.cb_zhp),
1234 zpool_get_name(zhp)) == 0)
1235 (void) printf(gettext("currently in "
1236 "use"));
1237 else
1238 (void) printf(gettext("in use by "
1239 "pool '%s'"),
1240 zpool_get_name(cb.cb_zhp));
1241 zpool_close(cb.cb_zhp);
1242 } else {
1243 (void) printf(gettext("currently in use"));
1244 }
1245 break;
1246
1247 case VDEV_AUX_ERR_EXCEEDED:
1248 (void) printf(gettext("too many errors"));
1249 break;
1250
1251 case VDEV_AUX_IO_FAILURE:
1252 (void) printf(gettext("experienced I/O failures"));
1253 break;
1254
1255 case VDEV_AUX_BAD_LOG:
1256 (void) printf(gettext("bad intent log"));
1257 break;
1258
1259 case VDEV_AUX_EXTERNAL:
1260 (void) printf(gettext("external device fault"));
1261 break;
1262
1263 case VDEV_AUX_SPLIT_POOL:
1264 (void) printf(gettext("split into new pool"));
1265 break;
1266
1267 default:
1268 (void) printf(gettext("corrupted data"));
1269 break;
1270 }
1271 }
1272
1273 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1274 (uint64_t **)&ps, &c);
1275
1276 if (ps && ps->pss_state == DSS_SCANNING &&
1277 vs->vs_scan_processed != 0 && children == 0) {
1278 (void) printf(gettext(" (%s)"),
1279 (ps->pss_func == POOL_SCAN_RESILVER) ?
1280 "resilvering" : "repairing");
1281 }
1282
1283 (void) printf("\n");
1284
1285 for (c = 0; c < children; c++) {
1286 uint64_t islog = B_FALSE, ishole = B_FALSE;
1287
1288 /* Don't print logs or holes here */
1289 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1290 &islog);
1291 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1292 &ishole);
1293 if (islog || ishole)
1294 continue;
1295 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1296 print_status_config(zhp, vname, child[c],
1297 namewidth, depth + 2, isspare);
1298 free(vname);
1299 }
1300 }
1301
1302
1303 /*
1304 * Print the configuration of an exported pool. Iterate over all vdevs in the
1305 * pool, printing out the name and status for each one.
1306 */
1307 void
1308 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1309 {
1310 nvlist_t **child;
1311 uint_t c, children;
1312 vdev_stat_t *vs;
1313 char *type, *vname;
1314
1315 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1316 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1317 strcmp(type, VDEV_TYPE_HOLE) == 0)
1318 return;
1319
1320 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1321 (uint64_t **)&vs, &c) == 0);
1322
1323 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1324 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1325
1326 if (vs->vs_aux != 0) {
1327 (void) printf(" ");
1328
1329 switch (vs->vs_aux) {
1330 case VDEV_AUX_OPEN_FAILED:
1331 (void) printf(gettext("cannot open"));
1332 break;
1333
1334 case VDEV_AUX_BAD_GUID_SUM:
1335 (void) printf(gettext("missing device"));
1336 break;
1337
1338 case VDEV_AUX_NO_REPLICAS:
1339 (void) printf(gettext("insufficient replicas"));
1340 break;
1341
1342 case VDEV_AUX_VERSION_NEWER:
1343 (void) printf(gettext("newer version"));
1344 break;
1345
1346 case VDEV_AUX_UNSUP_FEAT:
1347 (void) printf(gettext("unsupported feature(s)"));
1348 break;
1349
1350 case VDEV_AUX_ERR_EXCEEDED:
1351 (void) printf(gettext("too many errors"));
1352 break;
1353
1354 default:
1355 (void) printf(gettext("corrupted data"));
1356 break;
1357 }
1358 }
1359 (void) printf("\n");
1360
1361 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1362 &child, &children) != 0)
1363 return;
1364
1365 for (c = 0; c < children; c++) {
1366 uint64_t is_log = B_FALSE;
1367
1368 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1369 &is_log);
1370 if (is_log)
1371 continue;
1372
1373 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1374 print_import_config(vname, child[c], namewidth, depth + 2);
1375 free(vname);
1376 }
1377
1378 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1379 &child, &children) == 0) {
1380 (void) printf(gettext("\tcache\n"));
1381 for (c = 0; c < children; c++) {
1382 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1383 (void) printf("\t %s\n", vname);
1384 free(vname);
1385 }
1386 }
1387
1388 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1389 &child, &children) == 0) {
1390 (void) printf(gettext("\tspares\n"));
1391 for (c = 0; c < children; c++) {
1392 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1393 (void) printf("\t %s\n", vname);
1394 free(vname);
1395 }
1396 }
1397 }
1398
1399 /*
1400 * Print log vdevs.
1401 * Logs are recorded as top level vdevs in the main pool child array
1402 * but with "is_log" set to 1. We use either print_status_config() or
1403 * print_import_config() to print the top level logs then any log
1404 * children (eg mirrored slogs) are printed recursively - which
1405 * works because only the top level vdev is marked "is_log"
1406 */
1407 static void
1408 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1409 {
1410 uint_t c, children;
1411 nvlist_t **child;
1412
1413 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1414 &children) != 0)
1415 return;
1416
1417 (void) printf(gettext("\tlogs\n"));
1418
1419 for (c = 0; c < children; c++) {
1420 uint64_t is_log = B_FALSE;
1421 char *name;
1422
1423 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1424 &is_log);
1425 if (!is_log)
1426 continue;
1427 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1428 if (verbose)
1429 print_status_config(zhp, name, child[c], namewidth,
1430 2, B_FALSE);
1431 else
1432 print_import_config(name, child[c], namewidth, 2);
1433 free(name);
1434 }
1435 }
1436
1437 /*
1438 * Display the status for the given pool.
1439 */
1440 static void
1441 show_import(nvlist_t *config)
1442 {
1443 uint64_t pool_state;
1444 vdev_stat_t *vs;
1445 char *name;
1446 uint64_t guid;
1447 char *msgid;
1448 nvlist_t *nvroot;
1449 int reason;
1450 const char *health;
1451 uint_t vsc;
1452 int namewidth;
1453 char *comment;
1454
1455 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1456 &name) == 0);
1457 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1458 &guid) == 0);
1459 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1460 &pool_state) == 0);
1461 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1462 &nvroot) == 0);
1463
1464 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1465 (uint64_t **)&vs, &vsc) == 0);
1466 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1467
1468 reason = zpool_import_status(config, &msgid);
1469
1470 (void) printf(gettext(" pool: %s\n"), name);
1471 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1472 (void) printf(gettext(" state: %s"), health);
1473 if (pool_state == POOL_STATE_DESTROYED)
1474 (void) printf(gettext(" (DESTROYED)"));
1475 (void) printf("\n");
1476
1477 switch (reason) {
1478 case ZPOOL_STATUS_MISSING_DEV_R:
1479 case ZPOOL_STATUS_MISSING_DEV_NR:
1480 case ZPOOL_STATUS_BAD_GUID_SUM:
1481 (void) printf(gettext(" status: One or more devices are "
1482 "missing from the system.\n"));
1483 break;
1484
1485 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1486 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1487 (void) printf(gettext(" status: One or more devices contains "
1488 "corrupted data.\n"));
1489 break;
1490
1491 case ZPOOL_STATUS_CORRUPT_DATA:
1492 (void) printf(
1493 gettext(" status: The pool data is corrupted.\n"));
1494 break;
1495
1496 case ZPOOL_STATUS_OFFLINE_DEV:
1497 (void) printf(gettext(" status: One or more devices "
1498 "are offlined.\n"));
1499 break;
1500
1501 case ZPOOL_STATUS_CORRUPT_POOL:
1502 (void) printf(gettext(" status: The pool metadata is "
1503 "corrupted.\n"));
1504 break;
1505
1506 case ZPOOL_STATUS_VERSION_OLDER:
1507 (void) printf(gettext(" status: The pool is formatted using a "
1508 "legacy on-disk version.\n"));
1509 break;
1510
1511 case ZPOOL_STATUS_VERSION_NEWER:
1512 (void) printf(gettext(" status: The pool is formatted using an "
1513 "incompatible version.\n"));
1514 break;
1515
1516 case ZPOOL_STATUS_FEAT_DISABLED:
1517 (void) printf(gettext(" status: Some supported features are "
1518 "not enabled on the pool.\n"));
1519 break;
1520
1521 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1522 (void) printf(gettext("status: The pool uses the following "
1523 "feature(s) not supported on this sytem:\n"));
1524 zpool_print_unsup_feat(config);
1525 break;
1526
1527 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1528 (void) printf(gettext("status: The pool can only be accessed "
1529 "in read-only mode on this system. It\n\tcannot be "
1530 "accessed in read-write mode because it uses the "
1531 "following\n\tfeature(s) not supported on this system:\n"));
1532 zpool_print_unsup_feat(config);
1533 break;
1534
1535 case ZPOOL_STATUS_HOSTID_MISMATCH:
1536 (void) printf(gettext(" status: The pool was last accessed by "
1537 "another system.\n"));
1538 break;
1539
1540 case ZPOOL_STATUS_FAULTED_DEV_R:
1541 case ZPOOL_STATUS_FAULTED_DEV_NR:
1542 (void) printf(gettext(" status: One or more devices are "
1543 "faulted.\n"));
1544 break;
1545
1546 case ZPOOL_STATUS_BAD_LOG:
1547 (void) printf(gettext(" status: An intent log record cannot be "
1548 "read.\n"));
1549 break;
1550
1551 case ZPOOL_STATUS_RESILVERING:
1552 (void) printf(gettext(" status: One or more devices were being "
1553 "resilvered.\n"));
1554 break;
1555
1556 default:
1557 /*
1558 * No other status can be seen when importing pools.
1559 */
1560 assert(reason == ZPOOL_STATUS_OK);
1561 }
1562
1563 /*
1564 * Print out an action according to the overall state of the pool.
1565 */
1566 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1567 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1568 reason == ZPOOL_STATUS_FEAT_DISABLED) {
1569 (void) printf(gettext(" action: The pool can be "
1570 "imported using its name or numeric identifier, "
1571 "though\n\tsome features will not be available "
1572 "without an explicit 'zpool upgrade'.\n"));
1573 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1574 (void) printf(gettext(" action: The pool can be "
1575 "imported using its name or numeric "
1576 "identifier and\n\tthe '-f' flag.\n"));
1577 } else {
1578 (void) printf(gettext(" action: The pool can be "
1579 "imported using its name or numeric "
1580 "identifier.\n"));
1581 }
1582 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1583 (void) printf(gettext(" action: The pool can be imported "
1584 "despite missing or damaged devices. The\n\tfault "
1585 "tolerance of the pool may be compromised if imported.\n"));
1586 } else {
1587 switch (reason) {
1588 case ZPOOL_STATUS_VERSION_NEWER:
1589 (void) printf(gettext(" action: The pool cannot be "
1590 "imported. Access the pool on a system running "
1591 "newer\n\tsoftware, or recreate the pool from "
1592 "backup.\n"));
1593 break;
1594 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1595 (void) printf(gettext("action: The pool cannot be "
1596 "imported. Access the pool on a system that "
1597 "supports\n\tthe required feature(s), or recreate "
1598 "the pool from backup.\n"));
1599 break;
1600 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1601 (void) printf(gettext("action: The pool cannot be "
1602 "imported in read-write mode. Import the pool "
1603 "with\n"
1604 "\t\"-o readonly=on\", access the pool on a system "
1605 "that supports the\n\trequired feature(s), or "
1606 "recreate the pool from backup.\n"));
1607 break;
1608 case ZPOOL_STATUS_MISSING_DEV_R:
1609 case ZPOOL_STATUS_MISSING_DEV_NR:
1610 case ZPOOL_STATUS_BAD_GUID_SUM:
1611 (void) printf(gettext(" action: The pool cannot be "
1612 "imported. Attach the missing\n\tdevices and try "
1613 "again.\n"));
1614 break;
1615 default:
1616 (void) printf(gettext(" action: The pool cannot be "
1617 "imported due to damaged devices or data.\n"));
1618 }
1619 }
1620
1621 /* Print the comment attached to the pool. */
1622 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1623 (void) printf(gettext("comment: %s\n"), comment);
1624
1625 /*
1626 * If the state is "closed" or "can't open", and the aux state
1627 * is "corrupt data":
1628 */
1629 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1630 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1631 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1632 if (pool_state == POOL_STATE_DESTROYED)
1633 (void) printf(gettext("\tThe pool was destroyed, "
1634 "but can be imported using the '-Df' flags.\n"));
1635 else if (pool_state != POOL_STATE_EXPORTED)
1636 (void) printf(gettext("\tThe pool may be active on "
1637 "another system, but can be imported using\n\t"
1638 "the '-f' flag.\n"));
1639 }
1640
1641 if (msgid != NULL)
1642 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
1643 msgid);
1644
1645 (void) printf(gettext(" config:\n\n"));
1646
1647 namewidth = max_width(NULL, nvroot, 0, 0);
1648 if (namewidth < 10)
1649 namewidth = 10;
1650
1651 print_import_config(name, nvroot, namewidth, 0);
1652 if (num_logs(nvroot) > 0)
1653 print_logs(NULL, nvroot, namewidth, B_FALSE);
1654
1655 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1656 (void) printf(gettext("\n\tAdditional devices are known to "
1657 "be part of this pool, though their\n\texact "
1658 "configuration cannot be determined.\n"));
1659 }
1660 }
1661
1662 /*
1663 * Perform the import for the given configuration. This passes the heavy
1664 * lifting off to zpool_import_props(), and then mounts the datasets contained
1665 * within the pool.
1666 */
1667 static int
1668 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1669 nvlist_t *props, int flags)
1670 {
1671 zpool_handle_t *zhp;
1672 char *name;
1673 uint64_t state;
1674 uint64_t version;
1675
1676 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1677 &name) == 0);
1678
1679 verify(nvlist_lookup_uint64(config,
1680 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1681 verify(nvlist_lookup_uint64(config,
1682 ZPOOL_CONFIG_VERSION, &version) == 0);
1683 if (!SPA_VERSION_IS_SUPPORTED(version)) {
1684 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1685 "is formatted using an unsupported ZFS version\n"), name);
1686 return (1);
1687 } else if (state != POOL_STATE_EXPORTED &&
1688 !(flags & ZFS_IMPORT_ANY_HOST)) {
1689 uint64_t hostid;
1690
1691 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1692 &hostid) == 0) {
1693 if ((unsigned long)hostid != gethostid()) {
1694 char *hostname;
1695 uint64_t timestamp;
1696 time_t t;
1697
1698 verify(nvlist_lookup_string(config,
1699 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1700 verify(nvlist_lookup_uint64(config,
1701 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0);
1702 t = timestamp;
1703 (void) fprintf(stderr, gettext("cannot import "
1704 "'%s': pool may be in use from other "
1705 "system, it was last accessed by %s "
1706 "(hostid: 0x%lx) on %s"), name, hostname,
1707 (unsigned long)hostid,
1708 asctime(localtime(&t)));
1709 (void) fprintf(stderr, gettext("use '-f' to "
1710 "import anyway\n"));
1711 return (1);
1712 }
1713 } else {
1714 (void) fprintf(stderr, gettext("cannot import '%s': "
1715 "pool may be in use from other system\n"), name);
1716 (void) fprintf(stderr, gettext("use '-f' to import "
1717 "anyway\n"));
1718 return (1);
1719 }
1720 }
1721
1722 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
1723 return (1);
1724
1725 if (newname != NULL)
1726 name = (char *)newname;
1727
1728 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
1729 return (1);
1730
1731 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1732 !(flags & ZFS_IMPORT_ONLY) &&
1733 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1734 zpool_close(zhp);
1735 return (1);
1736 }
1737
1738 zpool_close(zhp);
1739 return (0);
1740 }
1741
1742 /*
1743 * zpool import [-d dir] [-D]
1744 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1745 * [-d dir | -c cachefile] [-f] -a
1746 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1747 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
1748 *
1749 * -c Read pool information from a cachefile instead of searching
1750 * devices.
1751 *
1752 * -d Scan in a specific directory, other than /dev/dsk. More than
1753 * one directory can be specified using multiple '-d' options.
1754 *
1755 * -D Scan for previously destroyed pools or import all or only
1756 * specified destroyed pools.
1757 *
1758 * -R Temporarily import the pool, with all mountpoints relative to
1759 * the given root. The pool will remain exported when the machine
1760 * is rebooted.
1761 *
1762 * -V Import even in the presence of faulted vdevs. This is an
1763 * intentionally undocumented option for testing purposes, and
1764 * treats the pool configuration as complete, leaving any bad
1765 * vdevs in the FAULTED state. In other words, it does verbatim
1766 * import.
1767 *
1768 * -f Force import, even if it appears that the pool is active.
1769 *
1770 * -F Attempt rewind if necessary.
1771 *
1772 * -n See if rewind would work, but don't actually rewind.
1773 *
1774 * -N Import the pool but don't mount datasets.
1775 *
1776 * -T Specify a starting txg to use for import. This option is
1777 * intentionally undocumented option for testing purposes.
1778 *
1779 * -a Import all pools found.
1780 *
1781 * -o Set property=value and/or temporary mount options (without '=').
1782 *
1783 * The import command scans for pools to import, and import pools based on pool
1784 * name and GUID. The pool can also be renamed as part of the import process.
1785 */
1786 int
1787 zpool_do_import(int argc, char **argv)
1788 {
1789 char **searchdirs = NULL;
1790 int nsearch = 0;
1791 int c;
1792 int err = 0;
1793 nvlist_t *pools = NULL;
1794 boolean_t do_all = B_FALSE;
1795 boolean_t do_destroyed = B_FALSE;
1796 char *mntopts = NULL;
1797 nvpair_t *elem;
1798 nvlist_t *config;
1799 uint64_t searchguid = 0;
1800 char *searchname = NULL;
1801 char *propval;
1802 nvlist_t *found_config;
1803 nvlist_t *policy = NULL;
1804 nvlist_t *props = NULL;
1805 boolean_t first;
1806 int flags = ZFS_IMPORT_NORMAL;
1807 uint32_t rewind_policy = ZPOOL_NO_REWIND;
1808 boolean_t dryrun = B_FALSE;
1809 boolean_t do_rewind = B_FALSE;
1810 boolean_t xtreme_rewind = B_FALSE;
1811 uint64_t pool_state, txg = -1ULL;
1812 char *cachefile = NULL;
1813 importargs_t idata = { 0 };
1814 char *endptr;
1815
1816 /* check options */
1817 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
1818 switch (c) {
1819 case 'a':
1820 do_all = B_TRUE;
1821 break;
1822 case 'c':
1823 cachefile = optarg;
1824 break;
1825 case 'd':
1826 if (searchdirs == NULL) {
1827 searchdirs = safe_malloc(sizeof (char *));
1828 } else {
1829 char **tmp = safe_malloc((nsearch + 1) *
1830 sizeof (char *));
1831 bcopy(searchdirs, tmp, nsearch *
1832 sizeof (char *));
1833 free(searchdirs);
1834 searchdirs = tmp;
1835 }
1836 searchdirs[nsearch++] = optarg;
1837 break;
1838 case 'D':
1839 do_destroyed = B_TRUE;
1840 break;
1841 case 'f':
1842 flags |= ZFS_IMPORT_ANY_HOST;
1843 break;
1844 case 'F':
1845 do_rewind = B_TRUE;
1846 break;
1847 case 'm':
1848 flags |= ZFS_IMPORT_MISSING_LOG;
1849 break;
1850 case 'n':
1851 dryrun = B_TRUE;
1852 break;
1853 case 'N':
1854 flags |= ZFS_IMPORT_ONLY;
1855 break;
1856 case 'o':
1857 if ((propval = strchr(optarg, '=')) != NULL) {
1858 *propval = '\0';
1859 propval++;
1860 if (add_prop_list(optarg, propval,
1861 &props, B_TRUE))
1862 goto error;
1863 } else {
1864 mntopts = optarg;
1865 }
1866 break;
1867 case 'R':
1868 if (add_prop_list(zpool_prop_to_name(
1869 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1870 goto error;
1871 if (nvlist_lookup_string(props,
1872 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1873 &propval) == 0)
1874 break;
1875 if (add_prop_list(zpool_prop_to_name(
1876 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1877 goto error;
1878 break;
1879 case 'T':
1880 errno = 0;
1881 txg = strtoull(optarg, &endptr, 10);
1882 if (errno != 0 || *endptr != '\0') {
1883 (void) fprintf(stderr,
1884 gettext("invalid txg value\n"));
1885 usage(B_FALSE);
1886 }
1887 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
1888 break;
1889 case 'V':
1890 flags |= ZFS_IMPORT_VERBATIM;
1891 break;
1892 case 'X':
1893 xtreme_rewind = B_TRUE;
1894 break;
1895 case ':':
1896 (void) fprintf(stderr, gettext("missing argument for "
1897 "'%c' option\n"), optopt);
1898 usage(B_FALSE);
1899 break;
1900 case '?':
1901 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1902 optopt);
1903 usage(B_FALSE);
1904 }
1905 }
1906
1907 argc -= optind;
1908 argv += optind;
1909
1910 if (cachefile && nsearch != 0) {
1911 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1912 usage(B_FALSE);
1913 }
1914
1915 if ((dryrun || xtreme_rewind) && !do_rewind) {
1916 (void) fprintf(stderr,
1917 gettext("-n or -X only meaningful with -F\n"));
1918 usage(B_FALSE);
1919 }
1920 if (dryrun)
1921 rewind_policy = ZPOOL_TRY_REWIND;
1922 else if (do_rewind)
1923 rewind_policy = ZPOOL_DO_REWIND;
1924 if (xtreme_rewind)
1925 rewind_policy |= ZPOOL_EXTREME_REWIND;
1926
1927 /* In the future, we can capture further policy and include it here */
1928 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
1929 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
1930 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
1931 goto error;
1932
1933 if (searchdirs == NULL) {
1934 searchdirs = safe_malloc(sizeof (char *));
1935 searchdirs[0] = "/dev/dsk";
1936 nsearch = 1;
1937 }
1938
1939 /* check argument count */
1940 if (do_all) {
1941 if (argc != 0) {
1942 (void) fprintf(stderr, gettext("too many arguments\n"));
1943 usage(B_FALSE);
1944 }
1945 } else {
1946 if (argc > 2) {
1947 (void) fprintf(stderr, gettext("too many arguments\n"));
1948 usage(B_FALSE);
1949 }
1950
1951 /*
1952 * Check for the SYS_CONFIG privilege. We do this explicitly
1953 * here because otherwise any attempt to discover pools will
1954 * silently fail.
1955 */
1956 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1957 (void) fprintf(stderr, gettext("cannot "
1958 "discover pools: permission denied\n"));
1959 free(searchdirs);
1960 nvlist_free(policy);
1961 return (1);
1962 }
1963 }
1964
1965 /*
1966 * Depending on the arguments given, we do one of the following:
1967 *
1968 * <none> Iterate through all pools and display information about
1969 * each one.
1970 *
1971 * -a Iterate through all pools and try to import each one.
1972 *
1973 * <id> Find the pool that corresponds to the given GUID/pool
1974 * name and import that one.
1975 *
1976 * -D Above options applies only to destroyed pools.
1977 */
1978 if (argc != 0) {
1979 char *endptr;
1980
1981 errno = 0;
1982 searchguid = strtoull(argv[0], &endptr, 10);
1983 if (errno != 0 || *endptr != '\0')
1984 searchname = argv[0];
1985 found_config = NULL;
1986
1987 /*
1988 * User specified a name or guid. Ensure it's unique.
1989 */
1990 idata.unique = B_TRUE;
1991 }
1992
1993
1994 idata.path = searchdirs;
1995 idata.paths = nsearch;
1996 idata.poolname = searchname;
1997 idata.guid = searchguid;
1998 idata.cachefile = cachefile;
1999
2000 pools = zpool_search_import(g_zfs, &idata);
2001
2002 if (pools != NULL && idata.exists &&
2003 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2004 (void) fprintf(stderr, gettext("cannot import '%s': "
2005 "a pool with that name already exists\n"),
2006 argv[0]);
2007 (void) fprintf(stderr, gettext("use the form '%s "
2008 "<pool | id> <newpool>' to give it a new name\n"),
2009 "zpool import");
2010 err = 1;
2011 } else if (pools == NULL && idata.exists) {
2012 (void) fprintf(stderr, gettext("cannot import '%s': "
2013 "a pool with that name is already created/imported,\n"),
2014 argv[0]);
2015 (void) fprintf(stderr, gettext("and no additional pools "
2016 "with that name were found\n"));
2017 err = 1;
2018 } else if (pools == NULL) {
2019 if (argc != 0) {
2020 (void) fprintf(stderr, gettext("cannot import '%s': "
2021 "no such pool available\n"), argv[0]);
2022 }
2023 err = 1;
2024 }
2025
2026 if (err == 1) {
2027 free(searchdirs);
2028 nvlist_free(policy);
2029 return (1);
2030 }
2031
2032 /*
2033 * At this point we have a list of import candidate configs. Even if
2034 * we were searching by pool name or guid, we still need to
2035 * post-process the list to deal with pool state and possible
2036 * duplicate names.
2037 */
2038 err = 0;
2039 elem = NULL;
2040 first = B_TRUE;
2041 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2042
2043 verify(nvpair_value_nvlist(elem, &config) == 0);
2044
2045 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2046 &pool_state) == 0);
2047 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2048 continue;
2049 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2050 continue;
2051
2052 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2053 policy) == 0);
2054
2055 if (argc == 0) {
2056 if (first)
2057 first = B_FALSE;
2058 else if (!do_all)
2059 (void) printf("\n");
2060
2061 if (do_all) {
2062 err |= do_import(config, NULL, mntopts,
2063 props, flags);
2064 } else {
2065 show_import(config);
2066 }
2067 } else if (searchname != NULL) {
2068 char *name;
2069
2070 /*
2071 * We are searching for a pool based on name.
2072 */
2073 verify(nvlist_lookup_string(config,
2074 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2075
2076 if (strcmp(name, searchname) == 0) {
2077 if (found_config != NULL) {
2078 (void) fprintf(stderr, gettext(
2079 "cannot import '%s': more than "
2080 "one matching pool\n"), searchname);
2081 (void) fprintf(stderr, gettext(
2082 "import by numeric ID instead\n"));
2083 err = B_TRUE;
2084 }
2085 found_config = config;
2086 }
2087 } else {
2088 uint64_t guid;
2089
2090 /*
2091 * Search for a pool by guid.
2092 */
2093 verify(nvlist_lookup_uint64(config,
2094 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2095
2096 if (guid == searchguid)
2097 found_config = config;
2098 }
2099 }
2100
2101 /*
2102 * If we were searching for a specific pool, verify that we found a
2103 * pool, and then do the import.
2104 */
2105 if (argc != 0 && err == 0) {
2106 if (found_config == NULL) {
2107 (void) fprintf(stderr, gettext("cannot import '%s': "
2108 "no such pool available\n"), argv[0]);
2109 err = B_TRUE;
2110 } else {
2111 err |= do_import(found_config, argc == 1 ? NULL :
2112 argv[1], mntopts, props, flags);
2113 }
2114 }
2115
2116 /*
2117 * If we were just looking for pools, report an error if none were
2118 * found.
2119 */
2120 if (argc == 0 && first)
2121 (void) fprintf(stderr,
2122 gettext("no pools available to import\n"));
2123
2124 error:
2125 nvlist_free(props);
2126 nvlist_free(pools);
2127 nvlist_free(policy);
2128 free(searchdirs);
2129
2130 return (err ? 1 : 0);
2131 }
2132
2133 typedef struct iostat_cbdata {
2134 boolean_t cb_verbose;
2135 int cb_namewidth;
2136 int cb_iteration;
2137 zpool_list_t *cb_list;
2138 } iostat_cbdata_t;
2139
2140 static void
2141 print_iostat_separator(iostat_cbdata_t *cb)
2142 {
2143 int i = 0;
2144
2145 for (i = 0; i < cb->cb_namewidth; i++)
2146 (void) printf("-");
2147 (void) printf(" ----- ----- ----- ----- ----- -----\n");
2148 }
2149
2150 static void
2151 print_iostat_header(iostat_cbdata_t *cb)
2152 {
2153 (void) printf("%*s capacity operations bandwidth\n",
2154 cb->cb_namewidth, "");
2155 (void) printf("%-*s alloc free read write read write\n",
2156 cb->cb_namewidth, "pool");
2157 print_iostat_separator(cb);
2158 }
2159
2160 /*
2161 * Display a single statistic.
2162 */
2163 static void
2164 print_one_stat(uint64_t value)
2165 {
2166 char buf[64];
2167
2168 zfs_nicenum(value, buf, sizeof (buf));
2169 (void) printf(" %5s", buf);
2170 }
2171
2172 /*
2173 * Print out all the statistics for the given vdev. This can either be the
2174 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2175 * is a verbose output, and we don't want to display the toplevel pool stats.
2176 */
2177 void
2178 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2179 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2180 {
2181 nvlist_t **oldchild, **newchild;
2182 uint_t c, children;
2183 vdev_stat_t *oldvs, *newvs;
2184 vdev_stat_t zerovs = { 0 };
2185 uint64_t tdelta;
2186 double scale;
2187 char *vname;
2188
2189 if (oldnv != NULL) {
2190 verify(nvlist_lookup_uint64_array(oldnv,
2191 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2192 } else {
2193 oldvs = &zerovs;
2194 }
2195
2196 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2197 (uint64_t **)&newvs, &c) == 0);
2198
2199 if (strlen(name) + depth > cb->cb_namewidth)
2200 (void) printf("%*s%s", depth, "", name);
2201 else
2202 (void) printf("%*s%s%*s", depth, "", name,
2203 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2204
2205 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2206
2207 if (tdelta == 0)
2208 scale = 1.0;
2209 else
2210 scale = (double)NANOSEC / tdelta;
2211
2212 /* only toplevel vdevs have capacity stats */
2213 if (newvs->vs_space == 0) {
2214 (void) printf(" - -");
2215 } else {
2216 print_one_stat(newvs->vs_alloc);
2217 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2218 }
2219
2220 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2221 oldvs->vs_ops[ZIO_TYPE_READ])));
2222
2223 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2224 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2225
2226 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2227 oldvs->vs_bytes[ZIO_TYPE_READ])));
2228
2229 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2230 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2231
2232 (void) printf("\n");
2233
2234 if (!cb->cb_verbose)
2235 return;
2236
2237 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2238 &newchild, &children) != 0)
2239 return;
2240
2241 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2242 &oldchild, &c) != 0)
2243 return;
2244
2245 for (c = 0; c < children; c++) {
2246 uint64_t ishole = B_FALSE, islog = B_FALSE;
2247
2248 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2249 &ishole);
2250
2251 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2252 &islog);
2253
2254 if (ishole || islog)
2255 continue;
2256
2257 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2258 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2259 newchild[c], cb, depth + 2);
2260 free(vname);
2261 }
2262
2263 /*
2264 * Log device section
2265 */
2266
2267 if (num_logs(newnv) > 0) {
2268 (void) printf("%-*s - - - - - "
2269 "-\n", cb->cb_namewidth, "logs");
2270
2271 for (c = 0; c < children; c++) {
2272 uint64_t islog = B_FALSE;
2273 (void) nvlist_lookup_uint64(newchild[c],
2274 ZPOOL_CONFIG_IS_LOG, &islog);
2275
2276 if (islog) {
2277 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2278 B_FALSE);
2279 print_vdev_stats(zhp, vname, oldnv ?
2280 oldchild[c] : NULL, newchild[c],
2281 cb, depth + 2);
2282 free(vname);
2283 }
2284 }
2285
2286 }
2287
2288 /*
2289 * Include level 2 ARC devices in iostat output
2290 */
2291 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2292 &newchild, &children) != 0)
2293 return;
2294
2295 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2296 &oldchild, &c) != 0)
2297 return;
2298
2299 if (children > 0) {
2300 (void) printf("%-*s - - - - - "
2301 "-\n", cb->cb_namewidth, "cache");
2302 for (c = 0; c < children; c++) {
2303 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2304 B_FALSE);
2305 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2306 newchild[c], cb, depth + 2);
2307 free(vname);
2308 }
2309 }
2310 }
2311
2312 static int
2313 refresh_iostat(zpool_handle_t *zhp, void *data)
2314 {
2315 iostat_cbdata_t *cb = data;
2316 boolean_t missing;
2317
2318 /*
2319 * If the pool has disappeared, remove it from the list and continue.
2320 */
2321 if (zpool_refresh_stats(zhp, &missing) != 0)
2322 return (-1);
2323
2324 if (missing)
2325 pool_list_remove(cb->cb_list, zhp);
2326
2327 return (0);
2328 }
2329
2330 /*
2331 * Callback to print out the iostats for the given pool.
2332 */
2333 int
2334 print_iostat(zpool_handle_t *zhp, void *data)
2335 {
2336 iostat_cbdata_t *cb = data;
2337 nvlist_t *oldconfig, *newconfig;
2338 nvlist_t *oldnvroot, *newnvroot;
2339
2340 newconfig = zpool_get_config(zhp, &oldconfig);
2341
2342 if (cb->cb_iteration == 1)
2343 oldconfig = NULL;
2344
2345 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2346 &newnvroot) == 0);
2347
2348 if (oldconfig == NULL)
2349 oldnvroot = NULL;
2350 else
2351 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2352 &oldnvroot) == 0);
2353
2354 /*
2355 * Print out the statistics for the pool.
2356 */
2357 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2358
2359 if (cb->cb_verbose)
2360 print_iostat_separator(cb);
2361
2362 return (0);
2363 }
2364
2365 int
2366 get_namewidth(zpool_handle_t *zhp, void *data)
2367 {
2368 iostat_cbdata_t *cb = data;
2369 nvlist_t *config, *nvroot;
2370
2371 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2372 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2373 &nvroot) == 0);
2374 if (!cb->cb_verbose)
2375 cb->cb_namewidth = strlen(zpool_get_name(zhp));
2376 else
2377 cb->cb_namewidth = max_width(zhp, nvroot, 0,
2378 cb->cb_namewidth);
2379 }
2380
2381 /*
2382 * The width must fall into the range [10,38]. The upper limit is the
2383 * maximum we can have and still fit in 80 columns.
2384 */
2385 if (cb->cb_namewidth < 10)
2386 cb->cb_namewidth = 10;
2387 if (cb->cb_namewidth > 38)
2388 cb->cb_namewidth = 38;
2389
2390 return (0);
2391 }
2392
2393 /*
2394 * Parse the input string, get the 'interval' and 'count' value if there is one.
2395 */
2396 static void
2397 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2398 unsigned long *cnt)
2399 {
2400 unsigned long interval = 0, count = 0;
2401 int argc = *argcp, errno;
2402
2403 /*
2404 * Determine if the last argument is an integer or a pool name
2405 */
2406 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2407 char *end;
2408
2409 errno = 0;
2410 interval = strtoul(argv[argc - 1], &end, 10);
2411
2412 if (*end == '\0' && errno == 0) {
2413 if (interval == 0) {
2414 (void) fprintf(stderr, gettext("interval "
2415 "cannot be zero\n"));
2416 usage(B_FALSE);
2417 }
2418 /*
2419 * Ignore the last parameter
2420 */
2421 argc--;
2422 } else {
2423 /*
2424 * If this is not a valid number, just plow on. The
2425 * user will get a more informative error message later
2426 * on.
2427 */
2428 interval = 0;
2429 }
2430 }
2431
2432 /*
2433 * If the last argument is also an integer, then we have both a count
2434 * and an interval.
2435 */
2436 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2437 char *end;
2438
2439 errno = 0;
2440 count = interval;
2441 interval = strtoul(argv[argc - 1], &end, 10);
2442
2443 if (*end == '\0' && errno == 0) {
2444 if (interval == 0) {
2445 (void) fprintf(stderr, gettext("interval "
2446 "cannot be zero\n"));
2447 usage(B_FALSE);
2448 }
2449
2450 /*
2451 * Ignore the last parameter
2452 */
2453 argc--;
2454 } else {
2455 interval = 0;
2456 }
2457 }
2458
2459 *iv = interval;
2460 *cnt = count;
2461 *argcp = argc;
2462 }
2463
2464 static void
2465 get_timestamp_arg(char c)
2466 {
2467 if (c == 'u')
2468 timestamp_fmt = UDATE;
2469 else if (c == 'd')
2470 timestamp_fmt = DDATE;
2471 else
2472 usage(B_FALSE);
2473 }
2474
2475 /*
2476 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2477 *
2478 * -v Display statistics for individual vdevs
2479 * -T Display a timestamp in date(1) or Unix format
2480 *
2481 * This command can be tricky because we want to be able to deal with pool
2482 * creation/destruction as well as vdev configuration changes. The bulk of this
2483 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
2484 * on pool_list_update() to detect the addition of new pools. Configuration
2485 * changes are all handled within libzfs.
2486 */
2487 int
2488 zpool_do_iostat(int argc, char **argv)
2489 {
2490 int c;
2491 int ret;
2492 int npools;
2493 unsigned long interval = 0, count = 0;
2494 zpool_list_t *list;
2495 boolean_t verbose = B_FALSE;
2496 iostat_cbdata_t cb;
2497
2498 /* check options */
2499 while ((c = getopt(argc, argv, "T:v")) != -1) {
2500 switch (c) {
2501 case 'T':
2502 get_timestamp_arg(*optarg);
2503 break;
2504 case 'v':
2505 verbose = B_TRUE;
2506 break;
2507 case '?':
2508 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2509 optopt);
2510 usage(B_FALSE);
2511 }
2512 }
2513
2514 argc -= optind;
2515 argv += optind;
2516
2517 get_interval_count(&argc, argv, &interval, &count);
2518
2519 /*
2520 * Construct the list of all interesting pools.
2521 */
2522 ret = 0;
2523 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2524 return (1);
2525
2526 if (pool_list_count(list) == 0 && argc != 0) {
2527 pool_list_free(list);
2528 return (1);
2529 }
2530
2531 if (pool_list_count(list) == 0 && interval == 0) {
2532 pool_list_free(list);
2533 (void) fprintf(stderr, gettext("no pools available\n"));
2534 return (1);
2535 }
2536
2537 /*
2538 * Enter the main iostat loop.
2539 */
2540 cb.cb_list = list;
2541 cb.cb_verbose = verbose;
2542 cb.cb_iteration = 0;
2543 cb.cb_namewidth = 0;
2544
2545 for (;;) {
2546 pool_list_update(list);
2547
2548 if ((npools = pool_list_count(list)) == 0)
2549 break;
2550
2551 /*
2552 * Refresh all statistics. This is done as an explicit step
2553 * before calculating the maximum name width, so that any
2554 * configuration changes are properly accounted for.
2555 */
2556 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2557
2558 /*
2559 * Iterate over all pools to determine the maximum width
2560 * for the pool / device name column across all pools.
2561 */
2562 cb.cb_namewidth = 0;
2563 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2564
2565 if (timestamp_fmt != NODATE)
2566 print_timestamp(timestamp_fmt);
2567
2568 /*
2569 * If it's the first time, or verbose mode, print the header.
2570 */
2571 if (++cb.cb_iteration == 1 || verbose)
2572 print_iostat_header(&cb);
2573
2574 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2575
2576 /*
2577 * If there's more than one pool, and we're not in verbose mode
2578 * (which prints a separator for us), then print a separator.
2579 */
2580 if (npools > 1 && !verbose)
2581 print_iostat_separator(&cb);
2582
2583 if (verbose)
2584 (void) printf("\n");
2585
2586 /*
2587 * Flush the output so that redirection to a file isn't buffered
2588 * indefinitely.
2589 */
2590 (void) fflush(stdout);
2591
2592 if (interval == 0)
2593 break;
2594
2595 if (count != 0 && --count == 0)
2596 break;
2597
2598 (void) sleep(interval);
2599 }
2600
2601 pool_list_free(list);
2602
2603 return (ret);
2604 }
2605
2606 typedef struct list_cbdata {
2607 boolean_t cb_verbose;
2608 int cb_namewidth;
2609 boolean_t cb_scripted;
2610 zprop_list_t *cb_proplist;
2611 } list_cbdata_t;
2612
2613 /*
2614 * Given a list of columns to display, output appropriate headers for each one.
2615 */
2616 static void
2617 print_header(list_cbdata_t *cb)
2618 {
2619 zprop_list_t *pl = cb->cb_proplist;
2620 char headerbuf[ZPOOL_MAXPROPLEN];
2621 const char *header;
2622 boolean_t first = B_TRUE;
2623 boolean_t right_justify;
2624 size_t width = 0;
2625
2626 for (; pl != NULL; pl = pl->pl_next) {
2627 width = pl->pl_width;
2628 if (first && cb->cb_verbose) {
2629 /*
2630 * Reset the width to accommodate the verbose listing
2631 * of devices.
2632 */
2633 width = cb->cb_namewidth;
2634 }
2635
2636 if (!first)
2637 (void) printf(" ");
2638 else
2639 first = B_FALSE;
2640
2641 right_justify = B_FALSE;
2642 if (pl->pl_prop != ZPROP_INVAL) {
2643 header = zpool_prop_column_name(pl->pl_prop);
2644 right_justify = zpool_prop_align_right(pl->pl_prop);
2645 } else {
2646 int i;
2647
2648 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
2649 headerbuf[i] = toupper(pl->pl_user_prop[i]);
2650 headerbuf[i] = '\0';
2651 header = headerbuf;
2652 }
2653
2654 if (pl->pl_next == NULL && !right_justify)
2655 (void) printf("%s", header);
2656 else if (right_justify)
2657 (void) printf("%*s", width, header);
2658 else
2659 (void) printf("%-*s", width, header);
2660
2661 }
2662
2663 (void) printf("\n");
2664 }
2665
2666 /*
2667 * Given a pool and a list of properties, print out all the properties according
2668 * to the described layout.
2669 */
2670 static void
2671 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
2672 {
2673 zprop_list_t *pl = cb->cb_proplist;
2674 boolean_t first = B_TRUE;
2675 char property[ZPOOL_MAXPROPLEN];
2676 char *propstr;
2677 boolean_t right_justify;
2678 size_t width;
2679
2680 for (; pl != NULL; pl = pl->pl_next) {
2681
2682 width = pl->pl_width;
2683 if (first && cb->cb_verbose) {
2684 /*
2685 * Reset the width to accommodate the verbose listing
2686 * of devices.
2687 */
2688 width = cb->cb_namewidth;
2689 }
2690
2691 if (!first) {
2692 if (cb->cb_scripted)
2693 (void) printf("\t");
2694 else
2695 (void) printf(" ");
2696 } else {
2697 first = B_FALSE;
2698 }
2699
2700 right_justify = B_FALSE;
2701 if (pl->pl_prop != ZPROP_INVAL) {
2702 if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ &&
2703 zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0)
2704 propstr = "-";
2705 else if (zpool_get_prop(zhp, pl->pl_prop, property,
2706 sizeof (property), NULL) != 0)
2707 propstr = "-";
2708 else
2709 propstr = property;
2710
2711 right_justify = zpool_prop_align_right(pl->pl_prop);
2712 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
2713 zpool_prop_unsupported(pl->pl_user_prop)) &&
2714 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
2715 sizeof (property)) == 0) {
2716 propstr = property;
2717 } else {
2718 propstr = "-";
2719 }
2720
2721
2722 /*
2723 * If this is being called in scripted mode, or if this is the
2724 * last column and it is left-justified, don't include a width
2725 * format specifier.
2726 */
2727 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
2728 (void) printf("%s", propstr);
2729 else if (right_justify)
2730 (void) printf("%*s", width, propstr);
2731 else
2732 (void) printf("%-*s", width, propstr);
2733 }
2734
2735 (void) printf("\n");
2736 }
2737
2738 static void
2739 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted)
2740 {
2741 char propval[64];
2742 boolean_t fixed;
2743 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
2744
2745 zfs_nicenum(value, propval, sizeof (propval));
2746
2747 if (prop == ZPOOL_PROP_EXPANDSZ && value == 0)
2748 (void) strlcpy(propval, "-", sizeof (propval));
2749
2750 if (scripted)
2751 (void) printf("\t%s", propval);
2752 else
2753 (void) printf(" %*s", width, propval);
2754 }
2755
2756 void
2757 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2758 list_cbdata_t *cb, int depth)
2759 {
2760 nvlist_t **child;
2761 vdev_stat_t *vs;
2762 uint_t c, children;
2763 char *vname;
2764 boolean_t scripted = cb->cb_scripted;
2765
2766 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2767 (uint64_t **)&vs, &c) == 0);
2768
2769 if (name != NULL) {
2770 if (scripted)
2771 (void) printf("\t%s", name);
2772 else if (strlen(name) + depth > cb->cb_namewidth)
2773 (void) printf("%*s%s", depth, "", name);
2774 else
2775 (void) printf("%*s%s%*s", depth, "", name,
2776 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2777
2778 /* only toplevel vdevs have capacity stats */
2779 if (vs->vs_space == 0) {
2780 if (scripted)
2781 (void) printf("\t-\t-\t-");
2782 else
2783 (void) printf(" - - -");
2784 } else {
2785 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space,
2786 scripted);
2787 print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc,
2788 scripted);
2789 print_one_column(ZPOOL_PROP_FREE,
2790 vs->vs_space - vs->vs_alloc, scripted);
2791 }
2792 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize,
2793 scripted);
2794 (void) printf("\n");
2795 }
2796
2797 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2798 &child, &children) != 0)
2799 return;
2800
2801 for (c = 0; c < children; c++) {
2802 uint64_t ishole = B_FALSE;
2803
2804 if (nvlist_lookup_uint64(child[c],
2805 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
2806 continue;
2807
2808 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
2809 print_list_stats(zhp, vname, child[c], cb, depth + 2);
2810 free(vname);
2811 }
2812
2813 /*
2814 * Include level 2 ARC devices in iostat output
2815 */
2816 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2817 &child, &children) != 0)
2818 return;
2819
2820 if (children > 0) {
2821 (void) printf("%-*s - - - - - "
2822 "-\n", cb->cb_namewidth, "cache");
2823 for (c = 0; c < children; c++) {
2824 vname = zpool_vdev_name(g_zfs, zhp, child[c],
2825 B_FALSE);
2826 print_list_stats(zhp, vname, child[c], cb, depth + 2);
2827 free(vname);
2828 }
2829 }
2830 }
2831
2832
2833 /*
2834 * Generic callback function to list a pool.
2835 */
2836 int
2837 list_callback(zpool_handle_t *zhp, void *data)
2838 {
2839 list_cbdata_t *cbp = data;
2840 nvlist_t *config;
2841 nvlist_t *nvroot;
2842
2843 config = zpool_get_config(zhp, NULL);
2844
2845 print_pool(zhp, cbp);
2846 if (!cbp->cb_verbose)
2847 return (0);
2848
2849 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2850 &nvroot) == 0);
2851 print_list_stats(zhp, NULL, nvroot, cbp, 0);
2852
2853 return (0);
2854 }
2855
2856 /*
2857 * zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
2858 *
2859 * -H Scripted mode. Don't display headers, and separate properties
2860 * by a single tab.
2861 * -o List of properties to display. Defaults to
2862 * "name,size,allocated,free,capacity,health,altroot"
2863 * -T Display a timestamp in date(1) or Unix format
2864 *
2865 * List all pools in the system, whether or not they're healthy. Output space
2866 * statistics for each one, as well as health status summary.
2867 */
2868 int
2869 zpool_do_list(int argc, char **argv)
2870 {
2871 int c;
2872 int ret;
2873 list_cbdata_t cb = { 0 };
2874 static char default_props[] =
2875 "name,size,allocated,free,expandsize,capacity,dedupratio,"
2876 "health,altroot";
2877 char *props = default_props;
2878 unsigned long interval = 0, count = 0;
2879 zpool_list_t *list;
2880 boolean_t first = B_TRUE;
2881
2882 /* check options */
2883 while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
2884 switch (c) {
2885 case 'H':
2886 cb.cb_scripted = B_TRUE;
2887 break;
2888 case 'o':
2889 props = optarg;
2890 break;
2891 case 'T':
2892 get_timestamp_arg(*optarg);
2893 break;
2894 case 'v':
2895 cb.cb_verbose = B_TRUE;
2896 break;
2897 case ':':
2898 (void) fprintf(stderr, gettext("missing argument for "
2899 "'%c' option\n"), optopt);
2900 usage(B_FALSE);
2901 break;
2902 case '?':
2903 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2904 optopt);
2905 usage(B_FALSE);
2906 }
2907 }
2908
2909 argc -= optind;
2910 argv += optind;
2911
2912 get_interval_count(&argc, argv, &interval, &count);
2913
2914 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2915 usage(B_FALSE);
2916
2917 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, &ret)) == NULL)
2918 return (1);
2919
2920 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
2921 (void) printf(gettext("no pools available\n"));
2922 zprop_free_list(cb.cb_proplist);
2923 return (0);
2924 }
2925
2926 for (;;) {
2927 pool_list_update(list);
2928
2929 if (pool_list_count(list) == 0)
2930 break;
2931
2932 cb.cb_namewidth = 0;
2933 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2934
2935 if (timestamp_fmt != NODATE)
2936 print_timestamp(timestamp_fmt);
2937
2938 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
2939 print_header(&cb);
2940 first = B_FALSE;
2941 }
2942 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
2943
2944 if (interval == 0)
2945 break;
2946
2947 if (count != 0 && --count == 0)
2948 break;
2949
2950 (void) sleep(interval);
2951 }
2952
2953 zprop_free_list(cb.cb_proplist);
2954 return (ret);
2955 }
2956
2957 static nvlist_t *
2958 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2959 {
2960 nvlist_t **child;
2961 uint_t c, children;
2962 nvlist_t *match;
2963 char *path;
2964
2965 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2966 &child, &children) != 0) {
2967 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2968 if (strncmp(name, "/dev/dsk/", 9) == 0)
2969 name += 9;
2970 if (strncmp(path, "/dev/dsk/", 9) == 0)
2971 path += 9;
2972 if (strcmp(name, path) == 0)
2973 return (nv);
2974 return (NULL);
2975 }
2976
2977 for (c = 0; c < children; c++)
2978 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2979 return (match);
2980
2981 return (NULL);
2982 }
2983
2984 static int
2985 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2986 {
2987 boolean_t force = B_FALSE;
2988 int c;
2989 nvlist_t *nvroot;
2990 char *poolname, *old_disk, *new_disk;
2991 zpool_handle_t *zhp;
2992 int ret;
2993
2994 /* check options */
2995 while ((c = getopt(argc, argv, "f")) != -1) {
2996 switch (c) {
2997 case 'f':
2998 force = B_TRUE;
2999 break;
3000 case '?':
3001 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3002 optopt);
3003 usage(B_FALSE);
3004 }
3005 }
3006
3007 argc -= optind;
3008 argv += optind;
3009
3010 /* get pool name and check number of arguments */
3011 if (argc < 1) {
3012 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3013 usage(B_FALSE);
3014 }
3015
3016 poolname = argv[0];
3017
3018 if (argc < 2) {
3019 (void) fprintf(stderr,
3020 gettext("missing <device> specification\n"));
3021 usage(B_FALSE);
3022 }
3023
3024 old_disk = argv[1];
3025
3026 if (argc < 3) {
3027 if (!replacing) {
3028 (void) fprintf(stderr,
3029 gettext("missing <new_device> specification\n"));
3030 usage(B_FALSE);
3031 }
3032 new_disk = old_disk;
3033 argc -= 1;
3034 argv += 1;
3035 } else {
3036 new_disk = argv[2];
3037 argc -= 2;
3038 argv += 2;
3039 }
3040
3041 if (argc > 1) {
3042 (void) fprintf(stderr, gettext("too many arguments\n"));
3043 usage(B_FALSE);
3044 }
3045
3046 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3047 return (1);
3048
3049 if (zpool_get_config(zhp, NULL) == NULL) {
3050 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3051 poolname);
3052 zpool_close(zhp);
3053 return (1);
3054 }
3055
3056 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3057 argc, argv);
3058 if (nvroot == NULL) {
3059 zpool_close(zhp);
3060 return (1);
3061 }
3062
3063 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3064
3065 nvlist_free(nvroot);
3066 zpool_close(zhp);
3067
3068 return (ret);
3069 }
3070
3071 /*
3072 * zpool replace [-f] <pool> <device> <new_device>
3073 *
3074 * -f Force attach, even if <new_device> appears to be in use.
3075 *
3076 * Replace <device> with <new_device>.
3077 */
3078 /* ARGSUSED */
3079 int
3080 zpool_do_replace(int argc, char **argv)
3081 {
3082 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3083 }
3084
3085 /*
3086 * zpool attach [-f] <pool> <device> <new_device>
3087 *
3088 * -f Force attach, even if <new_device> appears to be in use.
3089 *
3090 * Attach <new_device> to the mirror containing <device>. If <device> is not
3091 * part of a mirror, then <device> will be transformed into a mirror of
3092 * <device> and <new_device>. In either case, <new_device> will begin life
3093 * with a DTL of [0, now], and will immediately begin to resilver itself.
3094 */
3095 int
3096 zpool_do_attach(int argc, char **argv)
3097 {
3098 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3099 }
3100
3101 /*
3102 * zpool detach [-f] <pool> <device>
3103 *
3104 * -f Force detach of <device>, even if DTLs argue against it
3105 * (not supported yet)
3106 *
3107 * Detach a device from a mirror. The operation will be refused if <device>
3108 * is the last device in the mirror, or if the DTLs indicate that this device
3109 * has the only valid copy of some data.
3110 */
3111 /* ARGSUSED */
3112 int
3113 zpool_do_detach(int argc, char **argv)
3114 {
3115 int c;
3116 char *poolname, *path;
3117 zpool_handle_t *zhp;
3118 int ret;
3119
3120 /* check options */
3121 while ((c = getopt(argc, argv, "f")) != -1) {
3122 switch (c) {
3123 case 'f':
3124 case '?':
3125 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3126 optopt);
3127 usage(B_FALSE);
3128 }
3129 }
3130
3131 argc -= optind;
3132 argv += optind;
3133
3134 /* get pool name and check number of arguments */
3135 if (argc < 1) {
3136 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3137 usage(B_FALSE);
3138 }
3139
3140 if (argc < 2) {
3141 (void) fprintf(stderr,
3142 gettext("missing <device> specification\n"));
3143 usage(B_FALSE);
3144 }
3145
3146 poolname = argv[0];
3147 path = argv[1];
3148
3149 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3150 return (1);
3151
3152 ret = zpool_vdev_detach(zhp, path);
3153
3154 zpool_close(zhp);
3155
3156 return (ret);
3157 }
3158
3159 /*
3160 * zpool split [-n] [-o prop=val] ...
3161 * [-o mntopt] ...
3162 * [-R altroot] <pool> <newpool> [<device> ...]
3163 *
3164 * -n Do not split the pool, but display the resulting layout if
3165 * it were to be split.
3166 * -o Set property=value, or set mount options.
3167 * -R Mount the split-off pool under an alternate root.
3168 *
3169 * Splits the named pool and gives it the new pool name. Devices to be split
3170 * off may be listed, provided that no more than one device is specified
3171 * per top-level vdev mirror. The newly split pool is left in an exported
3172 * state unless -R is specified.
3173 *
3174 * Restrictions: the top-level of the pool pool must only be made up of
3175 * mirrors; all devices in the pool must be healthy; no device may be
3176 * undergoing a resilvering operation.
3177 */
3178 int
3179 zpool_do_split(int argc, char **argv)
3180 {
3181 char *srcpool, *newpool, *propval;
3182 char *mntopts = NULL;
3183 splitflags_t flags;
3184 int c, ret = 0;
3185 zpool_handle_t *zhp;
3186 nvlist_t *config, *props = NULL;
3187
3188 flags.dryrun = B_FALSE;
3189 flags.import = B_FALSE;
3190
3191 /* check options */
3192 while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3193 switch (c) {
3194 case 'R':
3195 flags.import = B_TRUE;
3196 if (add_prop_list(
3197 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3198 &props, B_TRUE) != 0) {
3199 if (props)
3200 nvlist_free(props);
3201 usage(B_FALSE);
3202 }
3203 break;
3204 case 'n':
3205 flags.dryrun = B_TRUE;
3206 break;
3207 case 'o':
3208 if ((propval = strchr(optarg, '=')) != NULL) {
3209 *propval = '\0';
3210 propval++;
3211 if (add_prop_list(optarg, propval,
3212 &props, B_TRUE) != 0) {
3213 if (props)
3214 nvlist_free(props);
3215 usage(B_FALSE);
3216 }
3217 } else {
3218 mntopts = optarg;
3219 }
3220 break;
3221 case ':':
3222 (void) fprintf(stderr, gettext("missing argument for "
3223 "'%c' option\n"), optopt);
3224 usage(B_FALSE);
3225 break;
3226 case '?':
3227 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3228 optopt);
3229 usage(B_FALSE);
3230 break;
3231 }
3232 }
3233
3234 if (!flags.import && mntopts != NULL) {
3235 (void) fprintf(stderr, gettext("setting mntopts is only "
3236 "valid when importing the pool\n"));
3237 usage(B_FALSE);
3238 }
3239
3240 argc -= optind;
3241 argv += optind;
3242
3243 if (argc < 1) {
3244 (void) fprintf(stderr, gettext("Missing pool name\n"));
3245 usage(B_FALSE);
3246 }
3247 if (argc < 2) {
3248 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3249 usage(B_FALSE);
3250 }
3251
3252 srcpool = argv[0];
3253 newpool = argv[1];
3254
3255 argc -= 2;
3256 argv += 2;
3257
3258 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3259 return (1);
3260
3261 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3262 if (config == NULL) {
3263 ret = 1;
3264 } else {
3265 if (flags.dryrun) {
3266 (void) printf(gettext("would create '%s' with the "
3267 "following layout:\n\n"), newpool);
3268 print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3269 }
3270 nvlist_free(config);
3271 }
3272
3273 zpool_close(zhp);
3274
3275 if (ret != 0 || flags.dryrun || !flags.import)
3276 return (ret);
3277
3278 /*
3279 * The split was successful. Now we need to open the new
3280 * pool and import it.
3281 */
3282 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3283 return (1);
3284 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3285 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3286 ret = 1;
3287 (void) fprintf(stderr, gettext("Split was successful, but "
3288 "the datasets could not all be mounted\n"));
3289 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3290 "different altroot\n"), "zpool import");
3291 }
3292 zpool_close(zhp);
3293
3294 return (ret);
3295 }
3296
3297
3298
3299 /*
3300 * zpool online <pool> <device> ...
3301 */
3302 int
3303 zpool_do_online(int argc, char **argv)
3304 {
3305 int c, i;
3306 char *poolname;
3307 zpool_handle_t *zhp;
3308 int ret = 0;
3309 vdev_state_t newstate;
3310 int flags = 0;
3311
3312 /* check options */
3313 while ((c = getopt(argc, argv, "et")) != -1) {
3314 switch (c) {
3315 case 'e':
3316 flags |= ZFS_ONLINE_EXPAND;
3317 break;
3318 case 't':
3319 case '?':
3320 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3321 optopt);
3322 usage(B_FALSE);
3323 }
3324 }
3325
3326 argc -= optind;
3327 argv += optind;
3328
3329 /* get pool name and check number of arguments */
3330 if (argc < 1) {
3331 (void) fprintf(stderr, gettext("missing pool name\n"));
3332 usage(B_FALSE);
3333 }
3334 if (argc < 2) {
3335 (void) fprintf(stderr, gettext("missing device name\n"));
3336 usage(B_FALSE);
3337 }
3338
3339 poolname = argv[0];
3340
3341 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3342 return (1);
3343
3344 for (i = 1; i < argc; i++) {
3345 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3346 if (newstate != VDEV_STATE_HEALTHY) {
3347 (void) printf(gettext("warning: device '%s' "
3348 "onlined, but remains in faulted state\n"),
3349 argv[i]);
3350 if (newstate == VDEV_STATE_FAULTED)
3351 (void) printf(gettext("use 'zpool "
3352 "clear' to restore a faulted "
3353 "device\n"));
3354 else
3355 (void) printf(gettext("use 'zpool "
3356 "replace' to replace devices "
3357 "that are no longer present\n"));
3358 }
3359 } else {
3360 ret = 1;
3361 }
3362 }
3363
3364 zpool_close(zhp);
3365
3366 return (ret);
3367 }
3368
3369 /*
3370 * zpool offline [-ft] <pool> <device> ...
3371 *
3372 * -f Force the device into the offline state, even if doing
3373 * so would appear to compromise pool availability.
3374 * (not supported yet)
3375 *
3376 * -t Only take the device off-line temporarily. The offline
3377 * state will not be persistent across reboots.
3378 */
3379 /* ARGSUSED */
3380 int
3381 zpool_do_offline(int argc, char **argv)
3382 {
3383 int c, i;
3384 char *poolname;
3385 zpool_handle_t *zhp;
3386 int ret = 0;
3387 boolean_t istmp = B_FALSE;
3388
3389 /* check options */
3390 while ((c = getopt(argc, argv, "ft")) != -1) {
3391 switch (c) {
3392 case 't':
3393 istmp = B_TRUE;
3394 break;
3395 case 'f':
3396 case '?':
3397 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3398 optopt);
3399 usage(B_FALSE);
3400 }
3401 }
3402
3403 argc -= optind;
3404 argv += optind;
3405
3406 /* get pool name and check number of arguments */
3407 if (argc < 1) {
3408 (void) fprintf(stderr, gettext("missing pool name\n"));
3409 usage(B_FALSE);
3410 }
3411 if (argc < 2) {
3412 (void) fprintf(stderr, gettext("missing device name\n"));
3413 usage(B_FALSE);
3414 }
3415
3416 poolname = argv[0];
3417
3418 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3419 return (1);
3420
3421 for (i = 1; i < argc; i++) {
3422 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3423 ret = 1;
3424 }
3425
3426 zpool_close(zhp);
3427
3428 return (ret);
3429 }
3430
3431 /*
3432 * zpool clear <pool> [device]
3433 *
3434 * Clear all errors associated with a pool or a particular device.
3435 */
3436 int
3437 zpool_do_clear(int argc, char **argv)
3438 {
3439 int c;
3440 int ret = 0;
3441 boolean_t dryrun = B_FALSE;
3442 boolean_t do_rewind = B_FALSE;
3443 boolean_t xtreme_rewind = B_FALSE;
3444 uint32_t rewind_policy = ZPOOL_NO_REWIND;
3445 nvlist_t *policy = NULL;
3446 zpool_handle_t *zhp;
3447 char *pool, *device;
3448
3449 /* check options */
3450 while ((c = getopt(argc, argv, "FnX")) != -1) {
3451 switch (c) {
3452 case 'F':
3453 do_rewind = B_TRUE;
3454 break;
3455 case 'n':
3456 dryrun = B_TRUE;
3457 break;
3458 case 'X':
3459 xtreme_rewind = B_TRUE;
3460 break;
3461 case '?':
3462 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3463 optopt);
3464 usage(B_FALSE);
3465 }
3466 }
3467
3468 argc -= optind;
3469 argv += optind;
3470
3471 if (argc < 1) {
3472 (void) fprintf(stderr, gettext("missing pool name\n"));
3473 usage(B_FALSE);
3474 }
3475
3476 if (argc > 2) {
3477 (void) fprintf(stderr, gettext("too many arguments\n"));
3478 usage(B_FALSE);
3479 }
3480
3481 if ((dryrun || xtreme_rewind) && !do_rewind) {
3482 (void) fprintf(stderr,
3483 gettext("-n or -X only meaningful with -F\n"));
3484 usage(B_FALSE);
3485 }
3486 if (dryrun)
3487 rewind_policy = ZPOOL_TRY_REWIND;
3488 else if (do_rewind)
3489 rewind_policy = ZPOOL_DO_REWIND;
3490 if (xtreme_rewind)
3491 rewind_policy |= ZPOOL_EXTREME_REWIND;
3492
3493 /* In future, further rewind policy choices can be passed along here */
3494 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3495 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3496 return (1);
3497
3498 pool = argv[0];
3499 device = argc == 2 ? argv[1] : NULL;
3500
3501 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3502 nvlist_free(policy);
3503 return (1);
3504 }
3505
3506 if (zpool_clear(zhp, device, policy) != 0)
3507 ret = 1;
3508
3509 zpool_close(zhp);
3510
3511 nvlist_free(policy);
3512
3513 return (ret);
3514 }
3515
3516 /*
3517 * zpool reguid <pool>
3518 */
3519 int
3520 zpool_do_reguid(int argc, char **argv)
3521 {
3522 int c;
3523 char *poolname;
3524 zpool_handle_t *zhp;
3525 int ret = 0;
3526
3527 /* check options */
3528 while ((c = getopt(argc, argv, "")) != -1) {
3529 switch (c) {
3530 case '?':
3531 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3532 optopt);
3533 usage(B_FALSE);
3534 }
3535 }
3536
3537 argc -= optind;
3538 argv += optind;
3539
3540 /* get pool name and check number of arguments */
3541 if (argc < 1) {
3542 (void) fprintf(stderr, gettext("missing pool name\n"));
3543 usage(B_FALSE);
3544 }
3545
3546 if (argc > 1) {
3547 (void) fprintf(stderr, gettext("too many arguments\n"));
3548 usage(B_FALSE);
3549 }
3550
3551 poolname = argv[0];
3552 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3553 return (1);
3554
3555 ret = zpool_reguid(zhp);
3556
3557 zpool_close(zhp);
3558 return (ret);
3559 }
3560
3561
3562 /*
3563 * zpool reopen <pool>
3564 *
3565 * Reopen the pool so that the kernel can update the sizes of all vdevs.
3566 */
3567 int
3568 zpool_do_reopen(int argc, char **argv)
3569 {
3570 int c;
3571 int ret = 0;
3572 zpool_handle_t *zhp;
3573 char *pool;
3574
3575 /* check options */
3576 while ((c = getopt(argc, argv, "")) != -1) {
3577 switch (c) {
3578 case '?':
3579 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3580 optopt);
3581 usage(B_FALSE);
3582 }
3583 }
3584
3585 argc--;
3586 argv++;
3587
3588 if (argc < 1) {
3589 (void) fprintf(stderr, gettext("missing pool name\n"));
3590 usage(B_FALSE);
3591 }
3592
3593 if (argc > 1) {
3594 (void) fprintf(stderr, gettext("too many arguments\n"));
3595 usage(B_FALSE);
3596 }
3597
3598 pool = argv[0];
3599 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
3600 return (1);
3601
3602 ret = zpool_reopen(zhp);
3603 zpool_close(zhp);
3604 return (ret);
3605 }
3606
3607 typedef struct scrub_cbdata {
3608 int cb_type;
3609 int cb_argc;
3610 char **cb_argv;
3611 } scrub_cbdata_t;
3612
3613 int
3614 scrub_callback(zpool_handle_t *zhp, void *data)
3615 {
3616 scrub_cbdata_t *cb = data;
3617 int err;
3618
3619 /*
3620 * Ignore faulted pools.
3621 */
3622 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3623 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3624 "currently unavailable\n"), zpool_get_name(zhp));
3625 return (1);
3626 }
3627
3628 err = zpool_scan(zhp, cb->cb_type);
3629
3630 return (err != 0);
3631 }
3632
3633 /*
3634 * zpool scrub [-s] <pool> ...
3635 *
3636 * -s Stop. Stops any in-progress scrub.
3637 */
3638 int
3639 zpool_do_scrub(int argc, char **argv)
3640 {
3641 int c;
3642 scrub_cbdata_t cb;
3643
3644 cb.cb_type = POOL_SCAN_SCRUB;
3645
3646 /* check options */
3647 while ((c = getopt(argc, argv, "s")) != -1) {
3648 switch (c) {
3649 case 's':
3650 cb.cb_type = POOL_SCAN_NONE;
3651 break;
3652 case '?':
3653 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3654 optopt);
3655 usage(B_FALSE);
3656 }
3657 }
3658
3659 cb.cb_argc = argc;
3660 cb.cb_argv = argv;
3661 argc -= optind;
3662 argv += optind;
3663
3664 if (argc < 1) {
3665 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3666 usage(B_FALSE);
3667 }
3668
3669 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
3670 }
3671
3672 typedef struct status_cbdata {
3673 int cb_count;
3674 boolean_t cb_allpools;
3675 boolean_t cb_verbose;
3676 boolean_t cb_explain;
3677 boolean_t cb_first;
3678 boolean_t cb_dedup_stats;
3679 } status_cbdata_t;
3680
3681 /*
3682 * Print out detailed scrub status.
3683 */
3684 void
3685 print_scan_status(pool_scan_stat_t *ps)
3686 {
3687 time_t start, end;
3688 uint64_t elapsed, mins_left, hours_left;
3689 uint64_t pass_exam, examined, total;
3690 uint_t rate;
3691 double fraction_done;
3692 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
3693
3694 (void) printf(gettext(" scan: "));
3695
3696 /* If there's never been a scan, there's not much to say. */
3697 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
3698 ps->pss_func >= POOL_SCAN_FUNCS) {
3699 (void) printf(gettext("none requested\n"));
3700 return;
3701 }
3702
3703 start = ps->pss_start_time;
3704 end = ps->pss_end_time;
3705 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
3706
3707 assert(ps->pss_func == POOL_SCAN_SCRUB ||
3708 ps->pss_func == POOL_SCAN_RESILVER);
3709 /*
3710 * Scan is finished or canceled.
3711 */
3712 if (ps->pss_state == DSS_FINISHED) {
3713 uint64_t minutes_taken = (end - start) / 60;
3714 char *fmt;
3715
3716 if (ps->pss_func == POOL_SCAN_SCRUB) {
3717 fmt = gettext("scrub repaired %s in %lluh%um with "
3718 "%llu errors on %s");
3719 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3720 fmt = gettext("resilvered %s in %lluh%um with "
3721 "%llu errors on %s");
3722 }
3723 /* LINTED */
3724 (void) printf(fmt, processed_buf,
3725 (u_longlong_t)(minutes_taken / 60),
3726 (uint_t)(minutes_taken % 60),
3727 (u_longlong_t)ps->pss_errors,
3728 ctime((time_t *)&end));
3729 return;
3730 } else if (ps->pss_state == DSS_CANCELED) {
3731 if (ps->pss_func == POOL_SCAN_SCRUB) {
3732 (void) printf(gettext("scrub canceled on %s"),
3733 ctime(&end));
3734 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3735 (void) printf(gettext("resilver canceled on %s"),
3736 ctime(&end));
3737 }
3738 return;
3739 }
3740
3741 assert(ps->pss_state == DSS_SCANNING);
3742
3743 /*
3744 * Scan is in progress.
3745 */
3746 if (ps->pss_func == POOL_SCAN_SCRUB) {
3747 (void) printf(gettext("scrub in progress since %s"),
3748 ctime(&start));
3749 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3750 (void) printf(gettext("resilver in progress since %s"),
3751 ctime(&start));
3752 }
3753
3754 examined = ps->pss_examined ? ps->pss_examined : 1;
3755 total = ps->pss_to_examine;
3756 fraction_done = (double)examined / total;
3757
3758 /* elapsed time for this pass */
3759 elapsed = time(NULL) - ps->pss_pass_start;
3760 elapsed = elapsed ? elapsed : 1;
3761 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
3762 rate = pass_exam / elapsed;
3763 rate = rate ? rate : 1;
3764 mins_left = ((total - examined) / rate) / 60;
3765 hours_left = mins_left / 60;
3766
3767 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
3768 zfs_nicenum(total, total_buf, sizeof (total_buf));
3769 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
3770
3771 /*
3772 * do not print estimated time if hours_left is more than 30 days
3773 */
3774 (void) printf(gettext(" %s scanned out of %s at %s/s"),
3775 examined_buf, total_buf, rate_buf);
3776 if (hours_left < (30 * 24)) {
3777 (void) printf(gettext(", %lluh%um to go\n"),
3778 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
3779 } else {
3780 (void) printf(gettext(
3781 ", (scan is slow, no estimated time)\n"));
3782 }
3783
3784 if (ps->pss_func == POOL_SCAN_RESILVER) {
3785 (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
3786 processed_buf, 100 * fraction_done);
3787 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
3788 (void) printf(gettext(" %s repaired, %.2f%% done\n"),
3789 processed_buf, 100 * fraction_done);
3790 }
3791 }
3792
3793 static void
3794 print_error_log(zpool_handle_t *zhp)
3795 {
3796 nvlist_t *nverrlist = NULL;
3797 nvpair_t *elem;
3798 char *pathname;
3799 size_t len = MAXPATHLEN * 2;
3800
3801 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
3802 (void) printf("errors: List of errors unavailable "
3803 "(insufficient privileges)\n");
3804 return;
3805 }
3806
3807 (void) printf("errors: Permanent errors have been "
3808 "detected in the following files:\n\n");
3809
3810 pathname = safe_malloc(len);
3811 elem = NULL;
3812 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
3813 nvlist_t *nv;
3814 uint64_t dsobj, obj;
3815
3816 verify(nvpair_value_nvlist(elem, &nv) == 0);
3817 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
3818 &dsobj) == 0);
3819 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
3820 &obj) == 0);
3821 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
3822 (void) printf("%7s %s\n", "", pathname);
3823 }
3824 free(pathname);
3825 nvlist_free(nverrlist);
3826 }
3827
3828 static void
3829 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
3830 int namewidth)
3831 {
3832 uint_t i;
3833 char *name;
3834
3835 if (nspares == 0)
3836 return;
3837
3838 (void) printf(gettext("\tspares\n"));
3839
3840 for (i = 0; i < nspares; i++) {
3841 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
3842 print_status_config(zhp, name, spares[i],
3843 namewidth, 2, B_TRUE);
3844 free(name);
3845 }
3846 }
3847
3848 static void
3849 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
3850 int namewidth)
3851 {
3852 uint_t i;
3853 char *name;
3854
3855 if (nl2cache == 0)
3856 return;
3857
3858 (void) printf(gettext("\tcache\n"));
3859
3860 for (i = 0; i < nl2cache; i++) {
3861 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
3862 print_status_config(zhp, name, l2cache[i],
3863 namewidth, 2, B_FALSE);
3864 free(name);
3865 }
3866 }
3867
3868 static void
3869 print_dedup_stats(nvlist_t *config)
3870 {
3871 ddt_histogram_t *ddh;
3872 ddt_stat_t *dds;
3873 ddt_object_t *ddo;
3874 uint_t c;
3875
3876 /*
3877 * If the pool was faulted then we may not have been able to
3878 * obtain the config. Otherwise, if we have anything in the dedup
3879 * table continue processing the stats.
3880 */
3881 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
3882 (uint64_t **)&ddo, &c) != 0)
3883 return;
3884
3885 (void) printf("\n");
3886 (void) printf(gettext(" dedup: "));
3887 if (ddo->ddo_count == 0) {
3888 (void) printf(gettext("no DDT entries\n"));
3889 return;
3890 }
3891
3892 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
3893 (u_longlong_t)ddo->ddo_count,
3894 (u_longlong_t)ddo->ddo_dspace,
3895 (u_longlong_t)ddo->ddo_mspace);
3896
3897 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
3898 (uint64_t **)&dds, &c) == 0);
3899 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
3900 (uint64_t **)&ddh, &c) == 0);
3901 zpool_dump_ddt(dds, ddh);
3902 }
3903
3904 /*
3905 * Display a summary of pool status. Displays a summary such as:
3906 *
3907 * pool: tank
3908 * status: DEGRADED
3909 * reason: One or more devices ...
3910 * see: http://illumos.org/msg/ZFS-xxxx-01
3911 * config:
3912 * mirror DEGRADED
3913 * c1t0d0 OK
3914 * c2t0d0 UNAVAIL
3915 *
3916 * When given the '-v' option, we print out the complete config. If the '-e'
3917 * option is specified, then we print out error rate information as well.
3918 */
3919 int
3920 status_callback(zpool_handle_t *zhp, void *data)
3921 {
3922 status_cbdata_t *cbp = data;
3923 nvlist_t *config, *nvroot;
3924 char *msgid;
3925 int reason;
3926 const char *health;
3927 uint_t c;
3928 vdev_stat_t *vs;
3929
3930 config = zpool_get_config(zhp, NULL);
3931 reason = zpool_get_status(zhp, &msgid);
3932
3933 cbp->cb_count++;
3934
3935 /*
3936 * If we were given 'zpool status -x', only report those pools with
3937 * problems.
3938 */
3939 if (cbp->cb_explain &&
3940 (reason == ZPOOL_STATUS_OK ||
3941 reason == ZPOOL_STATUS_VERSION_OLDER ||
3942 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
3943 if (!cbp->cb_allpools) {
3944 (void) printf(gettext("pool '%s' is healthy\n"),
3945 zpool_get_name(zhp));
3946 if (cbp->cb_first)
3947 cbp->cb_first = B_FALSE;
3948 }
3949 return (0);
3950 }
3951
3952 if (cbp->cb_first)
3953 cbp->cb_first = B_FALSE;
3954 else
3955 (void) printf("\n");
3956
3957 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3958 &nvroot) == 0);
3959 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
3960 (uint64_t **)&vs, &c) == 0);
3961 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3962
3963 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
3964 (void) printf(gettext(" state: %s\n"), health);
3965
3966 switch (reason) {
3967 case ZPOOL_STATUS_MISSING_DEV_R:
3968 (void) printf(gettext("status: One or more devices could not "
3969 "be opened. Sufficient replicas exist for\n\tthe pool to "
3970 "continue functioning in a degraded state.\n"));
3971 (void) printf(gettext("action: Attach the missing device and "
3972 "online it using 'zpool online'.\n"));
3973 break;
3974
3975 case ZPOOL_STATUS_MISSING_DEV_NR:
3976 (void) printf(gettext("status: One or more devices could not "
3977 "be opened. There are insufficient\n\treplicas for the "
3978 "pool to continue functioning.\n"));
3979 (void) printf(gettext("action: Attach the missing device and "
3980 "online it using 'zpool online'.\n"));
3981 break;
3982
3983 case ZPOOL_STATUS_CORRUPT_LABEL_R:
3984 (void) printf(gettext("status: One or more devices could not "
3985 "be used because the label is missing or\n\tinvalid. "
3986 "Sufficient replicas exist for the pool to continue\n\t"
3987 "functioning in a degraded state.\n"));
3988 (void) printf(gettext("action: Replace the device using "
3989 "'zpool replace'.\n"));
3990 break;
3991
3992 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3993 (void) printf(gettext("status: One or more devices could not "
3994 "be used because the label is missing \n\tor invalid. "
3995 "There are insufficient replicas for the pool to "
3996 "continue\n\tfunctioning.\n"));
3997 zpool_explain_recover(zpool_get_handle(zhp),
3998 zpool_get_name(zhp), reason, config);
3999 break;
4000
4001 case ZPOOL_STATUS_FAILING_DEV:
4002 (void) printf(gettext("status: One or more devices has "
4003 "experienced an unrecoverable error. An\n\tattempt was "
4004 "made to correct the error. Applications are "
4005 "unaffected.\n"));
4006 (void) printf(gettext("action: Determine if the device needs "
4007 "to be replaced, and clear the errors\n\tusing "
4008 "'zpool clear' or replace the device with 'zpool "
4009 "replace'.\n"));
4010 break;
4011
4012 case ZPOOL_STATUS_OFFLINE_DEV:
4013 (void) printf(gettext("status: One or more devices has "
4014 "been taken offline by the administrator.\n\tSufficient "
4015 "replicas exist for the pool to continue functioning in "
4016 "a\n\tdegraded state.\n"));
4017 (void) printf(gettext("action: Online the device using "
4018 "'zpool online' or replace the device with\n\t'zpool "
4019 "replace'.\n"));
4020 break;
4021
4022 case ZPOOL_STATUS_REMOVED_DEV:
4023 (void) printf(gettext("status: One or more devices has "
4024 "been removed by the administrator.\n\tSufficient "
4025 "replicas exist for the pool to continue functioning in "
4026 "a\n\tdegraded state.\n"));
4027 (void) printf(gettext("action: Online the device using "
4028 "'zpool online' or replace the device with\n\t'zpool "
4029 "replace'.\n"));
4030 break;
4031
4032 case ZPOOL_STATUS_RESILVERING:
4033 (void) printf(gettext("status: One or more devices is "
4034 "currently being resilvered. The pool will\n\tcontinue "
4035 "to function, possibly in a degraded state.\n"));
4036 (void) printf(gettext("action: Wait for the resilver to "
4037 "complete.\n"));
4038 break;
4039
4040 case ZPOOL_STATUS_CORRUPT_DATA:
4041 (void) printf(gettext("status: One or more devices has "
4042 "experienced an error resulting in data\n\tcorruption. "
4043 "Applications may be affected.\n"));
4044 (void) printf(gettext("action: Restore the file in question "
4045 "if possible. Otherwise restore the\n\tentire pool from "
4046 "backup.\n"));
4047 break;
4048
4049 case ZPOOL_STATUS_CORRUPT_POOL:
4050 (void) printf(gettext("status: The pool metadata is corrupted "
4051 "and the pool cannot be opened.\n"));
4052 zpool_explain_recover(zpool_get_handle(zhp),
4053 zpool_get_name(zhp), reason, config);
4054 break;
4055
4056 case ZPOOL_STATUS_VERSION_OLDER:
4057 (void) printf(gettext("status: The pool is formatted using a "
4058 "legacy on-disk format. The pool can\n\tstill be used, "
4059 "but some features are unavailable.\n"));
4060 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4061 "upgrade'. Once this is done, the\n\tpool will no longer "
4062 "be accessible on software that does not support feature\n"
4063 "\tflags.\n"));
4064 break;
4065
4066 case ZPOOL_STATUS_VERSION_NEWER:
4067 (void) printf(gettext("status: The pool has been upgraded to a "
4068 "newer, incompatible on-disk version.\n\tThe pool cannot "
4069 "be accessed on this system.\n"));
4070 (void) printf(gettext("action: Access the pool from a system "
4071 "running more recent software, or\n\trestore the pool from "
4072 "backup.\n"));
4073 break;
4074
4075 case ZPOOL_STATUS_FEAT_DISABLED:
4076 (void) printf(gettext("status: Some supported features are not "
4077 "enabled on the pool. The pool can\n\tstill be used, but "
4078 "some features are unavailable.\n"));
4079 (void) printf(gettext("action: Enable all features using "
4080 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4081 "longer be accessible by software that does not support\n\t"
4082 "the features. See zpool-features(5) for details.\n"));
4083 break;
4084
4085 case ZPOOL_STATUS_UNSUP_FEAT_READ:
4086 (void) printf(gettext("status: The pool cannot be accessed on "
4087 "this system because it uses the\n\tfollowing feature(s) "
4088 "not supported on this system:\n"));
4089 zpool_print_unsup_feat(config);
4090 (void) printf("\n");
4091 (void) printf(gettext("action: Access the pool from a system "
4092 "that supports the required feature(s),\n\tor restore the "
4093 "pool from backup.\n"));
4094 break;
4095
4096 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4097 (void) printf(gettext("status: The pool can only be accessed "
4098 "in read-only mode on this system. It\n\tcannot be "
4099 "accessed in read-write mode because it uses the "
4100 "following\n\tfeature(s) not supported on this system:\n"));
4101 zpool_print_unsup_feat(config);
4102 (void) printf("\n");
4103 (void) printf(gettext("action: The pool cannot be accessed in "
4104 "read-write mode. Import the pool with\n"
4105 "\t\"-o readonly=on\", access the pool from a system that "
4106 "supports the\n\trequired feature(s), or restore the "
4107 "pool from backup.\n"));
4108 break;
4109
4110 case ZPOOL_STATUS_FAULTED_DEV_R:
4111 (void) printf(gettext("status: One or more devices are "
4112 "faulted in response to persistent errors.\n\tSufficient "
4113 "replicas exist for the pool to continue functioning "
4114 "in a\n\tdegraded state.\n"));
4115 (void) printf(gettext("action: Replace the faulted device, "
4116 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4117 break;
4118
4119 case ZPOOL_STATUS_FAULTED_DEV_NR:
4120 (void) printf(gettext("status: One or more devices are "
4121 "faulted in response to persistent errors. There are "
4122 "insufficient replicas for the pool to\n\tcontinue "
4123 "functioning.\n"));
4124 (void) printf(gettext("action: Destroy and re-create the pool "
4125 "from a backup source. Manually marking the device\n"
4126 "\trepaired using 'zpool clear' may allow some data "
4127 "to be recovered.\n"));
4128 break;
4129
4130 case ZPOOL_STATUS_IO_FAILURE_WAIT:
4131 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4132 (void) printf(gettext("status: One or more devices are "
4133 "faulted in response to IO failures.\n"));
4134 (void) printf(gettext("action: Make sure the affected devices "
4135 "are connected, then run 'zpool clear'.\n"));
4136 break;
4137
4138 case ZPOOL_STATUS_BAD_LOG:
4139 (void) printf(gettext("status: An intent log record "
4140 "could not be read.\n"
4141 "\tWaiting for adminstrator intervention to fix the "
4142 "faulted pool.\n"));
4143 (void) printf(gettext("action: Either restore the affected "
4144 "device(s) and run 'zpool online',\n"
4145 "\tor ignore the intent log records by running "
4146 "'zpool clear'.\n"));
4147 break;
4148
4149 default:
4150 /*
4151 * The remaining errors can't actually be generated, yet.
4152 */
4153 assert(reason == ZPOOL_STATUS_OK);
4154 }
4155
4156 if (msgid != NULL)
4157 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4158 msgid);
4159
4160 if (config != NULL) {
4161 int namewidth;
4162 uint64_t nerr;
4163 nvlist_t **spares, **l2cache;
4164 uint_t nspares, nl2cache;
4165 pool_scan_stat_t *ps = NULL;
4166
4167 (void) nvlist_lookup_uint64_array(nvroot,
4168 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4169 print_scan_status(ps);
4170
4171 namewidth = max_width(zhp, nvroot, 0, 0);
4172 if (namewidth < 10)
4173 namewidth = 10;
4174
4175 (void) printf(gettext("config:\n\n"));
4176 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
4177 "NAME", "STATE", "READ", "WRITE", "CKSUM");
4178 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4179 namewidth, 0, B_FALSE);
4180
4181 if (num_logs(nvroot) > 0)
4182 print_logs(zhp, nvroot, namewidth, B_TRUE);
4183 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4184 &l2cache, &nl2cache) == 0)
4185 print_l2cache(zhp, l2cache, nl2cache, namewidth);
4186
4187 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4188 &spares, &nspares) == 0)
4189 print_spares(zhp, spares, nspares, namewidth);
4190
4191 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4192 &nerr) == 0) {
4193 nvlist_t *nverrlist = NULL;
4194
4195 /*
4196 * If the approximate error count is small, get a
4197 * precise count by fetching the entire log and
4198 * uniquifying the results.
4199 */
4200 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4201 zpool_get_errlog(zhp, &nverrlist) == 0) {
4202 nvpair_t *elem;
4203
4204 elem = NULL;
4205 nerr = 0;
4206 while ((elem = nvlist_next_nvpair(nverrlist,
4207 elem)) != NULL) {
4208 nerr++;
4209 }
4210 }
4211 nvlist_free(nverrlist);
4212
4213 (void) printf("\n");
4214
4215 if (nerr == 0)
4216 (void) printf(gettext("errors: No known data "
4217 "errors\n"));
4218 else if (!cbp->cb_verbose)
4219 (void) printf(gettext("errors: %llu data "
4220 "errors, use '-v' for a list\n"),
4221 (u_longlong_t)nerr);
4222 else
4223 print_error_log(zhp);
4224 }
4225
4226 if (cbp->cb_dedup_stats)
4227 print_dedup_stats(config);
4228 } else {
4229 (void) printf(gettext("config: The configuration cannot be "
4230 "determined.\n"));
4231 }
4232
4233 return (0);
4234 }
4235
4236 /*
4237 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4238 *
4239 * -v Display complete error logs
4240 * -x Display only pools with potential problems
4241 * -D Display dedup status (undocumented)
4242 * -T Display a timestamp in date(1) or Unix format
4243 *
4244 * Describes the health status of all pools or some subset.
4245 */
4246 int
4247 zpool_do_status(int argc, char **argv)
4248 {
4249 int c;
4250 int ret;
4251 unsigned long interval = 0, count = 0;
4252 status_cbdata_t cb = { 0 };
4253
4254 /* check options */
4255 while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4256 switch (c) {
4257 case 'v':
4258 cb.cb_verbose = B_TRUE;
4259 break;
4260 case 'x':
4261 cb.cb_explain = B_TRUE;
4262 break;
4263 case 'D':
4264 cb.cb_dedup_stats = B_TRUE;
4265 break;
4266 case 'T':
4267 get_timestamp_arg(*optarg);
4268 break;
4269 case '?':
4270 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4271 optopt);
4272 usage(B_FALSE);
4273 }
4274 }
4275
4276 argc -= optind;
4277 argv += optind;
4278
4279 get_interval_count(&argc, argv, &interval, &count);
4280
4281 if (argc == 0)
4282 cb.cb_allpools = B_TRUE;
4283
4284 cb.cb_first = B_TRUE;
4285
4286 for (;;) {
4287 if (timestamp_fmt != NODATE)
4288 print_timestamp(timestamp_fmt);
4289
4290 ret = for_each_pool(argc, argv, B_TRUE, NULL,
4291 status_callback, &cb);
4292
4293 if (argc == 0 && cb.cb_count == 0)
4294 (void) printf(gettext("no pools available\n"));
4295 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4296 (void) printf(gettext("all pools are healthy\n"));
4297
4298 if (ret != 0)
4299 return (ret);
4300
4301 if (interval == 0)
4302 break;
4303
4304 if (count != 0 && --count == 0)
4305 break;
4306
4307 (void) sleep(interval);
4308 }
4309
4310 return (0);
4311 }
4312
4313 typedef struct upgrade_cbdata {
4314 int cb_first;
4315 int cb_argc;
4316 uint64_t cb_version;
4317 char **cb_argv;
4318 } upgrade_cbdata_t;
4319
4320 static int
4321 upgrade_version(zpool_handle_t *zhp, uint64_t version)
4322 {
4323 int ret;
4324 nvlist_t *config;
4325 uint64_t oldversion;
4326
4327 config = zpool_get_config(zhp, NULL);
4328 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4329 &oldversion) == 0);
4330
4331 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
4332 assert(oldversion < version);
4333
4334 ret = zpool_upgrade(zhp, version);
4335 if (ret != 0)
4336 return (ret);
4337
4338 if (version >= SPA_VERSION_FEATURES) {
4339 (void) printf(gettext("Successfully upgraded "
4340 "'%s' from version %llu to feature flags.\n"),
4341 zpool_get_name(zhp), oldversion);
4342 } else {
4343 (void) printf(gettext("Successfully upgraded "
4344 "'%s' from version %llu to version %llu.\n"),
4345 zpool_get_name(zhp), oldversion, version);
4346 }
4347
4348 return (0);
4349 }
4350
4351 static int
4352 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4353 {
4354 int i, ret, count;
4355 boolean_t firstff = B_TRUE;
4356 nvlist_t *enabled = zpool_get_features(zhp);
4357
4358 count = 0;
4359 for (i = 0; i < SPA_FEATURES; i++) {
4360 const char *fname = spa_feature_table[i].fi_uname;
4361 const char *fguid = spa_feature_table[i].fi_guid;
4362 if (!nvlist_exists(enabled, fguid)) {
4363 char *propname;
4364 verify(-1 != asprintf(&propname, "feature@%s", fname));
4365 ret = zpool_set_prop(zhp, propname,
4366 ZFS_FEATURE_ENABLED);
4367 if (ret != 0) {
4368 free(propname);
4369 return (ret);
4370 }
4371 count++;
4372
4373 if (firstff) {
4374 (void) printf(gettext("Enabled the "
4375 "following features on '%s':\n"),
4376 zpool_get_name(zhp));
4377 firstff = B_FALSE;
4378 }
4379 (void) printf(gettext(" %s\n"), fname);
4380 free(propname);
4381 }
4382 }
4383
4384 if (countp != NULL)
4385 *countp = count;
4386 return (0);
4387 }
4388
4389 static int
4390 upgrade_cb(zpool_handle_t *zhp, void *arg)
4391 {
4392 upgrade_cbdata_t *cbp = arg;
4393 nvlist_t *config;
4394 uint64_t version;
4395 boolean_t printnl = B_FALSE;
4396 int ret;
4397
4398 config = zpool_get_config(zhp, NULL);
4399 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4400 &version) == 0);
4401
4402 assert(SPA_VERSION_IS_SUPPORTED(version));
4403
4404 if (version < cbp->cb_version) {
4405 cbp->cb_first = B_FALSE;
4406 ret = upgrade_version(zhp, cbp->cb_version);
4407 if (ret != 0)
4408 return (ret);
4409 printnl = B_TRUE;
4410
4411 /*
4412 * If they did "zpool upgrade -a", then we could
4413 * be doing ioctls to different pools. We need
4414 * to log this history once to each pool, and bypass
4415 * the normal history logging that happens in main().
4416 */
4417 (void) zpool_log_history(g_zfs, history_str);
4418 log_history = B_FALSE;
4419 }
4420
4421 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4422 int count;
4423 ret = upgrade_enable_all(zhp, &count);
4424 if (ret != 0)
4425 return (ret);
4426
4427 if (count > 0) {
4428 cbp->cb_first = B_FALSE;
4429 printnl = B_TRUE;
4430 }
4431 }
4432
4433 if (printnl) {
4434 (void) printf(gettext("\n"));
4435 }
4436
4437 return (0);
4438 }
4439
4440 static int
4441 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
4442 {
4443 upgrade_cbdata_t *cbp = arg;
4444 nvlist_t *config;
4445 uint64_t version;
4446
4447 config = zpool_get_config(zhp, NULL);
4448 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4449 &version) == 0);
4450
4451 assert(SPA_VERSION_IS_SUPPORTED(version));
4452
4453 if (version < SPA_VERSION_FEATURES) {
4454 if (cbp->cb_first) {
4455 (void) printf(gettext("The following pools are "
4456 "formatted with legacy version numbers and can\n"
4457 "be upgraded to use feature flags. After "
4458 "being upgraded, these pools\nwill no "
4459 "longer be accessible by software that does not "
4460 "support feature\nflags.\n\n"));
4461 (void) printf(gettext("VER POOL\n"));
4462 (void) printf(gettext("--- ------------\n"));
4463 cbp->cb_first = B_FALSE;
4464 }
4465
4466 (void) printf("%2llu %s\n", (u_longlong_t)version,
4467 zpool_get_name(zhp));
4468 }
4469
4470 return (0);
4471 }
4472
4473 static int
4474 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
4475 {
4476 upgrade_cbdata_t *cbp = arg;
4477 nvlist_t *config;
4478 uint64_t version;
4479
4480 config = zpool_get_config(zhp, NULL);
4481 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4482 &version) == 0);
4483
4484 if (version >= SPA_VERSION_FEATURES) {
4485 int i;
4486 boolean_t poolfirst = B_TRUE;
4487 nvlist_t *enabled = zpool_get_features(zhp);
4488
4489 for (i = 0; i < SPA_FEATURES; i++) {
4490 const char *fguid = spa_feature_table[i].fi_guid;
4491 const char *fname = spa_feature_table[i].fi_uname;
4492 if (!nvlist_exists(enabled, fguid)) {
4493 if (cbp->cb_first) {
4494 (void) printf(gettext("\nSome "
4495 "supported features are not "
4496 "enabled on the following pools. "
4497 "Once a\nfeature is enabled the "
4498 "pool may become incompatible with "
4499 "software\nthat does not support "
4500 "the feature. See "
4501 "zpool-features(5) for "
4502 "details.\n\n"));
4503 (void) printf(gettext("POOL "
4504 "FEATURE\n"));
4505 (void) printf(gettext("------"
4506 "---------\n"));
4507 cbp->cb_first = B_FALSE;
4508 }
4509
4510 if (poolfirst) {
4511 (void) printf(gettext("%s\n"),
4512 zpool_get_name(zhp));
4513 poolfirst = B_FALSE;
4514 }
4515
4516 (void) printf(gettext(" %s\n"), fname);
4517 }
4518 }
4519 }
4520
4521 return (0);
4522 }
4523
4524 /* ARGSUSED */
4525 static int
4526 upgrade_one(zpool_handle_t *zhp, void *data)
4527 {
4528 boolean_t printnl = B_FALSE;
4529 upgrade_cbdata_t *cbp = data;
4530 uint64_t cur_version;
4531 int ret;
4532
4533 if (strcmp("log", zpool_get_name(zhp)) == 0) {
4534 (void) printf(gettext("'log' is now a reserved word\n"
4535 "Pool 'log' must be renamed using export and import"
4536 " to upgrade.\n"));
4537 return (1);
4538 }
4539
4540 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4541 if (cur_version > cbp->cb_version) {
4542 (void) printf(gettext("Pool '%s' is already formatted "
4543 "using more current version '%llu'.\n\n"),
4544 zpool_get_name(zhp), cur_version);
4545 return (0);
4546 }
4547
4548 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
4549 (void) printf(gettext("Pool '%s' is already formatted "
4550 "using version %llu.\n\n"), zpool_get_name(zhp),
4551 cbp->cb_version);
4552 return (0);
4553 }
4554
4555 if (cur_version != cbp->cb_version) {
4556 printnl = B_TRUE;
4557 ret = upgrade_version(zhp, cbp->cb_version);
4558 if (ret != 0)
4559 return (ret);
4560 }
4561
4562 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4563 int count = 0;
4564 ret = upgrade_enable_all(zhp, &count);
4565 if (ret != 0)
4566 return (ret);
4567
4568 if (count != 0) {
4569 printnl = B_TRUE;
4570 } else if (cur_version == SPA_VERSION) {
4571 (void) printf(gettext("Pool '%s' already has all "
4572 "supported features enabled.\n"),
4573 zpool_get_name(zhp));
4574 }
4575 }
4576
4577 if (printnl) {
4578 (void) printf(gettext("\n"));
4579 }
4580
4581 return (0);
4582 }
4583
4584 /*
4585 * zpool upgrade
4586 * zpool upgrade -v
4587 * zpool upgrade [-V version] <-a | pool ...>
4588 *
4589 * With no arguments, display downrev'd ZFS pool available for upgrade.
4590 * Individual pools can be upgraded by specifying the pool, and '-a' will
4591 * upgrade all pools.
4592 */
4593 int
4594 zpool_do_upgrade(int argc, char **argv)
4595 {
4596 int c;
4597 upgrade_cbdata_t cb = { 0 };
4598 int ret = 0;
4599 boolean_t showversions = B_FALSE;
4600 boolean_t upgradeall = B_FALSE;
4601 char *end;
4602
4603
4604 /* check options */
4605 while ((c = getopt(argc, argv, ":avV:")) != -1) {
4606 switch (c) {
4607 case 'a':
4608 upgradeall = B_TRUE;
4609 break;
4610 case 'v':
4611 showversions = B_TRUE;
4612 break;
4613 case 'V':
4614 cb.cb_version = strtoll(optarg, &end, 10);
4615 if (*end != '\0' ||
4616 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
4617 (void) fprintf(stderr,
4618 gettext("invalid version '%s'\n"), optarg);
4619 usage(B_FALSE);
4620 }
4621 break;
4622 case ':':
4623 (void) fprintf(stderr, gettext("missing argument for "
4624 "'%c' option\n"), optopt);
4625 usage(B_FALSE);
4626 break;
4627 case '?':
4628 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4629 optopt);
4630 usage(B_FALSE);
4631 }
4632 }
4633
4634 cb.cb_argc = argc;
4635 cb.cb_argv = argv;
4636 argc -= optind;
4637 argv += optind;
4638
4639 if (cb.cb_version == 0) {
4640 cb.cb_version = SPA_VERSION;
4641 } else if (!upgradeall && argc == 0) {
4642 (void) fprintf(stderr, gettext("-V option is "
4643 "incompatible with other arguments\n"));
4644 usage(B_FALSE);
4645 }
4646
4647 if (showversions) {
4648 if (upgradeall || argc != 0) {
4649 (void) fprintf(stderr, gettext("-v option is "
4650 "incompatible with other arguments\n"));
4651 usage(B_FALSE);
4652 }
4653 } else if (upgradeall) {
4654 if (argc != 0) {
4655 (void) fprintf(stderr, gettext("-a option should not "
4656 "be used along with a pool name\n"));
4657 usage(B_FALSE);
4658 }
4659 }
4660
4661 (void) printf(gettext("This system supports ZFS pool feature "
4662 "flags.\n\n"));
4663 if (showversions) {
4664 int i;
4665
4666 (void) printf(gettext("The following features are "
4667 "supported:\n\n"));
4668 (void) printf(gettext("FEAT DESCRIPTION\n"));
4669 (void) printf("----------------------------------------------"
4670 "---------------\n");
4671 for (i = 0; i < SPA_FEATURES; i++) {
4672 zfeature_info_t *fi = &spa_feature_table[i];
4673 const char *ro = fi->fi_can_readonly ?
4674 " (read-only compatible)" : "";
4675
4676 (void) printf("%-37s%s\n", fi->fi_uname, ro);
4677 (void) printf(" %s\n", fi->fi_desc);
4678 }
4679 (void) printf("\n");
4680
4681 (void) printf(gettext("The following legacy versions are also "
4682 "supported:\n\n"));
4683 (void) printf(gettext("VER DESCRIPTION\n"));
4684 (void) printf("--- -----------------------------------------"
4685 "---------------\n");
4686 (void) printf(gettext(" 1 Initial ZFS version\n"));
4687 (void) printf(gettext(" 2 Ditto blocks "
4688 "(replicated metadata)\n"));
4689 (void) printf(gettext(" 3 Hot spares and double parity "
4690 "RAID-Z\n"));
4691 (void) printf(gettext(" 4 zpool history\n"));
4692 (void) printf(gettext(" 5 Compression using the gzip "
4693 "algorithm\n"));
4694 (void) printf(gettext(" 6 bootfs pool property\n"));
4695 (void) printf(gettext(" 7 Separate intent log devices\n"));
4696 (void) printf(gettext(" 8 Delegated administration\n"));
4697 (void) printf(gettext(" 9 refquota and refreservation "
4698 "properties\n"));
4699 (void) printf(gettext(" 10 Cache devices\n"));
4700 (void) printf(gettext(" 11 Improved scrub performance\n"));
4701 (void) printf(gettext(" 12 Snapshot properties\n"));
4702 (void) printf(gettext(" 13 snapused property\n"));
4703 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
4704 (void) printf(gettext(" 15 user/group space accounting\n"));
4705 (void) printf(gettext(" 16 stmf property support\n"));
4706 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
4707 (void) printf(gettext(" 18 Snapshot user holds\n"));
4708 (void) printf(gettext(" 19 Log device removal\n"));
4709 (void) printf(gettext(" 20 Compression using zle "
4710 "(zero-length encoding)\n"));
4711 (void) printf(gettext(" 21 Deduplication\n"));
4712 (void) printf(gettext(" 22 Received properties\n"));
4713 (void) printf(gettext(" 23 Slim ZIL\n"));
4714 (void) printf(gettext(" 24 System attributes\n"));
4715 (void) printf(gettext(" 25 Improved scrub stats\n"));
4716 (void) printf(gettext(" 26 Improved snapshot deletion "
4717 "performance\n"));
4718 (void) printf(gettext(" 27 Improved snapshot creation "
4719 "performance\n"));
4720 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
4721 (void) printf(gettext("\nFor more information on a particular "
4722 "version, including supported releases,\n"));
4723 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
4724 } else if (argc == 0 && upgradeall) {
4725 cb.cb_first = B_TRUE;
4726 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
4727 if (ret == 0 && cb.cb_first) {
4728 if (cb.cb_version == SPA_VERSION) {
4729 (void) printf(gettext("All pools are already "
4730 "formatted using feature flags.\n\n"));
4731 (void) printf(gettext("Every feature flags "
4732 "pool already has all supported features "
4733 "enabled.\n"));
4734 } else {
4735 (void) printf(gettext("All pools are already "
4736 "formatted with version %llu or higher.\n"),
4737 cb.cb_version);
4738 }
4739 }
4740 } else if (argc == 0) {
4741 cb.cb_first = B_TRUE;
4742 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
4743 assert(ret == 0);
4744
4745 if (cb.cb_first) {
4746 (void) printf(gettext("All pools are formatted "
4747 "using feature flags.\n\n"));
4748 } else {
4749 (void) printf(gettext("\nUse 'zpool upgrade -v' "
4750 "for a list of available legacy versions.\n"));
4751 }
4752
4753 cb.cb_first = B_TRUE;
4754 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
4755 assert(ret == 0);
4756
4757 if (cb.cb_first) {
4758 (void) printf(gettext("Every feature flags pool has "
4759 "all supported features enabled.\n"));
4760 } else {
4761 (void) printf(gettext("\n"));
4762 }
4763 } else {
4764 ret = for_each_pool(argc, argv, B_FALSE, NULL,
4765 upgrade_one, &cb);
4766 }
4767
4768 return (ret);
4769 }
4770
4771 typedef struct hist_cbdata {
4772 boolean_t first;
4773 boolean_t longfmt;
4774 boolean_t internal;
4775 } hist_cbdata_t;
4776
4777 /*
4778 * Print out the command history for a specific pool.
4779 */
4780 static int
4781 get_history_one(zpool_handle_t *zhp, void *data)
4782 {
4783 nvlist_t *nvhis;
4784 nvlist_t **records;
4785 uint_t numrecords;
4786 int ret, i;
4787 hist_cbdata_t *cb = (hist_cbdata_t *)data;
4788
4789 cb->first = B_FALSE;
4790
4791 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
4792
4793 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
4794 return (ret);
4795
4796 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
4797 &records, &numrecords) == 0);
4798 for (i = 0; i < numrecords; i++) {
4799 nvlist_t *rec = records[i];
4800 char tbuf[30] = "";
4801
4802 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
4803 time_t tsec;
4804 struct tm t;
4805
4806 tsec = fnvlist_lookup_uint64(records[i],
4807 ZPOOL_HIST_TIME);
4808 (void) localtime_r(&tsec, &t);
4809 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
4810 }
4811
4812 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
4813 (void) printf("%s %s", tbuf,
4814 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
4815 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
4816 int ievent =
4817 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
4818 if (!cb->internal)
4819 continue;
4820 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
4821 (void) printf("%s unrecognized record:\n",
4822 tbuf);
4823 dump_nvlist(rec, 4);
4824 continue;
4825 }
4826 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
4827 zfs_history_event_names[ievent],
4828 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
4829 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
4830 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
4831 if (!cb->internal)
4832 continue;
4833 (void) printf("%s [txg:%lld] %s", tbuf,
4834 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
4835 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
4836 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
4837 (void) printf(" %s (%llu)",
4838 fnvlist_lookup_string(rec,
4839 ZPOOL_HIST_DSNAME),
4840 fnvlist_lookup_uint64(rec,
4841 ZPOOL_HIST_DSID));
4842 }
4843 (void) printf(" %s", fnvlist_lookup_string(rec,
4844 ZPOOL_HIST_INT_STR));
4845 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
4846 if (!cb->internal)
4847 continue;
4848 (void) printf("%s ioctl %s\n", tbuf,
4849 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
4850 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
4851 (void) printf(" input:\n");
4852 dump_nvlist(fnvlist_lookup_nvlist(rec,
4853 ZPOOL_HIST_INPUT_NVL), 8);
4854 }
4855 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
4856 (void) printf(" output:\n");
4857 dump_nvlist(fnvlist_lookup_nvlist(rec,
4858 ZPOOL_HIST_OUTPUT_NVL), 8);
4859 }
4860 } else {
4861 if (!cb->internal)
4862 continue;
4863 (void) printf("%s unrecognized record:\n", tbuf);
4864 dump_nvlist(rec, 4);
4865 }
4866
4867 if (!cb->longfmt) {
4868 (void) printf("\n");
4869 continue;
4870 }
4871 (void) printf(" [");
4872 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
4873 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
4874 struct passwd *pwd = getpwuid(who);
4875 (void) printf("user %d ", (int)who);
4876 if (pwd != NULL)
4877 (void) printf("(%s) ", pwd->pw_name);
4878 }
4879 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
4880 (void) printf("on %s",
4881 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
4882 }
4883 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
4884 (void) printf(":%s",
4885 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
4886 }
4887 (void) printf("]");
4888 (void) printf("\n");
4889 }
4890 (void) printf("\n");
4891 nvlist_free(nvhis);
4892
4893 return (ret);
4894 }
4895
4896 /*
4897 * zpool history <pool>
4898 *
4899 * Displays the history of commands that modified pools.
4900 */
4901 int
4902 zpool_do_history(int argc, char **argv)
4903 {
4904 hist_cbdata_t cbdata = { 0 };
4905 int ret;
4906 int c;
4907
4908 cbdata.first = B_TRUE;
4909 /* check options */
4910 while ((c = getopt(argc, argv, "li")) != -1) {
4911 switch (c) {
4912 case 'l':
4913 cbdata.longfmt = B_TRUE;
4914 break;
4915 case 'i':
4916 cbdata.internal = B_TRUE;
4917 break;
4918 case '?':
4919 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4920 optopt);
4921 usage(B_FALSE);
4922 }
4923 }
4924 argc -= optind;
4925 argv += optind;
4926
4927 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
4928 &cbdata);
4929
4930 if (argc == 0 && cbdata.first == B_TRUE) {
4931 (void) printf(gettext("no pools available\n"));
4932 return (0);
4933 }
4934
4935 return (ret);
4936 }
4937
4938 static int
4939 get_callback(zpool_handle_t *zhp, void *data)
4940 {
4941 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
4942 char value[MAXNAMELEN];
4943 zprop_source_t srctype;
4944 zprop_list_t *pl;
4945
4946 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
4947
4948 /*
4949 * Skip the special fake placeholder. This will also skip
4950 * over the name property when 'all' is specified.
4951 */
4952 if (pl->pl_prop == ZPOOL_PROP_NAME &&
4953 pl == cbp->cb_proplist)
4954 continue;
4955
4956 if (pl->pl_prop == ZPROP_INVAL &&
4957 (zpool_prop_feature(pl->pl_user_prop) ||
4958 zpool_prop_unsupported(pl->pl_user_prop))) {
4959 srctype = ZPROP_SRC_LOCAL;
4960
4961 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
4962 value, sizeof (value)) == 0) {
4963 zprop_print_one_property(zpool_get_name(zhp),
4964 cbp, pl->pl_user_prop, value, srctype,
4965 NULL, NULL);
4966 }
4967 } else {
4968 if (zpool_get_prop(zhp, pl->pl_prop, value,
4969 sizeof (value), &srctype) != 0)
4970 continue;
4971
4972 zprop_print_one_property(zpool_get_name(zhp), cbp,
4973 zpool_prop_to_name(pl->pl_prop), value, srctype,
4974 NULL, NULL);
4975 }
4976 }
4977 return (0);
4978 }
4979
4980 int
4981 zpool_do_get(int argc, char **argv)
4982 {
4983 zprop_get_cbdata_t cb = { 0 };
4984 zprop_list_t fake_name = { 0 };
4985 int ret;
4986
4987 if (argc < 2) {
4988 (void) fprintf(stderr, gettext("missing property "
4989 "argument\n"));
4990 usage(B_FALSE);
4991 }
4992
4993 cb.cb_first = B_TRUE;
4994 cb.cb_sources = ZPROP_SRC_ALL;
4995 cb.cb_columns[0] = GET_COL_NAME;
4996 cb.cb_columns[1] = GET_COL_PROPERTY;
4997 cb.cb_columns[2] = GET_COL_VALUE;
4998 cb.cb_columns[3] = GET_COL_SOURCE;
4999 cb.cb_type = ZFS_TYPE_POOL;
5000
5001 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
5002 ZFS_TYPE_POOL) != 0)
5003 usage(B_FALSE);
5004
5005 if (cb.cb_proplist != NULL) {
5006 fake_name.pl_prop = ZPOOL_PROP_NAME;
5007 fake_name.pl_width = strlen(gettext("NAME"));
5008 fake_name.pl_next = cb.cb_proplist;
5009 cb.cb_proplist = &fake_name;
5010 }
5011
5012 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
5013 get_callback, &cb);
5014
5015 if (cb.cb_proplist == &fake_name)
5016 zprop_free_list(fake_name.pl_next);
5017 else
5018 zprop_free_list(cb.cb_proplist);
5019
5020 return (ret);
5021 }
5022
5023 typedef struct set_cbdata {
5024 char *cb_propname;
5025 char *cb_value;
5026 boolean_t cb_any_successful;
5027 } set_cbdata_t;
5028
5029 int
5030 set_callback(zpool_handle_t *zhp, void *data)
5031 {
5032 int error;
5033 set_cbdata_t *cb = (set_cbdata_t *)data;
5034
5035 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5036
5037 if (!error)
5038 cb->cb_any_successful = B_TRUE;
5039
5040 return (error);
5041 }
5042
5043 int
5044 zpool_do_set(int argc, char **argv)
5045 {
5046 set_cbdata_t cb = { 0 };
5047 int error;
5048
5049 if (argc > 1 && argv[1][0] == '-') {
5050 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5051 argv[1][1]);
5052 usage(B_FALSE);
5053 }
5054
5055 if (argc < 2) {
5056 (void) fprintf(stderr, gettext("missing property=value "
5057 "argument\n"));
5058 usage(B_FALSE);
5059 }
5060
5061 if (argc < 3) {
5062 (void) fprintf(stderr, gettext("missing pool name\n"));
5063 usage(B_FALSE);
5064 }
5065
5066 if (argc > 3) {
5067 (void) fprintf(stderr, gettext("too many pool names\n"));
5068 usage(B_FALSE);
5069 }
5070
5071 cb.cb_propname = argv[1];
5072 cb.cb_value = strchr(cb.cb_propname, '=');
5073 if (cb.cb_value == NULL) {
5074 (void) fprintf(stderr, gettext("missing value in "
5075 "property=value argument\n"));
5076 usage(B_FALSE);
5077 }
5078
5079 *(cb.cb_value) = '\0';
5080 cb.cb_value++;
5081
5082 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5083 set_callback, &cb);
5084
5085 return (error);
5086 }
5087
5088 static int
5089 find_command_idx(char *command, int *idx)
5090 {
5091 int i;
5092
5093 for (i = 0; i < NCOMMAND; i++) {
5094 if (command_table[i].name == NULL)
5095 continue;
5096
5097 if (strcmp(command, command_table[i].name) == 0) {
5098 *idx = i;
5099 return (0);
5100 }
5101 }
5102 return (1);
5103 }
5104
5105 int
5106 main(int argc, char **argv)
5107 {
5108 int ret;
5109 int i;
5110 char *cmdname;
5111
5112 (void) setlocale(LC_ALL, "");
5113 (void) textdomain(TEXT_DOMAIN);
5114
5115 if ((g_zfs = libzfs_init()) == NULL) {
5116 (void) fprintf(stderr, gettext("internal error: failed to "
5117 "initialize ZFS library\n"));
5118 return (1);
5119 }
5120
5121 libzfs_print_on_error(g_zfs, B_TRUE);
5122
5123 opterr = 0;
5124
5125 /*
5126 * Make sure the user has specified some command.
5127 */
5128 if (argc < 2) {
5129 (void) fprintf(stderr, gettext("missing command\n"));
5130 usage(B_FALSE);
5131 }
5132
5133 cmdname = argv[1];
5134
5135 /*
5136 * Special case '-?'
5137 */
5138 if (strcmp(cmdname, "-?") == 0)
5139 usage(B_TRUE);
5140
5141 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5142
5143 /*
5144 * Run the appropriate command.
5145 */
5146 if (find_command_idx(cmdname, &i) == 0) {
5147 current_command = &command_table[i];
5148 ret = command_table[i].func(argc - 1, argv + 1);
5149 } else if (strchr(cmdname, '=')) {
5150 verify(find_command_idx("set", &i) == 0);
5151 current_command = &command_table[i];
5152 ret = command_table[i].func(argc, argv);
5153 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5154 /*
5155 * 'freeze' is a vile debugging abomination, so we treat
5156 * it as such.
5157 */
5158 char buf[16384];
5159 int fd = open(ZFS_DEV, O_RDWR);
5160 (void) strcpy((void *)buf, argv[2]);
5161 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
5162 } else {
5163 (void) fprintf(stderr, gettext("unrecognized "
5164 "command '%s'\n"), cmdname);
5165 usage(B_FALSE);
5166 }
5167
5168 if (ret == 0 && log_history)
5169 (void) zpool_log_history(g_zfs, history_str);
5170
5171 libzfs_fini(g_zfs);
5172
5173 /*
5174 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5175 * for the purposes of running ::findleaks.
5176 */
5177 if (getenv("ZFS_ABORT") != NULL) {
5178 (void) printf("dumping core by request\n");
5179 abort();
5180 }
5181
5182 return (ret);
5183 }