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