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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <assert.h>
28 #include <ctype.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <libgen.h>
33 #include <libintl.h>
34 #include <libuutil.h>
35 #include <locale.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <priv.h>
42 #include <pwd.h>
43 #include <zone.h>
44 #include <sys/fs/zfs.h>
45
46 #include <sys/stat.h>
47
48 #include <libzfs.h>
49
50 #include "zpool_util.h"
51 #include "zfs_comutil.h"
52
53 static int zpool_do_create(int, char **);
54 static int zpool_do_destroy(int, char **);
55
56 static int zpool_do_add(int, char **);
57 static int zpool_do_remove(int, char **);
58
59 static int zpool_do_list(int, char **);
60 static int zpool_do_iostat(int, char **);
61 static int zpool_do_status(int, char **);
62
63 static int zpool_do_online(int, char **);
64 static int zpool_do_offline(int, char **);
65 static int zpool_do_clear(int, char **);
66
67 static int zpool_do_attach(int, char **);
68 static int zpool_do_detach(int, char **);
69 static int zpool_do_replace(int, char **);
70
71 static int zpool_do_scrub(int, char **);
72
73 static int zpool_do_import(int, char **);
74 static int zpool_do_export(int, char **);
75
76 static int zpool_do_upgrade(int, char **);
77
78 static int zpool_do_history(int, char **);
79
80 static int zpool_do_get(int, char **);
81 static int zpool_do_set(int, char **);
82
83 static int zpool_do_key(int, char **);
84
85 /*
86 * These libumem hooks provide a reasonable set of defaults for the allocator's
87 * debugging facilities.
88 */
89
90 #ifdef DEBUG
91 const char *
92 _umem_debug_init(void)
93 {
94 return ("default,verbose"); /* $UMEM_DEBUG setting */
95 }
96
97 const char *
98 _umem_logging_init(void)
99 {
100 return ("fail,contents"); /* $UMEM_LOGGING setting */
101 }
102 #endif
103
104 typedef enum {
105 HELP_ADD,
106 HELP_ATTACH,
107 HELP_CLEAR,
108 HELP_CREATE,
109 HELP_DESTROY,
110 HELP_DETACH,
111 HELP_EXPORT,
112 HELP_HISTORY,
113 HELP_IMPORT,
114 HELP_IOSTAT,
115 HELP_LIST,
116 HELP_OFFLINE,
117 HELP_ONLINE,
118 HELP_REPLACE,
119 HELP_REMOVE,
120 HELP_SCRUB,
121 HELP_STATUS,
122 HELP_UPGRADE,
123 HELP_GET,
124 HELP_SET,
125 HELP_KEY
126 } zpool_help_t;
127
128
129 typedef struct zpool_command {
130 const char *name;
131 int (*func)(int, char **);
132 zpool_help_t usage;
133 } zpool_command_t;
134
135 /*
136 * Master command table. Each ZFS command has a name, associated function, and
137 * usage message. The usage messages need to be internationalized, so we have
138 * to have a function to return the usage message based on a command index.
139 *
140 * These commands are organized according to how they are displayed in the usage
141 * message. An empty command (one with a NULL name) indicates an empty line in
142 * the generic usage message.
143 */
144 static zpool_command_t command_table[] = {
145 { "create", zpool_do_create, HELP_CREATE },
146 { "destroy", zpool_do_destroy, HELP_DESTROY },
147 { NULL },
148 { "add", zpool_do_add, HELP_ADD },
149 { "remove", zpool_do_remove, HELP_REMOVE },
150 { NULL },
151 { "list", zpool_do_list, HELP_LIST },
152 { "iostat", zpool_do_iostat, HELP_IOSTAT },
153 { "status", zpool_do_status, HELP_STATUS },
154 { NULL },
155 { "online", zpool_do_online, HELP_ONLINE },
156 { "offline", zpool_do_offline, HELP_OFFLINE },
157 { "clear", zpool_do_clear, HELP_CLEAR },
158 { NULL },
159 { "attach", zpool_do_attach, HELP_ATTACH },
160 { "detach", zpool_do_detach, HELP_DETACH },
161 { "replace", zpool_do_replace, HELP_REPLACE },
162 { NULL },
163 { "scrub", zpool_do_scrub, HELP_SCRUB },
164 { NULL },
165 { "import", zpool_do_import, HELP_IMPORT },
166 { "export", zpool_do_export, HELP_EXPORT },
167 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
168 { NULL },
169 { "history", zpool_do_history, HELP_HISTORY },
170 { "get", zpool_do_get, HELP_GET },
171 { "set", zpool_do_set, HELP_SET },
172 { NULL },
173 { "key", zpool_do_key, HELP_KEY },
174 };
175
176 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
177
178 zpool_command_t *current_command;
179 static char history_str[HIS_MAX_RECORD_LEN];
180
181 static const char *
182 get_usage(zpool_help_t idx) {
183 switch (idx) {
184 case HELP_ADD:
185 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
186 case HELP_ATTACH:
187 return (gettext("\tattach [-f] <pool> <device> "
188 "<new-device>\n"));
189 case HELP_CLEAR:
190 return (gettext("\tclear <pool> [device]\n"));
191 case HELP_CREATE:
192 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
193 "\t [-O file-system-property=value] ... \n"
194 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
195 case HELP_DESTROY:
196 return (gettext("\tdestroy [-f] <pool>\n"));
197 case HELP_DETACH:
198 return (gettext("\tdetach <pool> <device>\n"));
199 case HELP_EXPORT:
200 return (gettext("\texport [-f] <pool> ...\n"));
201 case HELP_HISTORY:
202 return (gettext("\thistory [-il] [<pool>] ...\n"));
203 case HELP_IMPORT:
204 return (gettext("\timport [-d dir] [-D]\n"
205 "\timport [-o mntopts] [-o property=value] ... \n"
206 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
207 "\timport [-o mntopts] [-o property=value] ... \n"
208 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] "
209 "<pool | id> [newpool]\n"));
210 case HELP_IOSTAT:
211 return (gettext("\tiostat [-v] [pool] ... [interval "
212 "[count]]\n"));
213 case HELP_LIST:
214 return (gettext("\tlist [-H] [-o property[,...]] "
215 "[pool] ...\n"));
216 case HELP_OFFLINE:
217 return (gettext("\toffline [-t] <pool> <device> ...\n"));
218 case HELP_ONLINE:
219 return (gettext("\tonline <pool> <device> ...\n"));
220 case HELP_REPLACE:
221 return (gettext("\treplace [-f] <pool> <device> "
222 "[new-device]\n"));
223 case HELP_REMOVE:
224 return (gettext("\tremove <pool> <device> ...\n"));
225 case HELP_SCRUB:
226 return (gettext("\tscrub [-s] <pool> ...\n"));
227 case HELP_STATUS:
228 return (gettext("\tstatus [-vx] [pool] ...\n"));
229 case HELP_UPGRADE:
230 return (gettext("\tupgrade\n"
231 "\tupgrade -v\n"
232 "\tupgrade [-V version] <-a | pool ...>\n"));
233 case HELP_GET:
234 return (gettext("\tget <\"all\" | property[,...]> "
235 "<pool> ...\n"));
236 case HELP_SET:
237 return (gettext("\tset <property=value> <pool> \n"));
238 case HELP_KEY:
239 return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
240 "<-a | pool>\n"));
241 }
242
243 abort();
244 /* NOTREACHED */
245 }
246
247
248 /*
249 * Callback routine that will print out a pool property value.
250 */
251 static int
252 print_prop_cb(int prop, void *cb)
253 {
254 FILE *fp = cb;
255
256 (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop));
257
258 if (zpool_prop_readonly(prop))
259 (void) fprintf(fp, " NO ");
260 else
261 (void) fprintf(fp, " YES ");
262
263 if (zpool_prop_values(prop) == NULL)
264 (void) fprintf(fp, "-\n");
265 else
266 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
267
268 return (ZPROP_CONT);
269 }
270
271 /*
272 * Display usage message. If we're inside a command, display only the usage for
273 * that command. Otherwise, iterate over the entire command table and display
274 * a complete usage message.
275 */
276 void
277 usage(boolean_t requested)
278 {
279 FILE *fp = requested ? stdout : stderr;
280
281 if (current_command == NULL) {
282 int i;
283
284 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
285 (void) fprintf(fp,
286 gettext("where 'command' is one of the following:\n\n"));
287
288 for (i = 0; i < NCOMMAND; i++) {
289 if (command_table[i].name == NULL)
290 (void) fprintf(fp, "\n");
291 else
292 (void) fprintf(fp, "%s",
293 get_usage(command_table[i].usage));
294 }
295 } else {
296 (void) fprintf(fp, gettext("usage:\n"));
297 (void) fprintf(fp, "%s", get_usage(current_command->usage));
298 }
299
300 if (current_command != NULL &&
301 ((strcmp(current_command->name, "set") == 0) ||
302 (strcmp(current_command->name, "get") == 0) ||
303 (strcmp(current_command->name, "list") == 0))) {
304
305 (void) fprintf(fp,
306 gettext("\nthe following properties are supported:\n"));
307
308 (void) fprintf(fp, "\n\t%-13s %s %s\n\n",
309 "PROPERTY", "EDIT", "VALUES");
310
311 /* Iterate over all properties */
312 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
313 ZFS_TYPE_POOL);
314 }
315
316 /*
317 * See comments at end of main().
318 */
319 if (getenv("ZFS_ABORT") != NULL) {
320 (void) printf("dumping core by request\n");
321 abort();
322 }
323
324 exit(requested ? 0 : 2);
325 }
326
327 void
328 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
329 boolean_t print_logs)
330 {
331 nvlist_t **child;
332 uint_t c, children;
333 char *vname;
334
335 if (name != NULL)
336 (void) printf("\t%*s%s\n", indent, "", name);
337
338 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
339 &child, &children) != 0)
340 return;
341
342 for (c = 0; c < children; c++) {
343 uint64_t is_log = B_FALSE;
344
345 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
346 &is_log);
347 if ((is_log && !print_logs) || (!is_log && print_logs))
348 continue;
349
350 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
351 print_vdev_tree(zhp, vname, child[c], indent + 2,
352 B_FALSE);
353 free(vname);
354 }
355 }
356
357 /*
358 * Add a property pair (name, string-value) into a property nvlist.
359 */
360 static int
361 add_prop_list(const char *propname, char *propval, nvlist_t **props,
362 boolean_t poolprop)
363 {
364 zpool_prop_t prop = ZPROP_INVAL;
365 zfs_prop_t fprop;
366 nvlist_t *proplist;
367 const char *normnm;
368 char *strval;
369
370 if (*props == NULL &&
371 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
372 (void) fprintf(stderr,
373 gettext("internal error: out of memory\n"));
374 return (1);
375 }
376
377 proplist = *props;
378
379 if (poolprop) {
380 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
381 (void) fprintf(stderr, gettext("property '%s' is "
382 "not a valid pool property\n"), propname);
383 return (2);
384 }
385 normnm = zpool_prop_to_name(prop);
386 } else {
387 if ((fprop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
388 (void) fprintf(stderr, gettext("property '%s' is "
389 "not a valid file system property\n"), propname);
390 return (2);
391 }
392 normnm = zfs_prop_to_name(fprop);
393 }
394
395 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
396 prop != ZPOOL_PROP_CACHEFILE) {
397 (void) fprintf(stderr, gettext("property '%s' "
398 "specified multiple times\n"), propname);
399 return (2);
400 }
401
402 if (nvlist_add_string(proplist, normnm, propval) != 0) {
403 (void) fprintf(stderr, gettext("internal "
404 "error: out of memory\n"));
405 return (1);
406 }
407
408 return (0);
409 }
410
411 /*
412 * zpool add [-fn] <pool> <vdev> ...
413 *
414 * -f Force addition of devices, even if they appear in use
415 * -n Do not add the devices, but display the resulting layout if
416 * they were to be added.
417 *
418 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
419 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
420 * libzfs.
421 */
422 int
423 zpool_do_add(int argc, char **argv)
424 {
425 boolean_t force = B_FALSE;
426 boolean_t dryrun = B_FALSE;
427 int c;
428 nvlist_t *nvroot;
429 char *poolname;
430 int ret;
431 zpool_handle_t *zhp;
432 nvlist_t *config;
433
434 /* check options */
435 while ((c = getopt(argc, argv, "fn")) != -1) {
436 switch (c) {
437 case 'f':
438 force = B_TRUE;
439 break;
440 case 'n':
441 dryrun = B_TRUE;
442 break;
443 case '?':
444 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
445 optopt);
446 usage(B_FALSE);
447 }
448 }
449
450 argc -= optind;
451 argv += optind;
452
453 /* get pool name and check number of arguments */
454 if (argc < 1) {
455 (void) fprintf(stderr, gettext("missing pool name argument\n"));
456 usage(B_FALSE);
457 }
458 if (argc < 2) {
459 (void) fprintf(stderr, gettext("missing vdev specification\n"));
460 usage(B_FALSE);
461 }
462
463 poolname = argv[0];
464
465 argc--;
466 argv++;
467
468 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
469 return (1);
470
471 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
472 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
473 poolname);
474 zpool_close(zhp);
475 return (1);
476 }
477
478 /* pass off to get_vdev_spec for processing */
479 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
480 argc, argv);
481 if (nvroot == NULL) {
482 zpool_close(zhp);
483 return (1);
484 }
485
486 if (dryrun) {
487 nvlist_t *poolnvroot;
488
489 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
490 &poolnvroot) == 0);
491
492 (void) printf(gettext("would update '%s' to the following "
493 "configuration:\n"), zpool_get_name(zhp));
494
495 /* print original main pool and new tree */
496 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
497 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
498
499 /* Do the same for the logs */
500 if (num_logs(poolnvroot) > 0) {
501 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
502 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
503 } else if (num_logs(nvroot) > 0) {
504 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
505 }
506
507 ret = 0;
508 } else {
509 ret = (zpool_add(zhp, nvroot) != 0);
510 }
511
512 nvlist_free(nvroot);
513 zpool_close(zhp);
514
515 return (ret);
516 }
517
518 /*
519 * zpool remove <pool> <vdev> ...
520 *
521 * Removes the given vdev from the pool. Currently, this only supports removing
522 * spares and cache devices from the pool. Eventually, we'll want to support
523 * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
524 */
525 int
526 zpool_do_remove(int argc, char **argv)
527 {
528 char *poolname;
529 int i, ret = 0;
530 zpool_handle_t *zhp;
531
532 argc--;
533 argv++;
534
535 /* get pool name and check number of arguments */
536 if (argc < 1) {
537 (void) fprintf(stderr, gettext("missing pool name argument\n"));
538 usage(B_FALSE);
539 }
540 if (argc < 2) {
541 (void) fprintf(stderr, gettext("missing device\n"));
542 usage(B_FALSE);
543 }
544
545 poolname = argv[0];
546
547 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
548 return (1);
549
550 for (i = 1; i < argc; i++) {
551 if (zpool_vdev_remove(zhp, argv[i]) != 0)
552 ret = 1;
553 }
554
555 return (ret);
556 }
557
558 /*
559 * zpool create [-fn] [-o property=value] ...
560 * [-O file-system-property=value] ...
561 * [-R root] [-m mountpoint] <pool> <dev> ...
562 *
563 * -f Force creation, even if devices appear in use
564 * -n Do not create the pool, but display the resulting layout if it
565 * were to be created.
566 * -R Create a pool under an alternate root
567 * -m Set default mountpoint for the root dataset. By default it's
568 * '/<pool>'
569 * -o Set property=value.
570 * -O Set fsproperty=value in the pool's root file system
571 *
572 * Creates the named pool according to the given vdev specification. The
573 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
574 * we get the nvlist back from get_vdev_spec(), we either print out the contents
575 * (if '-n' was specified), or pass it to libzfs to do the creation.
576 */
577 int
578 zpool_do_create(int argc, char **argv)
579 {
580 boolean_t force = B_FALSE;
581 boolean_t dryrun = B_FALSE;
582 int c;
583 nvlist_t *nvroot = NULL;
584 char *poolname;
585 int ret = 1;
586 char *altroot = NULL;
587 char *mountpoint = NULL;
588 nvlist_t *fsprops = NULL;
589 nvlist_t *props = NULL;
590 char *propval;
591
592 /* check options */
593 while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
594 switch (c) {
595 case 'f':
596 force = B_TRUE;
597 break;
598 case 'n':
599 dryrun = B_TRUE;
600 break;
601 case 'R':
602 altroot = optarg;
603 if (add_prop_list(zpool_prop_to_name(
604 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
605 goto errout;
606 if (nvlist_lookup_string(props,
607 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
608 &propval) == 0)
609 break;
610 if (add_prop_list(zpool_prop_to_name(
611 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
612 goto errout;
613 break;
614 case 'm':
615 mountpoint = optarg;
616 break;
617 case 'o':
618 if ((propval = strchr(optarg, '=')) == NULL) {
619 (void) fprintf(stderr, gettext("missing "
620 "'=' for -o option\n"));
621 goto errout;
622 }
623 *propval = '\0';
624 propval++;
625
626 if (add_prop_list(optarg, propval, &props, B_TRUE))
627 goto errout;
628 break;
629 case 'O':
630 if ((propval = strchr(optarg, '=')) == NULL) {
631 (void) fprintf(stderr, gettext("missing "
632 "'=' for -O option\n"));
633 goto errout;
634 }
635 *propval = '\0';
636 propval++;
637
638 if (add_prop_list(optarg, propval, &fsprops, B_FALSE))
639 goto errout;
640 break;
641 case ':':
642 (void) fprintf(stderr, gettext("missing argument for "
643 "'%c' option\n"), optopt);
644 goto badusage;
645 case '?':
646 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
647 optopt);
648 goto badusage;
649 }
650 }
651
652 argc -= optind;
653 argv += optind;
654
655 /* get pool name and check number of arguments */
656 if (argc < 1) {
657 (void) fprintf(stderr, gettext("missing pool name argument\n"));
658 goto badusage;
659 }
660 if (argc < 2) {
661 (void) fprintf(stderr, gettext("missing vdev specification\n"));
662 goto badusage;
663 }
664
665 poolname = argv[0];
666
667 /*
668 * As a special case, check for use of '/' in the name, and direct the
669 * user to use 'zfs create' instead.
670 */
671 if (strchr(poolname, '/') != NULL) {
672 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
673 "character '/' in pool name\n"), poolname);
674 (void) fprintf(stderr, gettext("use 'zfs create' to "
675 "create a dataset\n"));
676 goto errout;
677 }
678
679 /* pass off to get_vdev_spec for bulk processing */
680 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
681 argc - 1, argv + 1);
682 if (nvroot == NULL)
683 goto errout;
684
685 /* make_root_vdev() allows 0 toplevel children if there are spares */
686 if (!zfs_allocatable_devs(nvroot)) {
687 (void) fprintf(stderr, gettext("invalid vdev "
688 "specification: at least one toplevel vdev must be "
689 "specified\n"));
690 goto errout;
691 }
692
693
694 if (altroot != NULL && altroot[0] != '/') {
695 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
696 "must be an absolute path\n"), altroot);
697 goto errout;
698 }
699
700 /*
701 * Check the validity of the mountpoint and direct the user to use the
702 * '-m' mountpoint option if it looks like its in use.
703 */
704 if (mountpoint == NULL ||
705 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
706 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
707 char buf[MAXPATHLEN];
708 DIR *dirp;
709
710 if (mountpoint && mountpoint[0] != '/') {
711 (void) fprintf(stderr, gettext("invalid mountpoint "
712 "'%s': must be an absolute path, 'legacy', or "
713 "'none'\n"), mountpoint);
714 goto errout;
715 }
716
717 if (mountpoint == NULL) {
718 if (altroot != NULL)
719 (void) snprintf(buf, sizeof (buf), "%s/%s",
720 altroot, poolname);
721 else
722 (void) snprintf(buf, sizeof (buf), "/%s",
723 poolname);
724 } else {
725 if (altroot != NULL)
726 (void) snprintf(buf, sizeof (buf), "%s%s",
727 altroot, mountpoint);
728 else
729 (void) snprintf(buf, sizeof (buf), "%s",
730 mountpoint);
731 }
732
733 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
734 (void) fprintf(stderr, gettext("mountpoint '%s' : "
735 "%s\n"), buf, strerror(errno));
736 (void) fprintf(stderr, gettext("use '-m' "
737 "option to provide a different default\n"));
738 goto errout;
739 } else if (dirp) {
740 int count = 0;
741
742 while (count < 3 && readdir(dirp) != NULL)
743 count++;
744 (void) closedir(dirp);
745
746 if (count > 2) {
747 (void) fprintf(stderr, gettext("mountpoint "
748 "'%s' exists and is not empty\n"), buf);
749 (void) fprintf(stderr, gettext("use '-m' "
750 "option to provide a "
751 "different default\n"));
752 goto errout;
753 }
754 }
755 }
756
757 if (dryrun) {
758 /*
759 * For a dry run invocation, print out a basic message and run
760 * through all the vdevs in the list and print out in an
761 * appropriate hierarchy.
762 */
763 (void) printf(gettext("would create '%s' with the "
764 "following layout:\n\n"), poolname);
765
766 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
767 if (num_logs(nvroot) > 0)
768 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
769
770 ret = 0;
771 } else {
772 /*
773 * Hand off to libzfs.
774 */
775 if (zpool_create(g_zfs, poolname,
776 nvroot, props, fsprops) == 0) {
777 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
778 ZFS_TYPE_FILESYSTEM);
779 if (pool != NULL) {
780 if (mountpoint != NULL)
781 verify(zfs_prop_set(pool,
782 zfs_prop_to_name(
783 ZFS_PROP_MOUNTPOINT),
784 mountpoint) == 0);
785 if (zfs_mount(pool, NULL, 0) == 0)
786 ret = zfs_shareall(pool);
787 zfs_close(pool);
788 }
789 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
790 (void) fprintf(stderr, gettext("pool name may have "
791 "been omitted\n"));
792 }
793 }
794
795 errout:
796 nvlist_free(nvroot);
797 nvlist_free(fsprops);
798 nvlist_free(props);
799 return (ret);
800 badusage:
801 nvlist_free(fsprops);
802 nvlist_free(props);
803 usage(B_FALSE);
804 return (2);
805 }
806
807 /*
808 * zpool destroy <pool>
809 *
810 * -f Forcefully unmount any datasets
811 *
812 * Destroy the given pool. Automatically unmounts any datasets in the pool.
813 */
814 int
815 zpool_do_destroy(int argc, char **argv)
816 {
817 boolean_t force = B_FALSE;
818 boolean_t encrypted_only = B_FALSE;
819 int c;
820 char *pool;
821 zpool_handle_t *zhp;
822 int ret;
823
824 /* check options */
825 while ((c = getopt(argc, argv, "f")) != -1) {
826 switch (c) {
827 case 'f':
828 force = B_TRUE;
829 break;
830 case '?':
831 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
832 optopt);
833 usage(B_FALSE);
834 }
835 }
836
837 argc -= optind;
838 argv += optind;
839
840 /* check arguments */
841 if (argc < 1) {
842 (void) fprintf(stderr, gettext("missing pool argument\n"));
843 usage(B_FALSE);
844 }
845 if (argc > 1) {
846 (void) fprintf(stderr, gettext("too many arguments\n"));
847 usage(B_FALSE);
848 }
849
850 pool = argv[0];
851
852 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
853 /*
854 * As a special case, check for use of '/' in the name, and
855 * direct the user to use 'zfs destroy' instead.
856 */
857 if (strchr(pool, '/') != NULL)
858 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
859 "destroy a dataset\n"));
860 return (1);
861 }
862
863 if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
864 (void) fprintf(stderr, gettext("could not destroy '%s': "
865 "could not unmount datasets\n"), zpool_get_name(zhp));
866 return (1);
867 }
868
869 ret = (zpool_destroy(zhp) != 0);
870
871 zpool_close(zhp);
872
873 return (ret);
874 }
875
876 /*
877 * zpool export [-f] <pool> ...
878 *
879 * -f Forcefully unmount datasets
880 *
881 * Export the given pools. By default, the command will attempt to cleanly
882 * unmount any active datasets within the pool. If the '-f' flag is specified,
883 * then the datasets will be forcefully unmounted.
884 */
885 int
886 zpool_do_export(int argc, char **argv)
887 {
888 boolean_t force = B_FALSE;
889 boolean_t hardforce = B_FALSE;
890 boolean_t encrypted_only = B_FALSE;
891 int c;
892 zpool_handle_t *zhp;
893 int ret;
894 int i;
895
896 /* check options */
897 while ((c = getopt(argc, argv, "fF")) != -1) {
898 switch (c) {
899 case 'f':
900 force = B_TRUE;
901 break;
902 case 'F':
903 hardforce = B_TRUE;
904 break;
905 case '?':
906 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
907 optopt);
908 usage(B_FALSE);
909 }
910 }
911
912 argc -= optind;
913 argv += optind;
914
915 /* check arguments */
916 if (argc < 1) {
917 (void) fprintf(stderr, gettext("missing pool argument\n"));
918 usage(B_FALSE);
919 }
920
921 ret = 0;
922 for (i = 0; i < argc; i++) {
923 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
924 ret = 1;
925 continue;
926 }
927
928 if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
929 ret = 1;
930 zpool_close(zhp);
931 continue;
932 }
933
934 if (hardforce) {
935 if (zpool_export_force(zhp) != 0)
936 ret = 1;
937 } else if (zpool_export(zhp, force) != 0) {
938 ret = 1;
939 }
940
941 zpool_close(zhp);
942 }
943
944 return (ret);
945 }
946
947 /*
948 * Given a vdev configuration, determine the maximum width needed for the device
949 * name column.
950 */
951 static int
952 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
953 {
954 char *name = zpool_vdev_name(g_zfs, zhp, nv);
955 nvlist_t **child;
956 uint_t c, children;
957 int ret;
958
959 if (strlen(name) + depth > max)
960 max = strlen(name) + depth;
961
962 free(name);
963
964 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
965 &child, &children) == 0) {
966 for (c = 0; c < children; c++)
967 if ((ret = max_width(zhp, child[c], depth + 2,
968 max)) > max)
969 max = ret;
970 }
971
972 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
973 &child, &children) == 0) {
974 for (c = 0; c < children; c++)
975 if ((ret = max_width(zhp, child[c], depth + 2,
976 max)) > max)
977 max = ret;
978 }
979
980 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
981 &child, &children) == 0) {
982 for (c = 0; c < children; c++)
983 if ((ret = max_width(zhp, child[c], depth + 2,
984 max)) > max)
985 max = ret;
986 }
987
988
989 return (max);
990 }
991
992
993 /*
994 * Print the configuration of an exported pool. Iterate over all vdevs in the
995 * pool, printing out the name and status for each one.
996 */
997 void
998 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
999 boolean_t print_logs)
1000 {
1001 nvlist_t **child;
1002 uint_t c, children;
1003 vdev_stat_t *vs;
1004 char *type, *vname;
1005
1006 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1007 if (strcmp(type, VDEV_TYPE_MISSING) == 0)
1008 return;
1009
1010 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
1011 (uint64_t **)&vs, &c) == 0);
1012
1013 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1014 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1015
1016 if (vs->vs_aux != 0) {
1017 (void) printf(" ");
1018
1019 switch (vs->vs_aux) {
1020 case VDEV_AUX_OPEN_FAILED:
1021 (void) printf(gettext("cannot open"));
1022 break;
1023
1024 case VDEV_AUX_BAD_GUID_SUM:
1025 (void) printf(gettext("missing device"));
1026 break;
1027
1028 case VDEV_AUX_NO_REPLICAS:
1029 (void) printf(gettext("insufficient replicas"));
1030 break;
1031
1032 case VDEV_AUX_VERSION_NEWER:
1033 (void) printf(gettext("newer version"));
1034 break;
1035
1036 case VDEV_AUX_ERR_EXCEEDED:
1037 (void) printf(gettext("too many errors"));
1038 break;
1039
1040 default:
1041 (void) printf(gettext("corrupted data"));
1042 break;
1043 }
1044 }
1045 (void) printf("\n");
1046
1047 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1048 &child, &children) != 0)
1049 return;
1050
1051 for (c = 0; c < children; c++) {
1052 uint64_t is_log = B_FALSE;
1053
1054 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1055 &is_log);
1056 if ((is_log && !print_logs) || (!is_log && print_logs))
1057 continue;
1058
1059 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1060 print_import_config(vname, child[c],
1061 namewidth, depth + 2, B_FALSE);
1062 free(vname);
1063 }
1064
1065 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1066 &child, &children) == 0) {
1067 (void) printf(gettext("\tcache\n"));
1068 for (c = 0; c < children; c++) {
1069 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1070 (void) printf("\t %s\n", vname);
1071 free(vname);
1072 }
1073 }
1074
1075 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1076 &child, &children) == 0) {
1077 (void) printf(gettext("\tspares\n"));
1078 for (c = 0; c < children; c++) {
1079 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1080 (void) printf("\t %s\n", vname);
1081 free(vname);
1082 }
1083 }
1084 }
1085
1086 /*
1087 * Display the status for the given pool.
1088 */
1089 static void
1090 show_import(nvlist_t *config)
1091 {
1092 uint64_t pool_state;
1093 vdev_stat_t *vs;
1094 char *name;
1095 uint64_t guid;
1096 char *msgid;
1097 nvlist_t *nvroot;
1098 int reason;
1099 const char *health;
1100 uint_t vsc;
1101 int namewidth;
1102
1103 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1104 &name) == 0);
1105 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1106 &guid) == 0);
1107 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1108 &pool_state) == 0);
1109 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1110 &nvroot) == 0);
1111
1112 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1113 (uint64_t **)&vs, &vsc) == 0);
1114 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1115
1116 reason = zpool_import_status(config, &msgid);
1117
1118 (void) printf(gettext(" pool: %s\n"), name);
1119 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1120 (void) printf(gettext(" state: %s"), health);
1121 if (pool_state == POOL_STATE_DESTROYED)
1122 (void) printf(gettext(" (DESTROYED)"));
1123 (void) printf("\n");
1124
1125 switch (reason) {
1126 case ZPOOL_STATUS_MISSING_DEV_R:
1127 case ZPOOL_STATUS_MISSING_DEV_NR:
1128 case ZPOOL_STATUS_BAD_GUID_SUM:
1129 (void) printf(gettext("status: One or more devices are missing "
1130 "from the system.\n"));
1131 break;
1132
1133 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1134 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1135 (void) printf(gettext("status: One or more devices contains "
1136 "corrupted data.\n"));
1137 break;
1138
1139 case ZPOOL_STATUS_CORRUPT_DATA:
1140 (void) printf(gettext("status: The pool data is corrupted.\n"));
1141 break;
1142
1143 case ZPOOL_STATUS_OFFLINE_DEV:
1144 (void) printf(gettext("status: One or more devices "
1145 "are offlined.\n"));
1146 break;
1147
1148 case ZPOOL_STATUS_CORRUPT_POOL:
1149 (void) printf(gettext("status: The pool metadata is "
1150 "corrupted.\n"));
1151 break;
1152
1153 case ZPOOL_STATUS_VERSION_OLDER:
1154 (void) printf(gettext("status: The pool is formatted using an "
1155 "older on-disk version.\n"));
1156 break;
1157
1158 case ZPOOL_STATUS_VERSION_NEWER:
1159 (void) printf(gettext("status: The pool is formatted using an "
1160 "incompatible version.\n"));
1161 break;
1162
1163 case ZPOOL_STATUS_HOSTID_MISMATCH:
1164 (void) printf(gettext("status: The pool was last accessed by "
1165 "another system.\n"));
1166 break;
1167
1168 case ZPOOL_STATUS_FAULTED_DEV_R:
1169 case ZPOOL_STATUS_FAULTED_DEV_NR:
1170 (void) printf(gettext("status: One or more devices are "
1171 "faulted.\n"));
1172 break;
1173
1174 case ZPOOL_STATUS_BAD_LOG:
1175 (void) printf(gettext("status: An intent log record cannot be "
1176 "read.\n"));
1177 break;
1178
1179 default:
1180 /*
1181 * No other status can be seen when importing pools.
1182 */
1183 assert(reason == ZPOOL_STATUS_OK);
1184 }
1185
1186 /*
1187 * Print out an action according to the overall state of the pool.
1188 */
1189 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1190 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1191 (void) printf(gettext("action: The pool can be "
1192 "imported using its name or numeric identifier, "
1193 "though\n\tsome features will not be available "
1194 "without an explicit 'zpool upgrade'.\n"));
1195 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1196 (void) printf(gettext("action: The pool can be "
1197 "imported using its name or numeric "
1198 "identifier and\n\tthe '-f' flag.\n"));
1199 else
1200 (void) printf(gettext("action: The pool can be "
1201 "imported using its name or numeric "
1202 "identifier.\n"));
1203 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1204 (void) printf(gettext("action: The pool can be imported "
1205 "despite missing or damaged devices. The\n\tfault "
1206 "tolerance of the pool may be compromised if imported.\n"));
1207 } else {
1208 switch (reason) {
1209 case ZPOOL_STATUS_VERSION_NEWER:
1210 (void) printf(gettext("action: The pool cannot be "
1211 "imported. Access the pool on a system running "
1212 "newer\n\tsoftware, or recreate the pool from "
1213 "backup.\n"));
1214 break;
1215 case ZPOOL_STATUS_MISSING_DEV_R:
1216 case ZPOOL_STATUS_MISSING_DEV_NR:
1217 case ZPOOL_STATUS_BAD_GUID_SUM:
1218 (void) printf(gettext("action: The pool cannot be "
1219 "imported. Attach the missing\n\tdevices and try "
1220 "again.\n"));
1221 break;
1222 default:
1223 (void) printf(gettext("action: The pool cannot be "
1224 "imported due to damaged devices or data.\n"));
1225 }
1226 }
1227
1228 /*
1229 * If the state is "closed" or "can't open", and the aux state
1230 * is "corrupt data":
1231 */
1232 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1233 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1234 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1235 if (pool_state == POOL_STATE_DESTROYED)
1236 (void) printf(gettext("\tThe pool was destroyed, "
1237 "but can be imported using the '-Df' flags.\n"));
1238 else if (pool_state != POOL_STATE_EXPORTED)
1239 (void) printf(gettext("\tThe pool may be active on "
1240 "another system, but can be imported using\n\t"
1241 "the '-f' flag.\n"));
1242 }
1243
1244 if (msgid != NULL)
1245 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
1246 msgid);
1247
1248 (void) printf(gettext("config:\n\n"));
1249
1250 namewidth = max_width(NULL, nvroot, 0, 0);
1251 if (namewidth < 10)
1252 namewidth = 10;
1253
1254 print_import_config(name, nvroot, namewidth, 0, B_FALSE);
1255 if (num_logs(nvroot) > 0) {
1256 (void) printf(gettext("\tlogs\n"));
1257 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1258 }
1259
1260 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1261 (void) printf(gettext("\n\tAdditional devices are known to "
1262 "be part of this pool, though their\n\texact "
1263 "configuration cannot be determined.\n"));
1264 }
1265 }
1266
1267 /*
1268 * Perform the import for the given configuration. This passes the heavy
1269 * lifting off to zpool_import_props(), and then mounts the datasets contained
1270 * within the pool.
1271 */
1272 static int
1273 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1274 int force, nvlist_t *props, boolean_t allowfaulted)
1275 {
1276 boolean_t encrypted_only = B_FALSE;
1277 zpool_handle_t *zhp;
1278 char *name;
1279 uint64_t state;
1280 uint64_t version;
1281 int error = 0;
1282
1283 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1284 &name) == 0);
1285
1286 verify(nvlist_lookup_uint64(config,
1287 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1288 verify(nvlist_lookup_uint64(config,
1289 ZPOOL_CONFIG_VERSION, &version) == 0);
1290 if (version > SPA_VERSION) {
1291 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1292 "is formatted using a newer ZFS version\n"), name);
1293 return (1);
1294 } else if (state != POOL_STATE_EXPORTED && !force) {
1295 uint64_t hostid;
1296
1297 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1298 &hostid) == 0) {
1299 if ((unsigned long)hostid != gethostid()) {
1300 char *hostname;
1301 uint64_t timestamp;
1302 time_t t;
1303
1304 verify(nvlist_lookup_string(config,
1305 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1306 verify(nvlist_lookup_uint64(config,
1307 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0);
1308 t = timestamp;
1309 (void) fprintf(stderr, gettext("cannot import "
1310 "'%s': pool may be in use from other "
1311 "system, it was last accessed by %s "
1312 "(hostid: 0x%lx) on %s"), name, hostname,
1313 (unsigned long)hostid,
1314 asctime(localtime(&t)));
1315 (void) fprintf(stderr, gettext("use '-f' to "
1316 "import anyway\n"));
1317 return (1);
1318 }
1319 } else {
1320 (void) fprintf(stderr, gettext("cannot import '%s': "
1321 "pool may be in use from other system\n"), name);
1322 (void) fprintf(stderr, gettext("use '-f' to import "
1323 "anyway\n"));
1324 return (1);
1325 }
1326 }
1327
1328 if (zpool_import_props(g_zfs, config, newname, props,
1329 allowfaulted) != 0)
1330 return (1);
1331
1332 if (newname != NULL)
1333 name = (char *)newname;
1334
1335 verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1336
1337 /*
1338 * Attempt to load the crypto keys before mounting up the datasets
1339 * Note that depending on the value of the keysource property
1340 * this could cause us to go interactive.
1341 * We don't mind if this falls though and continue to enable what
1342 * datasets we can if it does.
1343 *
1344 * Use zpool_load_key() and tell it we are doing an import rather than
1345 * zpool_cmd_key_load().
1346 *
1347 * We then attempt enable all datasets not just the encrypted ones.
1348 */
1349
1350 error = zpool_load_key(zhp, B_TRUE);
1351 if (error != 0 && error != ENOTSUP) {
1352 libzfs_handle_t *zpool_hdl = zpool_get_handle(zhp);
1353 (void) fprintf(stderr, gettext(
1354 "%s.\nEncrypted datasets with keyscope=pool "
1355 "will not be mounted.\n"),
1356 libzfs_error_description(zpool_hdl));
1357 }
1358
1359 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1360 zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
1361 zpool_close(zhp);
1362 return (1);
1363 }
1364
1365 zpool_close(zhp);
1366 return (0);
1367 }
1368
1369 /*
1370 * zpool import [-d dir] [-D]
1371 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1372 * [-d dir | -c cachefile] [-f] -a
1373 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1374 * [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1375 *
1376 * -c Read pool information from a cachefile instead of searching
1377 * devices.
1378 *
1379 * -d Scan in a specific directory, other than /dev/dsk. More than
1380 * one directory can be specified using multiple '-d' options.
1381 *
1382 * -D Scan for previously destroyed pools or import all or only
1383 * specified destroyed pools.
1384 *
1385 * -R Temporarily import the pool, with all mountpoints relative to
1386 * the given root. The pool will remain exported when the machine
1387 * is rebooted.
1388 *
1389 * -f Force import, even if it appears that the pool is active.
1390 *
1391 * -F Import even in the presence of faulted vdevs. This is an
1392 * intentionally undocumented option for testing purposes, and
1393 * treats the pool configuration as complete, leaving any bad
1394 * vdevs in the FAULTED state.
1395 *
1396 * -a Import all pools found.
1397 *
1398 * -o Set property=value and/or temporary mount options (without '=').
1399 *
1400 * The import command scans for pools to import, and import pools based on pool
1401 * name and GUID. The pool can also be renamed as part of the import process.
1402 */
1403 int
1404 zpool_do_import(int argc, char **argv)
1405 {
1406 char **searchdirs = NULL;
1407 int nsearch = 0;
1408 int c;
1409 int err;
1410 nvlist_t *pools = NULL;
1411 boolean_t do_all = B_FALSE;
1412 boolean_t do_destroyed = B_FALSE;
1413 char *mntopts = NULL;
1414 boolean_t do_force = B_FALSE;
1415 nvpair_t *elem;
1416 nvlist_t *config;
1417 uint64_t searchguid = 0;
1418 char *searchname = NULL;
1419 char *propval;
1420 nvlist_t *found_config;
1421 nvlist_t *props = NULL;
1422 boolean_t first;
1423 boolean_t allow_faulted = B_FALSE;
1424 uint64_t pool_state;
1425 char *cachefile = NULL;
1426
1427 /* check options */
1428 while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) {
1429 switch (c) {
1430 case 'a':
1431 do_all = B_TRUE;
1432 break;
1433 case 'c':
1434 cachefile = optarg;
1435 break;
1436 case 'd':
1437 if (searchdirs == NULL) {
1438 searchdirs = safe_malloc(sizeof (char *));
1439 } else {
1440 char **tmp = safe_malloc((nsearch + 1) *
1441 sizeof (char *));
1442 bcopy(searchdirs, tmp, nsearch *
1443 sizeof (char *));
1444 free(searchdirs);
1445 searchdirs = tmp;
1446 }
1447 searchdirs[nsearch++] = optarg;
1448 break;
1449 case 'D':
1450 do_destroyed = B_TRUE;
1451 break;
1452 case 'f':
1453 do_force = B_TRUE;
1454 break;
1455 case 'F':
1456 allow_faulted = B_TRUE;
1457 break;
1458 case 'o':
1459 if ((propval = strchr(optarg, '=')) != NULL) {
1460 *propval = '\0';
1461 propval++;
1462 if (add_prop_list(optarg, propval,
1463 &props, B_TRUE))
1464 goto error;
1465 } else {
1466 mntopts = optarg;
1467 }
1468 break;
1469 case 'R':
1470 if (add_prop_list(zpool_prop_to_name(
1471 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1472 goto error;
1473 if (nvlist_lookup_string(props,
1474 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1475 &propval) == 0)
1476 break;
1477 if (add_prop_list(zpool_prop_to_name(
1478 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1479 goto error;
1480 break;
1481 case ':':
1482 (void) fprintf(stderr, gettext("missing argument for "
1483 "'%c' option\n"), optopt);
1484 usage(B_FALSE);
1485 break;
1486 case '?':
1487 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1488 optopt);
1489 usage(B_FALSE);
1490 }
1491 }
1492
1493 argc -= optind;
1494 argv += optind;
1495
1496 if (cachefile && nsearch != 0) {
1497 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1498 usage(B_FALSE);
1499 }
1500
1501 if (searchdirs == NULL) {
1502 searchdirs = safe_malloc(sizeof (char *));
1503 searchdirs[0] = "/dev/dsk";
1504 nsearch = 1;
1505 }
1506
1507 /* check argument count */
1508 if (do_all) {
1509 if (argc != 0) {
1510 (void) fprintf(stderr, gettext("too many arguments\n"));
1511 usage(B_FALSE);
1512 }
1513 } else {
1514 if (argc > 2) {
1515 (void) fprintf(stderr, gettext("too many arguments\n"));
1516 usage(B_FALSE);
1517 }
1518
1519 /*
1520 * Check for the SYS_CONFIG privilege. We do this explicitly
1521 * here because otherwise any attempt to discover pools will
1522 * silently fail.
1523 */
1524 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1525 (void) fprintf(stderr, gettext("cannot "
1526 "discover pools: permission denied\n"));
1527 free(searchdirs);
1528 return (1);
1529 }
1530 }
1531
1532 /*
1533 * Depending on the arguments given, we do one of the following:
1534 *
1535 * <none> Iterate through all pools and display information about
1536 * each one.
1537 *
1538 * -a Iterate through all pools and try to import each one.
1539 *
1540 * <id> Find the pool that corresponds to the given GUID/pool
1541 * name and import that one.
1542 *
1543 * -D Above options applies only to destroyed pools.
1544 */
1545 if (argc != 0) {
1546 char *endptr;
1547
1548 errno = 0;
1549 searchguid = strtoull(argv[0], &endptr, 10);
1550 if (errno != 0 || *endptr != '\0')
1551 searchname = argv[0];
1552 found_config = NULL;
1553 }
1554
1555 if (cachefile) {
1556 pools = zpool_find_import_cached(g_zfs, cachefile, searchname,
1557 searchguid);
1558 } else if (searchname != NULL) {
1559 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs,
1560 searchname);
1561 } else {
1562 /*
1563 * It's OK to search by guid even if searchguid is 0.
1564 */
1565 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs,
1566 searchguid);
1567 }
1568
1569 if (pools == NULL) {
1570 if (argc != 0) {
1571 (void) fprintf(stderr, gettext("cannot import '%s': "
1572 "no such pool available\n"), argv[0]);
1573 }
1574 free(searchdirs);
1575 return (1);
1576 }
1577
1578 /*
1579 * At this point we have a list of import candidate configs. Even if
1580 * we were searching by pool name or guid, we still need to
1581 * post-process the list to deal with pool state and possible
1582 * duplicate names.
1583 */
1584 err = 0;
1585 elem = NULL;
1586 first = B_TRUE;
1587 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1588
1589 verify(nvpair_value_nvlist(elem, &config) == 0);
1590
1591 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1592 &pool_state) == 0);
1593 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1594 continue;
1595 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1596 continue;
1597
1598 if (argc == 0) {
1599 if (first)
1600 first = B_FALSE;
1601 else if (!do_all)
1602 (void) printf("\n");
1603
1604 if (do_all)
1605 err |= do_import(config, NULL, mntopts,
1606 do_force, props, allow_faulted);
1607 else
1608 show_import(config);
1609 } else if (searchname != NULL) {
1610 char *name;
1611
1612 /*
1613 * We are searching for a pool based on name.
1614 */
1615 verify(nvlist_lookup_string(config,
1616 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1617
1618 if (strcmp(name, searchname) == 0) {
1619 if (found_config != NULL) {
1620 (void) fprintf(stderr, gettext(
1621 "cannot import '%s': more than "
1622 "one matching pool\n"), searchname);
1623 (void) fprintf(stderr, gettext(
1624 "import by numeric ID instead\n"));
1625 err = B_TRUE;
1626 }
1627 found_config = config;
1628 }
1629 } else {
1630 uint64_t guid;
1631
1632 /*
1633 * Search for a pool by guid.
1634 */
1635 verify(nvlist_lookup_uint64(config,
1636 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1637
1638 if (guid == searchguid)
1639 found_config = config;
1640 }
1641 }
1642
1643 /*
1644 * If we were searching for a specific pool, verify that we found a
1645 * pool, and then do the import.
1646 */
1647 if (argc != 0 && err == 0) {
1648 if (found_config == NULL) {
1649 (void) fprintf(stderr, gettext("cannot import '%s': "
1650 "no such pool available\n"), argv[0]);
1651 err = B_TRUE;
1652 } else {
1653 err |= do_import(found_config, argc == 1 ? NULL :
1654 argv[1], mntopts, do_force, props, allow_faulted);
1655 }
1656 }
1657
1658 /*
1659 * If we were just looking for pools, report an error if none were
1660 * found.
1661 */
1662 if (argc == 0 && first)
1663 (void) fprintf(stderr,
1664 gettext("no pools available to import\n"));
1665
1666 error:
1667 nvlist_free(props);
1668 nvlist_free(pools);
1669 free(searchdirs);
1670
1671 return (err ? 1 : 0);
1672 }
1673
1674 typedef struct iostat_cbdata {
1675 zpool_list_t *cb_list;
1676 int cb_verbose;
1677 int cb_iteration;
1678 int cb_namewidth;
1679 } iostat_cbdata_t;
1680
1681 static void
1682 print_iostat_separator(iostat_cbdata_t *cb)
1683 {
1684 int i = 0;
1685
1686 for (i = 0; i < cb->cb_namewidth; i++)
1687 (void) printf("-");
1688 (void) printf(" ----- ----- ----- ----- ----- -----\n");
1689 }
1690
1691 static void
1692 print_iostat_header(iostat_cbdata_t *cb)
1693 {
1694 (void) printf("%*s capacity operations bandwidth\n",
1695 cb->cb_namewidth, "");
1696 (void) printf("%-*s used avail read write read write\n",
1697 cb->cb_namewidth, "pool");
1698 print_iostat_separator(cb);
1699 }
1700
1701 /*
1702 * Display a single statistic.
1703 */
1704 static void
1705 print_one_stat(uint64_t value)
1706 {
1707 char buf[64];
1708
1709 zfs_nicenum(value, buf, sizeof (buf));
1710 (void) printf(" %5s", buf);
1711 }
1712
1713 /*
1714 * Print out all the statistics for the given vdev. This can either be the
1715 * toplevel configuration, or called recursively. If 'name' is NULL, then this
1716 * is a verbose output, and we don't want to display the toplevel pool stats.
1717 */
1718 void
1719 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1720 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1721 {
1722 nvlist_t **oldchild, **newchild;
1723 uint_t c, children;
1724 vdev_stat_t *oldvs, *newvs;
1725 vdev_stat_t zerovs = { 0 };
1726 uint64_t tdelta;
1727 double scale;
1728 char *vname;
1729
1730 if (oldnv != NULL) {
1731 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1732 (uint64_t **)&oldvs, &c) == 0);
1733 } else {
1734 oldvs = &zerovs;
1735 }
1736
1737 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1738 (uint64_t **)&newvs, &c) == 0);
1739
1740 if (strlen(name) + depth > cb->cb_namewidth)
1741 (void) printf("%*s%s", depth, "", name);
1742 else
1743 (void) printf("%*s%s%*s", depth, "", name,
1744 (int)(cb->cb_namewidth - strlen(name) - depth), "");
1745
1746 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1747
1748 if (tdelta == 0)
1749 scale = 1.0;
1750 else
1751 scale = (double)NANOSEC / tdelta;
1752
1753 /* only toplevel vdevs have capacity stats */
1754 if (newvs->vs_space == 0) {
1755 (void) printf(" - -");
1756 } else {
1757 print_one_stat(newvs->vs_alloc);
1758 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1759 }
1760
1761 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1762 oldvs->vs_ops[ZIO_TYPE_READ])));
1763
1764 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1765 oldvs->vs_ops[ZIO_TYPE_WRITE])));
1766
1767 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1768 oldvs->vs_bytes[ZIO_TYPE_READ])));
1769
1770 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1771 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1772
1773 (void) printf("\n");
1774
1775 if (!cb->cb_verbose)
1776 return;
1777
1778 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1779 &newchild, &children) != 0)
1780 return;
1781
1782 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1783 &oldchild, &c) != 0)
1784 return;
1785
1786 for (c = 0; c < children; c++) {
1787 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1788 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1789 newchild[c], cb, depth + 2);
1790 free(vname);
1791 }
1792
1793 /*
1794 * Include level 2 ARC devices in iostat output
1795 */
1796 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1797 &newchild, &children) != 0)
1798 return;
1799
1800 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1801 &oldchild, &c) != 0)
1802 return;
1803
1804 if (children > 0) {
1805 (void) printf("%-*s - - - - - "
1806 "-\n", cb->cb_namewidth, "cache");
1807 for (c = 0; c < children; c++) {
1808 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1809 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1810 newchild[c], cb, depth + 2);
1811 free(vname);
1812 }
1813 }
1814 }
1815
1816 static int
1817 refresh_iostat(zpool_handle_t *zhp, void *data)
1818 {
1819 iostat_cbdata_t *cb = data;
1820 boolean_t missing;
1821
1822 /*
1823 * If the pool has disappeared, remove it from the list and continue.
1824 */
1825 if (zpool_refresh_stats(zhp, &missing) != 0)
1826 return (-1);
1827
1828 if (missing)
1829 pool_list_remove(cb->cb_list, zhp);
1830
1831 return (0);
1832 }
1833
1834 /*
1835 * Callback to print out the iostats for the given pool.
1836 */
1837 int
1838 print_iostat(zpool_handle_t *zhp, void *data)
1839 {
1840 iostat_cbdata_t *cb = data;
1841 nvlist_t *oldconfig, *newconfig;
1842 nvlist_t *oldnvroot, *newnvroot;
1843
1844 newconfig = zpool_get_config(zhp, &oldconfig);
1845
1846 if (cb->cb_iteration == 1)
1847 oldconfig = NULL;
1848
1849 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1850 &newnvroot) == 0);
1851
1852 if (oldconfig == NULL)
1853 oldnvroot = NULL;
1854 else
1855 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1856 &oldnvroot) == 0);
1857
1858 /*
1859 * Print out the statistics for the pool.
1860 */
1861 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1862
1863 if (cb->cb_verbose)
1864 print_iostat_separator(cb);
1865
1866 return (0);
1867 }
1868
1869 int
1870 get_namewidth(zpool_handle_t *zhp, void *data)
1871 {
1872 iostat_cbdata_t *cb = data;
1873 nvlist_t *config, *nvroot;
1874
1875 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1876 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1877 &nvroot) == 0);
1878 if (!cb->cb_verbose)
1879 cb->cb_namewidth = strlen(zpool_get_name(zhp));
1880 else
1881 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1882 }
1883
1884 /*
1885 * The width must fall into the range [10,38]. The upper limit is the
1886 * maximum we can have and still fit in 80 columns.
1887 */
1888 if (cb->cb_namewidth < 10)
1889 cb->cb_namewidth = 10;
1890 if (cb->cb_namewidth > 38)
1891 cb->cb_namewidth = 38;
1892
1893 return (0);
1894 }
1895
1896 /*
1897 * zpool iostat [-v] [pool] ... [interval [count]]
1898 *
1899 * -v Display statistics for individual vdevs
1900 *
1901 * This command can be tricky because we want to be able to deal with pool
1902 * creation/destruction as well as vdev configuration changes. The bulk of this
1903 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
1904 * on pool_list_update() to detect the addition of new pools. Configuration
1905 * changes are all handled within libzfs.
1906 */
1907 int
1908 zpool_do_iostat(int argc, char **argv)
1909 {
1910 int c;
1911 int ret;
1912 int npools;
1913 unsigned long interval = 0, count = 0;
1914 zpool_list_t *list;
1915 boolean_t verbose = B_FALSE;
1916 iostat_cbdata_t cb;
1917
1918 /* check options */
1919 while ((c = getopt(argc, argv, "v")) != -1) {
1920 switch (c) {
1921 case 'v':
1922 verbose = B_TRUE;
1923 break;
1924 case '?':
1925 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1926 optopt);
1927 usage(B_FALSE);
1928 }
1929 }
1930
1931 argc -= optind;
1932 argv += optind;
1933
1934 /*
1935 * Determine if the last argument is an integer or a pool name
1936 */
1937 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1938 char *end;
1939
1940 errno = 0;
1941 interval = strtoul(argv[argc - 1], &end, 10);
1942
1943 if (*end == '\0' && errno == 0) {
1944 if (interval == 0) {
1945 (void) fprintf(stderr, gettext("interval "
1946 "cannot be zero\n"));
1947 usage(B_FALSE);
1948 }
1949
1950 /*
1951 * Ignore the last parameter
1952 */
1953 argc--;
1954 } else {
1955 /*
1956 * If this is not a valid number, just plow on. The
1957 * user will get a more informative error message later
1958 * on.
1959 */
1960 interval = 0;
1961 }
1962 }
1963
1964 /*
1965 * If the last argument is also an integer, then we have both a count
1966 * and an integer.
1967 */
1968 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1969 char *end;
1970
1971 errno = 0;
1972 count = interval;
1973 interval = strtoul(argv[argc - 1], &end, 10);
1974
1975 if (*end == '\0' && errno == 0) {
1976 if (interval == 0) {
1977 (void) fprintf(stderr, gettext("interval "
1978 "cannot be zero\n"));
1979 usage(B_FALSE);
1980 }
1981
1982 /*
1983 * Ignore the last parameter
1984 */
1985 argc--;
1986 } else {
1987 interval = 0;
1988 }
1989 }
1990
1991 /*
1992 * Construct the list of all interesting pools.
1993 */
1994 ret = 0;
1995 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1996 return (1);
1997
1998 if (pool_list_count(list) == 0 && argc != 0) {
1999 pool_list_free(list);
2000 return (1);
2001 }
2002
2003 if (pool_list_count(list) == 0 && interval == 0) {
2004 pool_list_free(list);
2005 (void) fprintf(stderr, gettext("no pools available\n"));
2006 return (1);
2007 }
2008
2009 /*
2010 * Enter the main iostat loop.
2011 */
2012 cb.cb_list = list;
2013 cb.cb_verbose = verbose;
2014 cb.cb_iteration = 0;
2015 cb.cb_namewidth = 0;
2016
2017 for (;;) {
2018 pool_list_update(list);
2019
2020 if ((npools = pool_list_count(list)) == 0)
2021 break;
2022
2023 /*
2024 * Refresh all statistics. This is done as an explicit step
2025 * before calculating the maximum name width, so that any
2026 * configuration changes are properly accounted for.
2027 */
2028 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2029
2030 /*
2031 * Iterate over all pools to determine the maximum width
2032 * for the pool / device name column across all pools.
2033 */
2034 cb.cb_namewidth = 0;
2035 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2036
2037 /*
2038 * If it's the first time, or verbose mode, print the header.
2039 */
2040 if (++cb.cb_iteration == 1 || verbose)
2041 print_iostat_header(&cb);
2042
2043 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2044
2045 /*
2046 * If there's more than one pool, and we're not in verbose mode
2047 * (which prints a separator for us), then print a separator.
2048 */
2049 if (npools > 1 && !verbose)
2050 print_iostat_separator(&cb);
2051
2052 if (verbose)
2053 (void) printf("\n");
2054
2055 /*
2056 * Flush the output so that redirection to a file isn't buffered
2057 * indefinitely.
2058 */
2059 (void) fflush(stdout);
2060
2061 if (interval == 0)
2062 break;
2063
2064 if (count != 0 && --count == 0)
2065 break;
2066
2067 (void) sleep(interval);
2068 }
2069
2070 pool_list_free(list);
2071
2072 return (ret);
2073 }
2074
2075 typedef struct list_cbdata {
2076 boolean_t cb_scripted;
2077 boolean_t cb_first;
2078 zprop_list_t *cb_proplist;
2079 } list_cbdata_t;
2080
2081 /*
2082 * Given a list of columns to display, output appropriate headers for each one.
2083 */
2084 static void
2085 print_header(zprop_list_t *pl)
2086 {
2087 const char *header;
2088 boolean_t first = B_TRUE;
2089 boolean_t right_justify;
2090
2091 for (; pl != NULL; pl = pl->pl_next) {
2092 if (pl->pl_prop == ZPROP_INVAL)
2093 continue;
2094
2095 if (!first)
2096 (void) printf(" ");
2097 else
2098 first = B_FALSE;
2099
2100 header = zpool_prop_column_name(pl->pl_prop);
2101 right_justify = zpool_prop_align_right(pl->pl_prop);
2102
2103 if (pl->pl_next == NULL && !right_justify)
2104 (void) printf("%s", header);
2105 else if (right_justify)
2106 (void) printf("%*s", pl->pl_width, header);
2107 else
2108 (void) printf("%-*s", pl->pl_width, header);
2109 }
2110
2111 (void) printf("\n");
2112 }
2113
2114 /*
2115 * Given a pool and a list of properties, print out all the properties according
2116 * to the described layout.
2117 */
2118 static void
2119 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2120 {
2121 boolean_t first = B_TRUE;
2122 char property[ZPOOL_MAXPROPLEN];
2123 char *propstr;
2124 boolean_t right_justify;
2125 int width;
2126
2127 for (; pl != NULL; pl = pl->pl_next) {
2128 if (!first) {
2129 if (scripted)
2130 (void) printf("\t");
2131 else
2132 (void) printf(" ");
2133 } else {
2134 first = B_FALSE;
2135 }
2136
2137 right_justify = B_FALSE;
2138 if (pl->pl_prop != ZPROP_INVAL) {
2139 if (zpool_get_prop(zhp, pl->pl_prop, property,
2140 sizeof (property), NULL) != 0)
2141 propstr = "-";
2142 else
2143 propstr = property;
2144
2145 right_justify = zpool_prop_align_right(pl->pl_prop);
2146 } else {
2147 propstr = "-";
2148 }
2149
2150 width = pl->pl_width;
2151
2152 /*
2153 * If this is being called in scripted mode, or if this is the
2154 * last column and it is left-justified, don't include a width
2155 * format specifier.
2156 */
2157 if (scripted || (pl->pl_next == NULL && !right_justify))
2158 (void) printf("%s", propstr);
2159 else if (right_justify)
2160 (void) printf("%*s", width, propstr);
2161 else
2162 (void) printf("%-*s", width, propstr);
2163 }
2164
2165 (void) printf("\n");
2166 }
2167
2168 /*
2169 * Generic callback function to list a pool.
2170 */
2171 int
2172 list_callback(zpool_handle_t *zhp, void *data)
2173 {
2174 list_cbdata_t *cbp = data;
2175
2176 if (cbp->cb_first) {
2177 if (!cbp->cb_scripted)
2178 print_header(cbp->cb_proplist);
2179 cbp->cb_first = B_FALSE;
2180 }
2181
2182 print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2183
2184 return (0);
2185 }
2186
2187 /*
2188 * zpool list [-H] [-o prop[,prop]*] [pool] ...
2189 *
2190 * -H Scripted mode. Don't display headers, and separate properties
2191 * by a single tab.
2192 * -o List of properties to display. Defaults to
2193 * "name,size,used,available,capacity,health,altroot"
2194 *
2195 * List all pools in the system, whether or not they're healthy. Output space
2196 * statistics for each one, as well as health status summary.
2197 */
2198 int
2199 zpool_do_list(int argc, char **argv)
2200 {
2201 int c;
2202 int ret;
2203 list_cbdata_t cb = { 0 };
2204 static char default_props[] =
2205 "name,size,used,available,capacity,health,altroot";
2206 char *props = default_props;
2207
2208 /* check options */
2209 while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2210 switch (c) {
2211 case 'H':
2212 cb.cb_scripted = B_TRUE;
2213 break;
2214 case 'o':
2215 props = optarg;
2216 break;
2217 case ':':
2218 (void) fprintf(stderr, gettext("missing argument for "
2219 "'%c' option\n"), optopt);
2220 usage(B_FALSE);
2221 break;
2222 case '?':
2223 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2224 optopt);
2225 usage(B_FALSE);
2226 }
2227 }
2228
2229 argc -= optind;
2230 argv += optind;
2231
2232 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2233 usage(B_FALSE);
2234
2235 cb.cb_first = B_TRUE;
2236
2237 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2238 list_callback, &cb);
2239
2240 zprop_free_list(cb.cb_proplist);
2241
2242 if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2243 (void) printf(gettext("no pools available\n"));
2244 return (0);
2245 }
2246
2247 return (ret);
2248 }
2249
2250 static nvlist_t *
2251 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2252 {
2253 nvlist_t **child;
2254 uint_t c, children;
2255 nvlist_t *match;
2256 char *path;
2257
2258 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2259 &child, &children) != 0) {
2260 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2261 if (strncmp(name, "/dev/dsk/", 9) == 0)
2262 name += 9;
2263 if (strncmp(path, "/dev/dsk/", 9) == 0)
2264 path += 9;
2265 if (strcmp(name, path) == 0)
2266 return (nv);
2267 return (NULL);
2268 }
2269
2270 for (c = 0; c < children; c++)
2271 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2272 return (match);
2273
2274 return (NULL);
2275 }
2276
2277 static int
2278 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2279 {
2280 boolean_t force = B_FALSE;
2281 int c;
2282 nvlist_t *nvroot;
2283 char *poolname, *old_disk, *new_disk;
2284 zpool_handle_t *zhp;
2285 int ret;
2286
2287 /* check options */
2288 while ((c = getopt(argc, argv, "f")) != -1) {
2289 switch (c) {
2290 case 'f':
2291 force = B_TRUE;
2292 break;
2293 case '?':
2294 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2295 optopt);
2296 usage(B_FALSE);
2297 }
2298 }
2299
2300 argc -= optind;
2301 argv += optind;
2302
2303 /* get pool name and check number of arguments */
2304 if (argc < 1) {
2305 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2306 usage(B_FALSE);
2307 }
2308
2309 poolname = argv[0];
2310
2311 if (argc < 2) {
2312 (void) fprintf(stderr,
2313 gettext("missing <device> specification\n"));
2314 usage(B_FALSE);
2315 }
2316
2317 old_disk = argv[1];
2318
2319 if (argc < 3) {
2320 if (!replacing) {
2321 (void) fprintf(stderr,
2322 gettext("missing <new_device> specification\n"));
2323 usage(B_FALSE);
2324 }
2325 new_disk = old_disk;
2326 argc -= 1;
2327 argv += 1;
2328 } else {
2329 new_disk = argv[2];
2330 argc -= 2;
2331 argv += 2;
2332 }
2333
2334 if (argc > 1) {
2335 (void) fprintf(stderr, gettext("too many arguments\n"));
2336 usage(B_FALSE);
2337 }
2338
2339 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2340 return (1);
2341
2342 if (zpool_get_config(zhp, NULL) == NULL) {
2343 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2344 poolname);
2345 zpool_close(zhp);
2346 return (1);
2347 }
2348
2349 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
2350 argc, argv);
2351 if (nvroot == NULL) {
2352 zpool_close(zhp);
2353 return (1);
2354 }
2355
2356 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2357
2358 nvlist_free(nvroot);
2359 zpool_close(zhp);
2360
2361 return (ret);
2362 }
2363
2364 /*
2365 * zpool replace [-f] <pool> <device> <new_device>
2366 *
2367 * -f Force attach, even if <new_device> appears to be in use.
2368 *
2369 * Replace <device> with <new_device>.
2370 */
2371 /* ARGSUSED */
2372 int
2373 zpool_do_replace(int argc, char **argv)
2374 {
2375 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2376 }
2377
2378 /*
2379 * zpool attach [-f] <pool> <device> <new_device>
2380 *
2381 * -f Force attach, even if <new_device> appears to be in use.
2382 *
2383 * Attach <new_device> to the mirror containing <device>. If <device> is not
2384 * part of a mirror, then <device> will be transformed into a mirror of
2385 * <device> and <new_device>. In either case, <new_device> will begin life
2386 * with a DTL of [0, now], and will immediately begin to resilver itself.
2387 */
2388 int
2389 zpool_do_attach(int argc, char **argv)
2390 {
2391 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2392 }
2393
2394 /*
2395 * zpool detach [-f] <pool> <device>
2396 *
2397 * -f Force detach of <device>, even if DTLs argue against it
2398 * (not supported yet)
2399 *
2400 * Detach a device from a mirror. The operation will be refused if <device>
2401 * is the last device in the mirror, or if the DTLs indicate that this device
2402 * has the only valid copy of some data.
2403 */
2404 /* ARGSUSED */
2405 int
2406 zpool_do_detach(int argc, char **argv)
2407 {
2408 int c;
2409 char *poolname, *path;
2410 zpool_handle_t *zhp;
2411 int ret;
2412
2413 /* check options */
2414 while ((c = getopt(argc, argv, "f")) != -1) {
2415 switch (c) {
2416 case 'f':
2417 case '?':
2418 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2419 optopt);
2420 usage(B_FALSE);
2421 }
2422 }
2423
2424 argc -= optind;
2425 argv += optind;
2426
2427 /* get pool name and check number of arguments */
2428 if (argc < 1) {
2429 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2430 usage(B_FALSE);
2431 }
2432
2433 if (argc < 2) {
2434 (void) fprintf(stderr,
2435 gettext("missing <device> specification\n"));
2436 usage(B_FALSE);
2437 }
2438
2439 poolname = argv[0];
2440 path = argv[1];
2441
2442 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2443 return (1);
2444
2445 ret = zpool_vdev_detach(zhp, path);
2446
2447 zpool_close(zhp);
2448
2449 return (ret);
2450 }
2451
2452 /*
2453 * zpool online <pool> <device> ...
2454 */
2455 int
2456 zpool_do_online(int argc, char **argv)
2457 {
2458 int c, i;
2459 char *poolname;
2460 zpool_handle_t *zhp;
2461 int ret = 0;
2462 vdev_state_t newstate;
2463
2464 /* check options */
2465 while ((c = getopt(argc, argv, "t")) != -1) {
2466 switch (c) {
2467 case 't':
2468 case '?':
2469 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2470 optopt);
2471 usage(B_FALSE);
2472 }
2473 }
2474
2475 argc -= optind;
2476 argv += optind;
2477
2478 /* get pool name and check number of arguments */
2479 if (argc < 1) {
2480 (void) fprintf(stderr, gettext("missing pool name\n"));
2481 usage(B_FALSE);
2482 }
2483 if (argc < 2) {
2484 (void) fprintf(stderr, gettext("missing device name\n"));
2485 usage(B_FALSE);
2486 }
2487
2488 poolname = argv[0];
2489
2490 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2491 return (1);
2492
2493 for (i = 1; i < argc; i++) {
2494 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2495 if (newstate != VDEV_STATE_HEALTHY) {
2496 (void) printf(gettext("warning: device '%s' "
2497 "onlined, but remains in faulted state\n"),
2498 argv[i]);
2499 if (newstate == VDEV_STATE_FAULTED)
2500 (void) printf(gettext("use 'zpool "
2501 "clear' to restore a faulted "
2502 "device\n"));
2503 else
2504 (void) printf(gettext("use 'zpool "
2505 "replace' to replace devices "
2506 "that are no longer present\n"));
2507 }
2508 } else {
2509 ret = 1;
2510 }
2511 }
2512
2513 zpool_close(zhp);
2514
2515 return (ret);
2516 }
2517
2518 /*
2519 * zpool offline [-ft] <pool> <device> ...
2520 *
2521 * -f Force the device into the offline state, even if doing
2522 * so would appear to compromise pool availability.
2523 * (not supported yet)
2524 *
2525 * -t Only take the device off-line temporarily. The offline
2526 * state will not be persistent across reboots.
2527 */
2528 /* ARGSUSED */
2529 int
2530 zpool_do_offline(int argc, char **argv)
2531 {
2532 int c, i;
2533 char *poolname;
2534 zpool_handle_t *zhp;
2535 int ret = 0;
2536 boolean_t istmp = B_FALSE;
2537
2538 /* check options */
2539 while ((c = getopt(argc, argv, "ft")) != -1) {
2540 switch (c) {
2541 case 't':
2542 istmp = B_TRUE;
2543 break;
2544 case 'f':
2545 case '?':
2546 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2547 optopt);
2548 usage(B_FALSE);
2549 }
2550 }
2551
2552 argc -= optind;
2553 argv += optind;
2554
2555 /* get pool name and check number of arguments */
2556 if (argc < 1) {
2557 (void) fprintf(stderr, gettext("missing pool name\n"));
2558 usage(B_FALSE);
2559 }
2560 if (argc < 2) {
2561 (void) fprintf(stderr, gettext("missing device name\n"));
2562 usage(B_FALSE);
2563 }
2564
2565 poolname = argv[0];
2566
2567 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2568 return (1);
2569
2570 for (i = 1; i < argc; i++) {
2571 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2572 ret = 1;
2573 }
2574
2575 zpool_close(zhp);
2576
2577 return (ret);
2578 }
2579
2580 /*
2581 * zpool clear <pool> [device]
2582 *
2583 * Clear all errors associated with a pool or a particular device.
2584 */
2585 int
2586 zpool_do_clear(int argc, char **argv)
2587 {
2588 int ret = 0;
2589 zpool_handle_t *zhp;
2590 char *pool, *device;
2591
2592 if (argc < 2) {
2593 (void) fprintf(stderr, gettext("missing pool name\n"));
2594 usage(B_FALSE);
2595 }
2596
2597 if (argc > 3) {
2598 (void) fprintf(stderr, gettext("too many arguments\n"));
2599 usage(B_FALSE);
2600 }
2601
2602 pool = argv[1];
2603 device = argc == 3 ? argv[2] : NULL;
2604
2605 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
2606 return (1);
2607
2608 if (zpool_clear(zhp, device) != 0)
2609 ret = 1;
2610
2611 zpool_close(zhp);
2612
2613 return (ret);
2614 }
2615
2616 typedef struct scrub_cbdata {
2617 int cb_type;
2618 int cb_argc;
2619 char **cb_argv;
2620 } scrub_cbdata_t;
2621
2622 int
2623 scrub_callback(zpool_handle_t *zhp, void *data)
2624 {
2625 scrub_cbdata_t *cb = data;
2626 int err;
2627
2628 /*
2629 * Ignore faulted pools.
2630 */
2631 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2632 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2633 "currently unavailable\n"), zpool_get_name(zhp));
2634 return (1);
2635 }
2636
2637 err = zpool_scrub(zhp, cb->cb_type);
2638
2639 return (err != 0);
2640 }
2641
2642 /*
2643 * zpool scrub [-s] <pool> ...
2644 *
2645 * -s Stop. Stops any in-progress scrub.
2646 */
2647 int
2648 zpool_do_scrub(int argc, char **argv)
2649 {
2650 int c;
2651 scrub_cbdata_t cb;
2652
2653 cb.cb_type = POOL_SCRUB_EVERYTHING;
2654
2655 /* check options */
2656 while ((c = getopt(argc, argv, "s")) != -1) {
2657 switch (c) {
2658 case 's':
2659 cb.cb_type = POOL_SCRUB_NONE;
2660 break;
2661 case '?':
2662 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2663 optopt);
2664 usage(B_FALSE);
2665 }
2666 }
2667
2668 cb.cb_argc = argc;
2669 cb.cb_argv = argv;
2670 argc -= optind;
2671 argv += optind;
2672
2673 if (argc < 1) {
2674 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2675 usage(B_FALSE);
2676 }
2677
2678 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2679 }
2680
2681 typedef struct status_cbdata {
2682 int cb_count;
2683 boolean_t cb_allpools;
2684 boolean_t cb_verbose;
2685 boolean_t cb_explain;
2686 boolean_t cb_first;
2687 } status_cbdata_t;
2688
2689 /*
2690 * Print out detailed scrub status.
2691 */
2692 void
2693 print_scrub_status(nvlist_t *nvroot)
2694 {
2695 vdev_stat_t *vs;
2696 uint_t vsc;
2697 time_t start, end, now;
2698 double fraction_done;
2699 uint64_t examined, total, minutes_left, minutes_taken;
2700 char *scrub_type;
2701
2702 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2703 (uint64_t **)&vs, &vsc) == 0);
2704
2705 /*
2706 * If there's never been a scrub, there's not much to say.
2707 */
2708 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2709 (void) printf(gettext("none requested\n"));
2710 return;
2711 }
2712
2713 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2714 "resilver" : "scrub";
2715
2716 start = vs->vs_scrub_start;
2717 end = vs->vs_scrub_end;
2718 now = time(NULL);
2719 examined = vs->vs_scrub_examined;
2720 total = vs->vs_alloc;
2721
2722 if (end != 0) {
2723 minutes_taken = (uint64_t)((end - start) / 60);
2724
2725 (void) printf(gettext("%s %s after %lluh%um with %llu errors "
2726 "on %s"),
2727 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2728 (u_longlong_t)(minutes_taken / 60),
2729 (uint_t)(minutes_taken % 60),
2730 (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2731 return;
2732 }
2733
2734 if (examined == 0)
2735 examined = 1;
2736 if (examined > total)
2737 total = examined;
2738
2739 fraction_done = (double)examined / total;
2740 minutes_left = (uint64_t)((now - start) *
2741 (1 - fraction_done) / fraction_done / 60);
2742 minutes_taken = (uint64_t)((now - start) / 60);
2743
2744 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
2745 "%lluh%um to go\n"),
2746 scrub_type, (u_longlong_t)(minutes_taken / 60),
2747 (uint_t)(minutes_taken % 60), 100 * fraction_done,
2748 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2749 }
2750
2751 typedef struct spare_cbdata {
2752 uint64_t cb_guid;
2753 zpool_handle_t *cb_zhp;
2754 } spare_cbdata_t;
2755
2756 static boolean_t
2757 find_vdev(nvlist_t *nv, uint64_t search)
2758 {
2759 uint64_t guid;
2760 nvlist_t **child;
2761 uint_t c, children;
2762
2763 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2764 search == guid)
2765 return (B_TRUE);
2766
2767 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2768 &child, &children) == 0) {
2769 for (c = 0; c < children; c++)
2770 if (find_vdev(child[c], search))
2771 return (B_TRUE);
2772 }
2773
2774 return (B_FALSE);
2775 }
2776
2777 static int
2778 find_spare(zpool_handle_t *zhp, void *data)
2779 {
2780 spare_cbdata_t *cbp = data;
2781 nvlist_t *config, *nvroot;
2782
2783 config = zpool_get_config(zhp, NULL);
2784 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2785 &nvroot) == 0);
2786
2787 if (find_vdev(nvroot, cbp->cb_guid)) {
2788 cbp->cb_zhp = zhp;
2789 return (1);
2790 }
2791
2792 zpool_close(zhp);
2793 return (0);
2794 }
2795
2796 /*
2797 * Print out configuration state as requested by status_callback.
2798 */
2799 void
2800 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2801 int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2802 {
2803 nvlist_t **child;
2804 uint_t c, children;
2805 vdev_stat_t *vs;
2806 char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2807 char *vname;
2808 uint64_t notpresent;
2809 spare_cbdata_t cb;
2810 char *state;
2811
2812 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2813 (uint64_t **)&vs, &c) == 0);
2814
2815 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2816 &child, &children) != 0)
2817 children = 0;
2818
2819 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2820 if (isspare) {
2821 /*
2822 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2823 * online drives.
2824 */
2825 if (vs->vs_aux == VDEV_AUX_SPARED)
2826 state = "INUSE";
2827 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2828 state = "AVAIL";
2829 }
2830
2831 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
2832 name, state);
2833
2834 if (!isspare) {
2835 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2836 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2837 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2838 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2839 }
2840
2841 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2842 ¬present) == 0) {
2843 char *path;
2844 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2845 (void) printf(" was %s", path);
2846 } else if (vs->vs_aux != 0) {
2847 (void) printf(" ");
2848
2849 switch (vs->vs_aux) {
2850 case VDEV_AUX_OPEN_FAILED:
2851 (void) printf(gettext("cannot open"));
2852 break;
2853
2854 case VDEV_AUX_BAD_GUID_SUM:
2855 (void) printf(gettext("missing device"));
2856 break;
2857
2858 case VDEV_AUX_NO_REPLICAS:
2859 (void) printf(gettext("insufficient replicas"));
2860 break;
2861
2862 case VDEV_AUX_VERSION_NEWER:
2863 (void) printf(gettext("newer version"));
2864 break;
2865
2866 case VDEV_AUX_SPARED:
2867 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2868 &cb.cb_guid) == 0);
2869 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2870 if (strcmp(zpool_get_name(cb.cb_zhp),
2871 zpool_get_name(zhp)) == 0)
2872 (void) printf(gettext("currently in "
2873 "use"));
2874 else
2875 (void) printf(gettext("in use by "
2876 "pool '%s'"),
2877 zpool_get_name(cb.cb_zhp));
2878 zpool_close(cb.cb_zhp);
2879 } else {
2880 (void) printf(gettext("currently in use"));
2881 }
2882 break;
2883
2884 case VDEV_AUX_ERR_EXCEEDED:
2885 (void) printf(gettext("too many errors"));
2886 break;
2887
2888 case VDEV_AUX_IO_FAILURE:
2889 (void) printf(gettext("experienced I/O failures"));
2890 break;
2891
2892 case VDEV_AUX_BAD_LOG:
2893 (void) printf(gettext("bad intent log"));
2894 break;
2895
2896 default:
2897 (void) printf(gettext("corrupted data"));
2898 break;
2899 }
2900 } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2901 /*
2902 * Report bytes resilvered/repaired on leaf devices.
2903 */
2904 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2905 (void) printf(gettext(" %s %s"), repaired,
2906 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2907 "resilvered" : "repaired");
2908 }
2909
2910 (void) printf("\n");
2911
2912 for (c = 0; c < children; c++) {
2913 uint64_t is_log = B_FALSE;
2914
2915 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2916 &is_log);
2917 if ((is_log && !print_logs) || (!is_log && print_logs))
2918 continue;
2919 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2920 print_status_config(zhp, vname, child[c],
2921 namewidth, depth + 2, isspare, B_FALSE);
2922 free(vname);
2923 }
2924 }
2925
2926 static void
2927 print_error_log(zpool_handle_t *zhp)
2928 {
2929 nvlist_t *nverrlist = NULL;
2930 nvpair_t *elem;
2931 char *pathname;
2932 size_t len = MAXPATHLEN * 2;
2933
2934 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2935 (void) printf("errors: List of errors unavailable "
2936 "(insufficient privileges)\n");
2937 return;
2938 }
2939
2940 (void) printf("errors: Permanent errors have been "
2941 "detected in the following files:\n\n");
2942
2943 pathname = safe_malloc(len);
2944 elem = NULL;
2945 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2946 nvlist_t *nv;
2947 uint64_t dsobj, obj;
2948
2949 verify(nvpair_value_nvlist(elem, &nv) == 0);
2950 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2951 &dsobj) == 0);
2952 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2953 &obj) == 0);
2954 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2955 (void) printf("%7s %s\n", "", pathname);
2956 }
2957 free(pathname);
2958 nvlist_free(nverrlist);
2959 }
2960
2961 static void
2962 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2963 int namewidth)
2964 {
2965 uint_t i;
2966 char *name;
2967
2968 if (nspares == 0)
2969 return;
2970
2971 (void) printf(gettext("\tspares\n"));
2972
2973 for (i = 0; i < nspares; i++) {
2974 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2975 print_status_config(zhp, name, spares[i],
2976 namewidth, 2, B_TRUE, B_FALSE);
2977 free(name);
2978 }
2979 }
2980
2981 static void
2982 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2983 int namewidth)
2984 {
2985 uint_t i;
2986 char *name;
2987
2988 if (nl2cache == 0)
2989 return;
2990
2991 (void) printf(gettext("\tcache\n"));
2992
2993 for (i = 0; i < nl2cache; i++) {
2994 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2995 print_status_config(zhp, name, l2cache[i],
2996 namewidth, 2, B_FALSE, B_FALSE);
2997 free(name);
2998 }
2999 }
3000
3001 /*
3002 * Display a summary of pool status. Displays a summary such as:
3003 *
3004 * pool: tank
3005 * status: DEGRADED
3006 * reason: One or more devices ...
3007 * see: http://www.sun.com/msg/ZFS-xxxx-01
3008 * config:
3009 * mirror DEGRADED
3010 * c1t0d0 OK
3011 * c2t0d0 UNAVAIL
3012 *
3013 * When given the '-v' option, we print out the complete config. If the '-e'
3014 * option is specified, then we print out error rate information as well.
3015 */
3016 int
3017 status_callback(zpool_handle_t *zhp, void *data)
3018 {
3019 status_cbdata_t *cbp = data;
3020 nvlist_t *config, *nvroot;
3021 char *msgid;
3022 int reason;
3023 const char *health;
3024 uint_t c;
3025 vdev_stat_t *vs;
3026 char keystatus[MAXNAMELEN];
3027 zprop_source_t srctype;
3028
3029 config = zpool_get_config(zhp, NULL);
3030 reason = zpool_get_status(zhp, &msgid);
3031
3032 cbp->cb_count++;
3033
3034 /*
3035 * If we were given 'zpool status -x', only report those pools with
3036 * problems.
3037 */
3038 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3039 if (!cbp->cb_allpools) {
3040 (void) printf(gettext("pool '%s' is healthy\n"),
3041 zpool_get_name(zhp));
3042 if (cbp->cb_first)
3043 cbp->cb_first = B_FALSE;
3044 }
3045 return (0);
3046 }
3047
3048 if (cbp->cb_first)
3049 cbp->cb_first = B_FALSE;
3050 else
3051 (void) printf("\n");
3052
3053 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3054 &nvroot) == 0);
3055 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3056 (uint64_t **)&vs, &c) == 0);
3057 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3058
3059 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
3060 (void) printf(gettext(" state: %s\n"), health);
3061
3062 (void) zpool_get_prop(zhp, ZPOOL_PROP_KEYSTATUS, keystatus,
3063 sizeof (keystatus), &srctype);
3064
3065 (void) printf(gettext(" key: %s\n"), keystatus);
3066
3067 switch (reason) {
3068 case ZPOOL_STATUS_MISSING_DEV_R:
3069 (void) printf(gettext("status: One or more devices could not "
3070 "be opened. Sufficient replicas exist for\n\tthe pool to "
3071 "continue functioning in a degraded state.\n"));
3072 (void) printf(gettext("action: Attach the missing device and "
3073 "online it using 'zpool online'.\n"));
3074 break;
3075
3076 case ZPOOL_STATUS_MISSING_DEV_NR:
3077 (void) printf(gettext("status: One or more devices could not "
3078 "be opened. There are insufficient\n\treplicas for the "
3079 "pool to continue functioning.\n"));
3080 (void) printf(gettext("action: Attach the missing device and "
3081 "online it using 'zpool online'.\n"));
3082 break;
3083
3084 case ZPOOL_STATUS_CORRUPT_LABEL_R:
3085 (void) printf(gettext("status: One or more devices could not "
3086 "be used because the label is missing or\n\tinvalid. "
3087 "Sufficient replicas exist for the pool to continue\n\t"
3088 "functioning in a degraded state.\n"));
3089 (void) printf(gettext("action: Replace the device using "
3090 "'zpool replace'.\n"));
3091 break;
3092
3093 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3094 (void) printf(gettext("status: One or more devices could not "
3095 "be used because the label is missing \n\tor invalid. "
3096 "There are insufficient replicas for the pool to "
3097 "continue\n\tfunctioning.\n"));
3098 (void) printf(gettext("action: Destroy and re-create the pool "
3099 "from a backup source.\n"));
3100 break;
3101
3102 case ZPOOL_STATUS_FAILING_DEV:
3103 (void) printf(gettext("status: One or more devices has "
3104 "experienced an unrecoverable error. An\n\tattempt was "
3105 "made to correct the error. Applications are "
3106 "unaffected.\n"));
3107 (void) printf(gettext("action: Determine if the device needs "
3108 "to be replaced, and clear the errors\n\tusing "
3109 "'zpool clear' or replace the device with 'zpool "
3110 "replace'.\n"));
3111 break;
3112
3113 case ZPOOL_STATUS_OFFLINE_DEV:
3114 (void) printf(gettext("status: One or more devices has "
3115 "been taken offline by the administrator.\n\tSufficient "
3116 "replicas exist for the pool to continue functioning in "
3117 "a\n\tdegraded state.\n"));
3118 (void) printf(gettext("action: Online the device using "
3119 "'zpool online' or replace the device with\n\t'zpool "
3120 "replace'.\n"));
3121 break;
3122
3123 case ZPOOL_STATUS_RESILVERING:
3124 (void) printf(gettext("status: One or more devices is "
3125 "currently being resilvered. The pool will\n\tcontinue "
3126 "to function, possibly in a degraded state.\n"));
3127 (void) printf(gettext("action: Wait for the resilver to "
3128 "complete.\n"));
3129 break;
3130
3131 case ZPOOL_STATUS_CORRUPT_DATA:
3132 (void) printf(gettext("status: One or more devices has "
3133 "experienced an error resulting in data\n\tcorruption. "
3134 "Applications may be affected.\n"));
3135 (void) printf(gettext("action: Restore the file in question "
3136 "if possible. Otherwise restore the\n\tentire pool from "
3137 "backup.\n"));
3138 break;
3139
3140 case ZPOOL_STATUS_CORRUPT_POOL:
3141 (void) printf(gettext("status: The pool metadata is corrupted "
3142 "and the pool cannot be opened.\n"));
3143 (void) printf(gettext("action: Destroy and re-create the pool "
3144 "from a backup source.\n"));
3145 break;
3146
3147 case ZPOOL_STATUS_VERSION_OLDER:
3148 (void) printf(gettext("status: The pool is formatted using an "
3149 "older on-disk format. The pool can\n\tstill be used, but "
3150 "some features are unavailable.\n"));
3151 (void) printf(gettext("action: Upgrade the pool using 'zpool "
3152 "upgrade'. Once this is done, the\n\tpool will no longer "
3153 "be accessible on older software versions.\n"));
3154 break;
3155
3156 case ZPOOL_STATUS_VERSION_NEWER:
3157 (void) printf(gettext("status: The pool has been upgraded to a "
3158 "newer, incompatible on-disk version.\n\tThe pool cannot "
3159 "be accessed on this system.\n"));
3160 (void) printf(gettext("action: Access the pool from a system "
3161 "running more recent software, or\n\trestore the pool from "
3162 "backup.\n"));
3163 break;
3164
3165 case ZPOOL_STATUS_FAULTED_DEV_R:
3166 (void) printf(gettext("status: One or more devices are "
3167 "faulted in response to persistent errors.\n\tSufficient "
3168 "replicas exist for the pool to continue functioning "
3169 "in a\n\tdegraded state.\n"));
3170 (void) printf(gettext("action: Replace the faulted device, "
3171 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3172 break;
3173
3174 case ZPOOL_STATUS_FAULTED_DEV_NR:
3175 (void) printf(gettext("status: One or more devices are "
3176 "faulted in response to persistent errors. There are "
3177 "insufficient replicas for the pool to\n\tcontinue "
3178 "functioning.\n"));
3179 (void) printf(gettext("action: Destroy and re-create the pool "
3180 "from a backup source. Manually marking the device\n"
3181 "\trepaired using 'zpool clear' may allow some data "
3182 "to be recovered.\n"));
3183 break;
3184
3185 case ZPOOL_STATUS_IO_FAILURE_WAIT:
3186 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
3187 (void) printf(gettext("status: One or more devices are "
3188 "faulted in response to IO failures.\n"));
3189 (void) printf(gettext("action: Make sure the affected devices "
3190 "are connected, then run 'zpool clear'.\n"));
3191 break;
3192
3193 case ZPOOL_STATUS_BAD_LOG:
3194 (void) printf(gettext("status: An intent log record "
3195 "could not be read.\n"
3196 "\tWaiting for adminstrator intervention to fix the "
3197 "faulted pool.\n"));
3198 (void) printf(gettext("action: Either restore the affected "
3199 "device(s) and run 'zpool online',\n"
3200 "\tor ignore the intent log records by running "
3201 "'zpool clear'.\n"));
3202 break;
3203
3204 default:
3205 /*
3206 * The remaining errors can't actually be generated, yet.
3207 */
3208 assert(reason == ZPOOL_STATUS_OK);
3209 }
3210
3211 if (msgid != NULL)
3212 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
3213 msgid);
3214
3215 if (config != NULL) {
3216 int namewidth;
3217 uint64_t nerr;
3218 nvlist_t **spares, **l2cache;
3219 uint_t nspares, nl2cache;
3220
3221
3222 (void) printf(gettext(" scrub: "));
3223 print_scrub_status(nvroot);
3224
3225 namewidth = max_width(zhp, nvroot, 0, 0);
3226 if (namewidth < 10)
3227 namewidth = 10;
3228
3229 (void) printf(gettext("config:\n\n"));
3230 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
3231 "NAME", "STATE", "READ", "WRITE", "CKSUM");
3232 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3233 namewidth, 0, B_FALSE, B_FALSE);
3234 if (num_logs(nvroot) > 0)
3235 print_status_config(zhp, "logs", nvroot, namewidth, 0,
3236 B_FALSE, B_TRUE);
3237
3238 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3239 &l2cache, &nl2cache) == 0)
3240 print_l2cache(zhp, l2cache, nl2cache, namewidth);
3241
3242 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3243 &spares, &nspares) == 0)
3244 print_spares(zhp, spares, nspares, namewidth);
3245
3246 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3247 &nerr) == 0) {
3248 nvlist_t *nverrlist = NULL;
3249
3250 /*
3251 * If the approximate error count is small, get a
3252 * precise count by fetching the entire log and
3253 * uniquifying the results.
3254 */
3255 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
3256 zpool_get_errlog(zhp, &nverrlist) == 0) {
3257 nvpair_t *elem;
3258
3259 elem = NULL;
3260 nerr = 0;
3261 while ((elem = nvlist_next_nvpair(nverrlist,
3262 elem)) != NULL) {
3263 nerr++;
3264 }
3265 }
3266 nvlist_free(nverrlist);
3267
3268 (void) printf("\n");
3269
3270 if (nerr == 0)
3271 (void) printf(gettext("errors: No known data "
3272 "errors\n"));
3273 else if (!cbp->cb_verbose)
3274 (void) printf(gettext("errors: %llu data "
3275 "errors, use '-v' for a list\n"),
3276 (u_longlong_t)nerr);
3277 else
3278 print_error_log(zhp);
3279 }
3280 } else {
3281 (void) printf(gettext("config: The configuration cannot be "
3282 "determined.\n"));
3283 }
3284
3285 return (0);
3286 }
3287
3288 /*
3289 * zpool status [-vx] [pool] ...
3290 *
3291 * -v Display complete error logs
3292 * -x Display only pools with potential problems
3293 *
3294 * Describes the health status of all pools or some subset.
3295 */
3296 int
3297 zpool_do_status(int argc, char **argv)
3298 {
3299 int c;
3300 int ret;
3301 status_cbdata_t cb = { 0 };
3302
3303 /* check options */
3304 while ((c = getopt(argc, argv, "vx")) != -1) {
3305 switch (c) {
3306 case 'v':
3307 cb.cb_verbose = B_TRUE;
3308 break;
3309 case 'x':
3310 cb.cb_explain = B_TRUE;
3311 break;
3312 case '?':
3313 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3314 optopt);
3315 usage(B_FALSE);
3316 }
3317 }
3318
3319 argc -= optind;
3320 argv += optind;
3321
3322 cb.cb_first = B_TRUE;
3323
3324 if (argc == 0)
3325 cb.cb_allpools = B_TRUE;
3326
3327 ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3328
3329 if (argc == 0 && cb.cb_count == 0)
3330 (void) printf(gettext("no pools available\n"));
3331 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3332 (void) printf(gettext("all pools are healthy\n"));
3333
3334 return (ret);
3335 }
3336
3337 typedef struct upgrade_cbdata {
3338 int cb_all;
3339 int cb_first;
3340 int cb_newer;
3341 int cb_argc;
3342 uint64_t cb_version;
3343 char **cb_argv;
3344 } upgrade_cbdata_t;
3345
3346 static int
3347 upgrade_cb(zpool_handle_t *zhp, void *arg)
3348 {
3349 upgrade_cbdata_t *cbp = arg;
3350 nvlist_t *config;
3351 uint64_t version;
3352 int ret = 0;
3353
3354 config = zpool_get_config(zhp, NULL);
3355 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3356 &version) == 0);
3357
3358 if (!cbp->cb_newer && version < SPA_VERSION) {
3359 if (!cbp->cb_all) {
3360 if (cbp->cb_first) {
3361 (void) printf(gettext("The following pools are "
3362 "out of date, and can be upgraded. After "
3363 "being\nupgraded, these pools will no "
3364 "longer be accessible by older software "
3365 "versions.\n\n"));
3366 (void) printf(gettext("VER POOL\n"));
3367 (void) printf(gettext("--- ------------\n"));
3368 cbp->cb_first = B_FALSE;
3369 }
3370
3371 (void) printf("%2llu %s\n", (u_longlong_t)version,
3372 zpool_get_name(zhp));
3373 } else {
3374 cbp->cb_first = B_FALSE;
3375 ret = zpool_upgrade(zhp, cbp->cb_version);
3376 if (!ret) {
3377 (void) printf(gettext("Successfully upgraded "
3378 "'%s'\n\n"), zpool_get_name(zhp));
3379 }
3380 }
3381 } else if (cbp->cb_newer && version > SPA_VERSION) {
3382 assert(!cbp->cb_all);
3383
3384 if (cbp->cb_first) {
3385 (void) printf(gettext("The following pools are "
3386 "formatted using a newer software version and\n"
3387 "cannot be accessed on the current system.\n\n"));
3388 (void) printf(gettext("VER POOL\n"));
3389 (void) printf(gettext("--- ------------\n"));
3390 cbp->cb_first = B_FALSE;
3391 }
3392
3393 (void) printf("%2llu %s\n", (u_longlong_t)version,
3394 zpool_get_name(zhp));
3395 }
3396
3397 zpool_close(zhp);
3398 return (ret);
3399 }
3400
3401 /* ARGSUSED */
3402 static int
3403 upgrade_one(zpool_handle_t *zhp, void *data)
3404 {
3405 upgrade_cbdata_t *cbp = data;
3406 uint64_t cur_version;
3407 int ret;
3408
3409 if (strcmp("log", zpool_get_name(zhp)) == 0) {
3410 (void) printf(gettext("'log' is now a reserved word\n"
3411 "Pool 'log' must be renamed using export and import"
3412 " to upgrade.\n"));
3413 return (1);
3414 }
3415
3416 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3417 if (cur_version > cbp->cb_version) {
3418 (void) printf(gettext("Pool '%s' is already formatted "
3419 "using more current version '%llu'.\n"),
3420 zpool_get_name(zhp), cur_version);
3421 return (0);
3422 }
3423 if (cur_version == cbp->cb_version) {
3424 (void) printf(gettext("Pool '%s' is already formatted "
3425 "using the current version.\n"), zpool_get_name(zhp));
3426 return (0);
3427 }
3428
3429 ret = zpool_upgrade(zhp, cbp->cb_version);
3430
3431 if (!ret) {
3432 (void) printf(gettext("Successfully upgraded '%s' "
3433 "from version %llu to version %llu\n\n"),
3434 zpool_get_name(zhp), (u_longlong_t)cur_version,
3435 (u_longlong_t)cbp->cb_version);
3436 }
3437
3438 return (ret != 0);
3439 }
3440
3441 /*
3442 * zpool upgrade
3443 * zpool upgrade -v
3444 * zpool upgrade [-V version] <-a | pool ...>
3445 *
3446 * With no arguments, display downrev'd ZFS pool available for upgrade.
3447 * Individual pools can be upgraded by specifying the pool, and '-a' will
3448 * upgrade all pools.
3449 */
3450 int
3451 zpool_do_upgrade(int argc, char **argv)
3452 {
3453 int c;
3454 upgrade_cbdata_t cb = { 0 };
3455 int ret = 0;
3456 boolean_t showversions = B_FALSE;
3457 char *end;
3458
3459
3460 /* check options */
3461 while ((c = getopt(argc, argv, "avV:")) != -1) {
3462 switch (c) {
3463 case 'a':
3464 cb.cb_all = B_TRUE;
3465 break;
3466 case 'v':
3467 showversions = B_TRUE;
3468 break;
3469 case 'V':
3470 cb.cb_version = strtoll(optarg, &end, 10);
3471 if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3472 cb.cb_version < SPA_VERSION_1) {
3473 (void) fprintf(stderr,
3474 gettext("invalid version '%s'\n"), optarg);
3475 usage(B_FALSE);
3476 }
3477 break;
3478 case '?':
3479 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3480 optopt);
3481 usage(B_FALSE);
3482 }
3483 }
3484
3485 cb.cb_argc = argc;
3486 cb.cb_argv = argv;
3487 argc -= optind;
3488 argv += optind;
3489
3490 if (cb.cb_version == 0) {
3491 cb.cb_version = SPA_VERSION;
3492 } else if (!cb.cb_all && argc == 0) {
3493 (void) fprintf(stderr, gettext("-V option is "
3494 "incompatible with other arguments\n"));
3495 usage(B_FALSE);
3496 }
3497
3498 if (showversions) {
3499 if (cb.cb_all || argc != 0) {
3500 (void) fprintf(stderr, gettext("-v option is "
3501 "incompatible with other arguments\n"));
3502 usage(B_FALSE);
3503 }
3504 } else if (cb.cb_all) {
3505 if (argc != 0) {
3506 (void) fprintf(stderr, gettext("-a option should not "
3507 "be used along with a pool name\n"));
3508 usage(B_FALSE);
3509 }
3510 }
3511
3512 (void) printf(gettext("This system is currently running "
3513 "ZFS pool version %llu.\n\n"), SPA_VERSION);
3514 cb.cb_first = B_TRUE;
3515 if (showversions) {
3516 (void) printf(gettext("The following versions are "
3517 "supported:\n\n"));
3518 (void) printf(gettext("VER DESCRIPTION\n"));
3519 (void) printf("--- -----------------------------------------"
3520 "---------------\n");
3521 (void) printf(gettext(" 1 Initial ZFS version\n"));
3522 (void) printf(gettext(" 2 Ditto blocks "
3523 "(replicated metadata)\n"));
3524 (void) printf(gettext(" 3 Hot spares and double parity "
3525 "RAID-Z\n"));
3526 (void) printf(gettext(" 4 zpool history\n"));
3527 (void) printf(gettext(" 5 Compression using the gzip "
3528 "algorithm\n"));
3529 (void) printf(gettext(" 6 bootfs pool property\n"));
3530 (void) printf(gettext(" 7 Separate intent log devices\n"));
3531 (void) printf(gettext(" 8 Delegated administration\n"));
3532 (void) printf(gettext(" 9 refquota and refreservation "
3533 "properties\n"));
3534 (void) printf(gettext(" 10 Cache devices\n"));
3535 (void) printf(gettext(" 11 Improved scrub performance\n"));
3536 (void) printf(gettext(" 12 Snapshot properties\n"));
3537 (void) printf(gettext(" 13 snapused property\n"));
3538 (void) printf(gettext(" 14 passthrough-x aclinherit "
3539 "support\n"));
3540 (void) printf(gettext(" 15 Cryptographic support.\n"));
3541 (void) printf(gettext("For more information on a particular "
3542 "version, including supported releases, see:\n\n"));
3543 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3544 "version/N\n\n");
3545 (void) printf(gettext("Where 'N' is the version number.\n"));
3546 } else if (argc == 0) {
3547 int notfound;
3548
3549 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3550 notfound = cb.cb_first;
3551
3552 if (!cb.cb_all && ret == 0) {
3553 if (!cb.cb_first)
3554 (void) printf("\n");
3555 cb.cb_first = B_TRUE;
3556 cb.cb_newer = B_TRUE;
3557 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3558 if (!cb.cb_first) {
3559 notfound = B_FALSE;
3560 (void) printf("\n");
3561 }
3562 }
3563
3564 if (ret == 0) {
3565 if (notfound)
3566 (void) printf(gettext("All pools are formatted "
3567 "using this version.\n"));
3568 else if (!cb.cb_all)
3569 (void) printf(gettext("Use 'zpool upgrade -v' "
3570 "for a list of available versions and "
3571 "their associated\nfeatures.\n"));
3572 }
3573 } else {
3574 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3575 upgrade_one, &cb);
3576 }
3577
3578 return (ret);
3579 }
3580
3581 typedef struct hist_cbdata {
3582 boolean_t first;
3583 int longfmt;
3584 int internal;
3585 } hist_cbdata_t;
3586
3587 char *hist_event_table[LOG_END] = {
3588 "invalid event",
3589 "pool create",
3590 "vdev add",
3591 "pool remove",
3592 "pool destroy",
3593 "pool export",
3594 "pool import",
3595 "vdev attach",
3596 "vdev replace",
3597 "vdev detach",
3598 "vdev online",
3599 "vdev offline",
3600 "vdev upgrade",
3601 "pool clear",
3602 "pool scrub",
3603 "pool property set",
3604 "create",
3605 "clone",
3606 "destroy",
3607 "destroy_begin_sync",
3608 "inherit",
3609 "property set",
3610 "quota set",
3611 "permission update",
3612 "permission remove",
3613 "permission who remove",
3614 "promote",
3615 "receive",
3616 "rename",
3617 "reservation set",
3618 "replay_inc_sync",
3619 "replay_full_sync",
3620 "rollback",
3621 "snapshot",
3622 "filesystem version upgrade",
3623 "refquota set",
3624 "refreservation set",
3625 "pool scrub done",
3626 "crypto key create",
3627 };
3628
3629 /*
3630 * Print out the command history for a specific pool.
3631 */
3632 static int
3633 get_history_one(zpool_handle_t *zhp, void *data)
3634 {
3635 nvlist_t *nvhis;
3636 nvlist_t **records;
3637 uint_t numrecords;
3638 char *cmdstr;
3639 char *pathstr;
3640 uint64_t dst_time;
3641 time_t tsec;
3642 struct tm t;
3643 char tbuf[30];
3644 int ret, i;
3645 uint64_t who;
3646 struct passwd *pwd;
3647 char *hostname;
3648 char *zonename;
3649 char internalstr[MAXPATHLEN];
3650 hist_cbdata_t *cb = (hist_cbdata_t *)data;
3651 uint64_t txg;
3652 uint64_t ievent;
3653
3654 cb->first = B_FALSE;
3655
3656 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3657
3658 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3659 return (ret);
3660
3661 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3662 &records, &numrecords) == 0);
3663 for (i = 0; i < numrecords; i++) {
3664 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3665 &dst_time) != 0)
3666 continue;
3667
3668 /* is it an internal event or a standard event? */
3669 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3670 &cmdstr) != 0) {
3671 if (cb->internal == 0)
3672 continue;
3673
3674 if (nvlist_lookup_uint64(records[i],
3675 ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3676 continue;
3677 verify(nvlist_lookup_uint64(records[i],
3678 ZPOOL_HIST_TXG, &txg) == 0);
3679 verify(nvlist_lookup_string(records[i],
3680 ZPOOL_HIST_INT_STR, &pathstr) == 0);
3681 if (ievent >= LOG_END)
3682 continue;
3683 (void) snprintf(internalstr,
3684 sizeof (internalstr),
3685 "[internal %s txg:%lld] %s",
3686 hist_event_table[ievent], txg,
3687 pathstr);
3688 cmdstr = internalstr;
3689 }
3690 tsec = dst_time;
3691 (void) localtime_r(&tsec, &t);
3692 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3693 (void) printf("%s %s", tbuf, cmdstr);
3694
3695 if (!cb->longfmt) {
3696 (void) printf("\n");
3697 continue;
3698 }
3699 (void) printf(" [");
3700 if (nvlist_lookup_uint64(records[i],
3701 ZPOOL_HIST_WHO, &who) == 0) {
3702 pwd = getpwuid((uid_t)who);
3703 if (pwd)
3704 (void) printf("user %s on",
3705 pwd->pw_name);
3706 else
3707 (void) printf("user %d on",
3708 (int)who);
3709 } else {
3710 (void) printf(gettext("no info]\n"));
3711 continue;
3712 }
3713 if (nvlist_lookup_string(records[i],
3714 ZPOOL_HIST_HOST, &hostname) == 0) {
3715 (void) printf(" %s", hostname);
3716 }
3717 if (nvlist_lookup_string(records[i],
3718 ZPOOL_HIST_ZONE, &zonename) == 0) {
3719 (void) printf(":%s", zonename);
3720 }
3721
3722 (void) printf("]");
3723 (void) printf("\n");
3724 }
3725 (void) printf("\n");
3726 nvlist_free(nvhis);
3727
3728 return (ret);
3729 }
3730
3731 /*
3732 * zpool history <pool>
3733 *
3734 * Displays the history of commands that modified pools.
3735 */
3736
3737
3738 int
3739 zpool_do_history(int argc, char **argv)
3740 {
3741 hist_cbdata_t cbdata = { 0 };
3742 int ret;
3743 int c;
3744
3745 cbdata.first = B_TRUE;
3746 /* check options */
3747 while ((c = getopt(argc, argv, "li")) != -1) {
3748 switch (c) {
3749 case 'l':
3750 cbdata.longfmt = 1;
3751 break;
3752 case 'i':
3753 cbdata.internal = 1;
3754 break;
3755 case '?':
3756 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3757 optopt);
3758 usage(B_FALSE);
3759 }
3760 }
3761 argc -= optind;
3762 argv += optind;
3763
3764 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
3765 &cbdata);
3766
3767 if (argc == 0 && cbdata.first == B_TRUE) {
3768 (void) printf(gettext("no pools available\n"));
3769 return (0);
3770 }
3771
3772 return (ret);
3773 }
3774
3775 static int
3776 get_callback(zpool_handle_t *zhp, void *data)
3777 {
3778 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3779 char value[MAXNAMELEN];
3780 zprop_source_t srctype;
3781 zprop_list_t *pl;
3782
3783 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3784
3785 /*
3786 * Skip the special fake placeholder. This will also skip
3787 * over the name property when 'all' is specified.
3788 */
3789 if (pl->pl_prop == ZPOOL_PROP_NAME &&
3790 pl == cbp->cb_proplist)
3791 continue;
3792
3793 if (zpool_get_prop(zhp, pl->pl_prop,
3794 value, sizeof (value), &srctype) != 0)
3795 continue;
3796
3797 zprop_print_one_property(zpool_get_name(zhp), cbp,
3798 zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3799 }
3800 return (0);
3801 }
3802
3803 int
3804 zpool_do_get(int argc, char **argv)
3805 {
3806 zprop_get_cbdata_t cb = { 0 };
3807 zprop_list_t fake_name = { 0 };
3808 int ret;
3809
3810 if (argc < 3)
3811 usage(B_FALSE);
3812
3813 cb.cb_first = B_TRUE;
3814 cb.cb_sources = ZPROP_SRC_ALL;
3815 cb.cb_columns[0] = GET_COL_NAME;
3816 cb.cb_columns[1] = GET_COL_PROPERTY;
3817 cb.cb_columns[2] = GET_COL_VALUE;
3818 cb.cb_columns[3] = GET_COL_SOURCE;
3819 cb.cb_type = ZFS_TYPE_POOL;
3820
3821 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
3822 ZFS_TYPE_POOL) != 0)
3823 usage(B_FALSE);
3824
3825 if (cb.cb_proplist != NULL) {
3826 fake_name.pl_prop = ZPOOL_PROP_NAME;
3827 fake_name.pl_width = strlen(gettext("NAME"));
3828 fake_name.pl_next = cb.cb_proplist;
3829 cb.cb_proplist = &fake_name;
3830 }
3831
3832 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3833 get_callback, &cb);
3834
3835 if (cb.cb_proplist == &fake_name)
3836 zprop_free_list(fake_name.pl_next);
3837 else
3838 zprop_free_list(cb.cb_proplist);
3839
3840 return (ret);
3841 }
3842
3843 typedef struct set_cbdata {
3844 char *cb_propname;
3845 char *cb_value;
3846 boolean_t cb_any_successful;
3847 } set_cbdata_t;
3848
3849 int
3850 set_callback(zpool_handle_t *zhp, void *data)
3851 {
3852 int error;
3853 set_cbdata_t *cb = (set_cbdata_t *)data;
3854
3855 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3856 if (!error)
3857 cb->cb_any_successful = B_TRUE;
3858
3859 return (error);
3860 }
3861
3862 int
3863 zpool_do_set(int argc, char **argv)
3864 {
3865 set_cbdata_t cb = { 0 };
3866 int error;
3867
3868 if (argc > 1 && argv[1][0] == '-') {
3869 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3870 argv[1][1]);
3871 usage(B_FALSE);
3872 }
3873
3874 if (argc < 2) {
3875 (void) fprintf(stderr, gettext("missing property=value "
3876 "argument\n"));
3877 usage(B_FALSE);
3878 }
3879
3880 if (argc < 3) {
3881 (void) fprintf(stderr, gettext("missing pool name\n"));
3882 usage(B_FALSE);
3883 }
3884
3885 if (argc > 3) {
3886 (void) fprintf(stderr, gettext("too many pool names\n"));
3887 usage(B_FALSE);
3888 }
3889
3890 cb.cb_propname = argv[1];
3891 cb.cb_value = strchr(cb.cb_propname, '=');
3892 if (cb.cb_value == NULL) {
3893 (void) fprintf(stderr, gettext("missing value in "
3894 "property=value argument\n"));
3895 usage(B_FALSE);
3896 }
3897
3898 *(cb.cb_value) = '\0';
3899 cb.cb_value++;
3900
3901 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3902 set_callback, &cb);
3903
3904 return (error);
3905 }
3906
3907
3908 static int
3909 /* LINTED E_FUNC_ARG_UNUSED */
3910 key_callback_load(zpool_handle_t *zhp, void *data)
3911 {
3912 int ret;
3913 if (zpool_keysource_prompt(zhp)) {
3914 char *smf_fmri = getenv("SMF_FMRI");
3915
3916 if (smf_fmri != NULL &&
3917 strcmp(smf_fmri, "svc:/system/device/local") == 0) {
3918 return (0);
3919 }
3920 }
3921 ret = zpool_cmd_key_load(zhp);
3922 if (ret != 0 && !(ret == EEXIST || ret == ENOTSUP)) {
3923 return (1);
3924 }
3925
3926 return (0);
3927 }
3928
3929 static int
3930 /* LINTED E_FUNC_ARG_UNUSED */
3931 key_callback_unload(zpool_handle_t *zhp, void *data)
3932 {
3933 int ret;
3934
3935 ret = zpool_cmd_key_unload(zhp);
3936 if (ret != 0 && !(ret == ENOENT || ret == ENOTSUP)) {
3937 return (1);
3938 }
3939
3940 return (0);
3941 }
3942
3943
3944 static int
3945 zpool_do_key(int argc, char **argv)
3946 {
3947 int error = 1, options = 0;
3948 nvlist_t *props = NULL;
3949 char c, *propval = NULL;
3950 boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
3951 boolean_t do_all = B_FALSE;
3952 zpool_handle_t *zhp = NULL;
3953
3954 while ((c = getopt(argc, argv, "aluco:")) != -1) {
3955 switch (c) {
3956 case 'a':
3957 do_all = B_TRUE;
3958 break;
3959
3960 case 'l':
3961 load = B_TRUE;
3962 break;
3963
3964 case 'u':
3965 unload = B_TRUE;
3966 break;
3967
3968 case 'c':
3969 change = B_TRUE;
3970 break;
3971
3972 case 'o':
3973 if ((propval = strchr(optarg, '=')) == NULL) {
3974 (void) fprintf(stderr, gettext("missing "
3975 "'=' for -o option\n"));
3976 return (error);
3977 }
3978
3979 *propval = '\0';
3980 propval++;
3981 if (strcmp(optarg, "keysource") != 0) {
3982 (void) fprintf(stderr, gettext(
3983 "Invalid property for key change: "
3984 "\"%s\"\n"),
3985 optarg);
3986 return (error);
3987 }
3988 if (add_prop_list(optarg, propval, &props, B_TRUE))
3989 return (error);
3990
3991 options += 2;
3992 break;
3993
3994 }
3995 }
3996
3997 if (!change && props != NULL) {
3998 (void) fprintf(stderr, gettext("Properties are not allowed to "
3999 "be used in this command.\n"));
4000 goto error;
4001 }
4002
4003 if (((load || unload) && (argc > 3)) ||
4004 (change && ((argc - options) > 3))) {
4005 (void) fprintf(stderr,
4006 gettext("too many arguments\n"));
4007 usage(B_FALSE);
4008 goto error;
4009 } else if ((load || unload) && (argc < 3)) {
4010 (void) fprintf(stderr, gettext("missing dataset "
4011 "argument (specify -a for all)\n"));
4012 usage(B_FALSE);
4013 goto error;
4014 } else if (change && ((argc - options) < 3)) {
4015 (void) fprintf(stderr, gettext("missing dataset "
4016 "argument\n"));
4017 usage(B_FALSE);
4018 goto error;
4019 }
4020
4021 if (do_all == B_FALSE) {
4022 zhp = zpool_open(g_zfs, argv[argc - 1]);
4023 if (zhp == NULL)
4024 goto error;
4025 }
4026
4027 if (load) {
4028 if (do_all)
4029 error = for_each_pool(0, NULL, B_TRUE, NULL,
4030 key_callback_load, NULL);
4031 else
4032 error = zpool_cmd_key_load(zhp);
4033
4034 } else if (unload) {
4035 if (do_all)
4036 error = for_each_pool(0, NULL, B_TRUE, NULL,
4037 key_callback_unload, NULL);
4038 else
4039 error = zpool_cmd_key_unload(zhp);
4040
4041 } else if (change) {
4042 if (do_all) {
4043 (void) fprintf(stderr, gettext("cannot use '-a' with "
4044 "change operation.\n"));
4045 usage(B_FALSE);
4046 goto error;
4047 }
4048
4049 error = zpool_cmd_key_change(zhp, props);
4050
4051 } else
4052 usage(B_FALSE);
4053
4054 if (zhp != NULL && !do_all)
4055 zpool_close(zhp);
4056
4057 error:
4058 nvlist_free(props);
4059 if (error != 0)
4060 return (1);
4061 return (0);
4062 }
4063
4064 static int
4065 find_command_idx(char *command, int *idx)
4066 {
4067 int i;
4068
4069 for (i = 0; i < NCOMMAND; i++) {
4070 if (command_table[i].name == NULL)
4071 continue;
4072
4073 if (strcmp(command, command_table[i].name) == 0) {
4074 *idx = i;
4075 return (0);
4076 }
4077 }
4078 return (1);
4079 }
4080
4081 int
4082 main(int argc, char **argv)
4083 {
4084 int ret;
4085 int i;
4086 char *cmdname;
4087
4088 (void) setlocale(LC_ALL, "");
4089 (void) textdomain(TEXT_DOMAIN);
4090
4091 if ((g_zfs = libzfs_init()) == NULL) {
4092 (void) fprintf(stderr, gettext("internal error: failed to "
4093 "initialize ZFS library\n"));
4094 return (1);
4095 }
4096
4097 libzfs_print_on_error(g_zfs, B_TRUE);
4098
4099 opterr = 0;
4100
4101 /*
4102 * Make sure the user has specified some command.
4103 */
4104 if (argc < 2) {
4105 (void) fprintf(stderr, gettext("missing command\n"));
4106 usage(B_FALSE);
4107 }
4108
4109 cmdname = argv[1];
4110
4111 /*
4112 * Special case '-?'
4113 */
4114 if (strcmp(cmdname, "-?") == 0)
4115 usage(B_TRUE);
4116
4117 zpool_set_history_str("zpool", argc, argv, history_str);
4118 verify(zpool_stage_history(g_zfs, history_str) == 0);
4119
4120 /*
4121 * Run the appropriate command.
4122 */
4123 if (find_command_idx(cmdname, &i) == 0) {
4124 current_command = &command_table[i];
4125 ret = command_table[i].func(argc - 1, argv + 1);
4126 } else if (strchr(cmdname, '=')) {
4127 verify(find_command_idx("set", &i) == 0);
4128 current_command = &command_table[i];
4129 ret = command_table[i].func(argc, argv);
4130 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
4131 /*
4132 * 'freeze' is a vile debugging abomination, so we treat
4133 * it as such.
4134 */
4135 char buf[16384];
4136 int fd = open(ZFS_DEV, O_RDWR);
4137 (void) strcpy((void *)buf, argv[2]);
4138 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
4139 } else {
4140 (void) fprintf(stderr, gettext("unrecognized "
4141 "command '%s'\n"), cmdname);
4142 usage(B_FALSE);
4143 }
4144
4145 libzfs_fini(g_zfs);
4146
4147 /*
4148 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
4149 * for the purposes of running ::findleaks.
4150 */
4151 if (getenv("ZFS_ABORT") != NULL) {
4152 (void) printf("dumping core by request\n");
4153 abort();
4154 }
4155
4156 return (ret);
4157 }