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