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