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