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