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 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <assert.h>
     30 #include <ctype.h>
     31 #include <dirent.h>
     32 #include <errno.h>
     33 #include <fcntl.h>
     34 #include <libgen.h>
     35 #include <libintl.h>
     36 #include <libuutil.h>
     37 #include <locale.h>
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <strings.h>
     42 #include <unistd.h>
     43 #include <priv.h>
     44 #include <pwd.h>
     45 #include <zone.h>
     46 #include <sys/fs/zfs.h>
     47 
     48 #include <sys/stat.h>
     49 
     50 #include <libzfs.h>
     51 
     52 #include "zpool_util.h"
     53 #include "zfs_comutil.h"
     54 
     55 static int zpool_do_create(int, char **);
     56 static int zpool_do_destroy(int, char **);
     57 
     58 static int zpool_do_add(int, char **);
     59 static int zpool_do_remove(int, char **);
     60 
     61 static int zpool_do_list(int, char **);
     62 static int zpool_do_iostat(int, char **);
     63 static int zpool_do_status(int, char **);
     64 
     65 static int zpool_do_online(int, char **);
     66 static int zpool_do_offline(int, char **);
     67 static int zpool_do_clear(int, char **);
     68 
     69 static int zpool_do_attach(int, char **);
     70 static int zpool_do_detach(int, char **);
     71 static int zpool_do_replace(int, char **);
     72 
     73 static int zpool_do_scrub(int, char **);
     74 
     75 static int zpool_do_import(int, char **);
     76 static int zpool_do_export(int, char **);
     77 
     78 static int zpool_do_upgrade(int, char **);
     79 
     80 static int zpool_do_history(int, char **);
     81 
     82 static int zpool_do_get(int, char **);
     83 static int zpool_do_set(int, char **);
     84 
     85 /*
     86  * These libumem hooks provide a reasonable set of defaults for the allocator's
     87  * debugging facilities.
     88  */
     89 
     90 #ifdef DEBUG
     91 const char *
     92 _umem_debug_init(void)
     93 {
     94 	return ("default,verbose"); /* $UMEM_DEBUG setting */
     95 }
     96 
     97 const char *
     98 _umem_logging_init(void)
     99 {
    100 	return ("fail,contents"); /* $UMEM_LOGGING setting */
    101 }
    102 #endif
    103 
    104 typedef enum {
    105 	HELP_ADD,
    106 	HELP_ATTACH,
    107 	HELP_CLEAR,
    108 	HELP_CREATE,
    109 	HELP_DESTROY,
    110 	HELP_DETACH,
    111 	HELP_EXPORT,
    112 	HELP_HISTORY,
    113 	HELP_IMPORT,
    114 	HELP_IOSTAT,
    115 	HELP_LIST,
    116 	HELP_OFFLINE,
    117 	HELP_ONLINE,
    118 	HELP_REPLACE,
    119 	HELP_REMOVE,
    120 	HELP_SCRUB,
    121 	HELP_STATUS,
    122 	HELP_UPGRADE,
    123 	HELP_GET,
    124 	HELP_SET
    125 } zpool_help_t;
    126 
    127 
    128 typedef struct zpool_command {
    129 	const char	*name;
    130 	int		(*func)(int, char **);
    131 	zpool_help_t	usage;
    132 } zpool_command_t;
    133 
    134 /*
    135  * Master command table.  Each ZFS command has a name, associated function, and
    136  * usage message.  The usage messages need to be internationalized, so we have
    137  * to have a function to return the usage message based on a command index.
    138  *
    139  * These commands are organized according to how they are displayed in the usage
    140  * message.  An empty command (one with a NULL name) indicates an empty line in
    141  * the generic usage message.
    142  */
    143 static zpool_command_t command_table[] = {
    144 	{ "create",	zpool_do_create,	HELP_CREATE		},
    145 	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
    146 	{ NULL },
    147 	{ "add",	zpool_do_add,		HELP_ADD		},
    148 	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
    149 	{ NULL },
    150 	{ "list",	zpool_do_list,		HELP_LIST		},
    151 	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
    152 	{ "status",	zpool_do_status,	HELP_STATUS		},
    153 	{ NULL },
    154 	{ "online",	zpool_do_online,	HELP_ONLINE		},
    155 	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
    156 	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
    157 	{ NULL },
    158 	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
    159 	{ "detach",	zpool_do_detach,	HELP_DETACH		},
    160 	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
    161 	{ NULL },
    162 	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
    163 	{ NULL },
    164 	{ "import",	zpool_do_import,	HELP_IMPORT		},
    165 	{ "export",	zpool_do_export,	HELP_EXPORT		},
    166 	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
    167 	{ NULL },
    168 	{ "history",	zpool_do_history,	HELP_HISTORY		},
    169 	{ "get",	zpool_do_get,		HELP_GET		},
    170 	{ "set",	zpool_do_set,		HELP_SET		},
    171 };
    172 
    173 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
    174 
    175 zpool_command_t *current_command;
    176 static char history_str[HIS_MAX_RECORD_LEN];
    177 
    178 static const char *
    179 get_usage(zpool_help_t idx) {
    180 	switch (idx) {
    181 	case HELP_ADD:
    182 		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
    183 	case HELP_ATTACH:
    184 		return (gettext("\tattach [-f] <pool> <device> "
    185 		    "<new-device>\n"));
    186 	case HELP_CLEAR:
    187 		return (gettext("\tclear <pool> [device]\n"));
    188 	case HELP_CREATE:
    189 		return (gettext("\tcreate [-fn] [-o property=value] ... \n"
    190 		    "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
    191 	case HELP_DESTROY:
    192 		return (gettext("\tdestroy [-f] <pool>\n"));
    193 	case HELP_DETACH:
    194 		return (gettext("\tdetach <pool> <device>\n"));
    195 	case HELP_EXPORT:
    196 		return (gettext("\texport [-f] <pool> ...\n"));
    197 	case HELP_HISTORY:
    198 		return (gettext("\thistory [-il] [<pool>] ...\n"));
    199 	case HELP_IMPORT:
    200 		return (gettext("\timport [-d dir] [-D]\n"
    201 		    "\timport [-o mntopts] [-o property=value] ... \n"
    202 		    "\t    [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
    203 		    "\timport [-o mntopts] [-o property=value] ... \n"
    204 		    "\t    [-d dir | -c cachefile] [-D] [-f] [-R root] "
    205 		    "<pool | id> [newpool]\n"));
    206 	case HELP_IOSTAT:
    207 		return (gettext("\tiostat [-v] [pool] ... [interval "
    208 		    "[count]]\n"));
    209 	case HELP_LIST:
    210 		return (gettext("\tlist [-H] [-o property[,...]] "
    211 		    "[pool] ...\n"));
    212 	case HELP_OFFLINE:
    213 		return (gettext("\toffline [-t] <pool> <device> ...\n"));
    214 	case HELP_ONLINE:
    215 		return (gettext("\tonline <pool> <device> ...\n"));
    216 	case HELP_REPLACE:
    217 		return (gettext("\treplace [-f] <pool> <device> "
    218 		    "[new-device]\n"));
    219 	case HELP_REMOVE:
    220 		return (gettext("\tremove <pool> <device> ...\n"));
    221 	case HELP_SCRUB:
    222 		return (gettext("\tscrub [-s] <pool> ...\n"));
    223 	case HELP_STATUS:
    224 		return (gettext("\tstatus [-vx] [pool] ...\n"));
    225 	case HELP_UPGRADE:
    226 		return (gettext("\tupgrade\n"
    227 		    "\tupgrade -v\n"
    228 		    "\tupgrade [-V version] <-a | pool ...>\n"));
    229 	case HELP_GET:
    230 		return (gettext("\tget <\"all\" | property[,...]> "
    231 		    "<pool> ...\n"));
    232 	case HELP_SET:
    233 		return (gettext("\tset <property=value> <pool> \n"));
    234 	}
    235 
    236 	abort();
    237 	/* NOTREACHED */
    238 }
    239 
    240 
    241 /*
    242  * Callback routine that will print out a pool property value.
    243  */
    244 static int
    245 print_prop_cb(int prop, void *cb)
    246 {
    247 	FILE *fp = cb;
    248 
    249 	(void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
    250 
    251 	if (zpool_prop_readonly(prop))
    252 		(void) fprintf(fp, "  NO   ");
    253 	else
    254 		(void) fprintf(fp, " YES    ");
    255 
    256 	if (zpool_prop_values(prop) == NULL)
    257 		(void) fprintf(fp, "-\n");
    258 	else
    259 		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
    260 
    261 	return (ZPROP_CONT);
    262 }
    263 
    264 /*
    265  * Display usage message.  If we're inside a command, display only the usage for
    266  * that command.  Otherwise, iterate over the entire command table and display
    267  * a complete usage message.
    268  */
    269 void
    270 usage(boolean_t requested)
    271 {
    272 	FILE *fp = requested ? stdout : stderr;
    273 
    274 	if (current_command == NULL) {
    275 		int i;
    276 
    277 		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
    278 		(void) fprintf(fp,
    279 		    gettext("where 'command' is one of the following:\n\n"));
    280 
    281 		for (i = 0; i < NCOMMAND; i++) {
    282 			if (command_table[i].name == NULL)
    283 				(void) fprintf(fp, "\n");
    284 			else
    285 				(void) fprintf(fp, "%s",
    286 				    get_usage(command_table[i].usage));
    287 		}
    288 	} else {
    289 		(void) fprintf(fp, gettext("usage:\n"));
    290 		(void) fprintf(fp, "%s", get_usage(current_command->usage));
    291 	}
    292 
    293 	if (current_command != NULL &&
    294 	    ((strcmp(current_command->name, "set") == 0) ||
    295 	    (strcmp(current_command->name, "get") == 0) ||
    296 	    (strcmp(current_command->name, "list") == 0))) {
    297 
    298 		(void) fprintf(fp,
    299 		    gettext("\nthe following properties are supported:\n"));
    300 
    301 		(void) fprintf(fp, "\n\t%-13s  %s  %s\n\n",
    302 		    "PROPERTY", "EDIT", "VALUES");
    303 
    304 		/* Iterate over all properties */
    305 		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
    306 		    ZFS_TYPE_POOL);
    307 	}
    308 
    309 	/*
    310 	 * See comments at end of main().
    311 	 */
    312 	if (getenv("ZFS_ABORT") != NULL) {
    313 		(void) printf("dumping core by request\n");
    314 		abort();
    315 	}
    316 
    317 	exit(requested ? 0 : 2);
    318 }
    319 
    320 void
    321 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
    322     boolean_t print_logs)
    323 {
    324 	nvlist_t **child;
    325 	uint_t c, children;
    326 	char *vname;
    327 
    328 	if (name != NULL)
    329 		(void) printf("\t%*s%s\n", indent, "", name);
    330 
    331 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
    332 	    &child, &children) != 0)
    333 		return;
    334 
    335 	for (c = 0; c < children; c++) {
    336 		uint64_t is_log = B_FALSE;
    337 
    338 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
    339 		    &is_log);
    340 		if ((is_log && !print_logs) || (!is_log && print_logs))
    341 			continue;
    342 
    343 		vname = zpool_vdev_name(g_zfs, zhp, child[c]);
    344 		print_vdev_tree(zhp, vname, child[c], indent + 2,
    345 		    B_FALSE);
    346 		free(vname);
    347 	}
    348 }
    349 
    350 /*
    351  * Add a property pair (name, string-value) into a property nvlist.
    352  */
    353 static int
    354 add_prop_list(const char *propname, char *propval, nvlist_t **props)
    355 {
    356 	char *strval;
    357 	nvlist_t *proplist;
    358 	zpool_prop_t prop;
    359 
    360 	if (*props == NULL &&
    361 	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
    362 		(void) fprintf(stderr,
    363 		    gettext("internal error: out of memory\n"));
    364 		return (1);
    365 	}
    366 
    367 	proplist = *props;
    368 
    369 	if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
    370 		(void) fprintf(stderr, gettext("property '%s' is "
    371 		    "not a valid pool property\n"), propname);
    372 		return (2);
    373 	}
    374 
    375 	/* Use normalized property name for nvlist operations */
    376 	if (nvlist_lookup_string(proplist, zpool_prop_to_name(prop),
    377 	    &strval) == 0 && prop != ZPOOL_PROP_CACHEFILE) {
    378 		(void) fprintf(stderr, gettext("property '%s' "
    379 		    "specified multiple times\n"), propname);
    380 		return (2);
    381 	}
    382 
    383 	if (nvlist_add_string(proplist, zpool_prop_to_name(prop),
    384 	    propval) != 0) {
    385 		(void) fprintf(stderr, gettext("internal "
    386 		    "error: out of memory\n"));
    387 		return (1);
    388 	}
    389 
    390 	return (0);
    391 }
    392 
    393 /*
    394  * zpool add [-fn] <pool> <vdev> ...
    395  *
    396  *	-f	Force addition of devices, even if they appear in use
    397  *	-n	Do not add the devices, but display the resulting layout if
    398  *		they were to be added.
    399  *
    400  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
    401  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
    402  * libzfs.
    403  */
    404 int
    405 zpool_do_add(int argc, char **argv)
    406 {
    407 	boolean_t force = B_FALSE;
    408 	boolean_t dryrun = B_FALSE;
    409 	int c;
    410 	nvlist_t *nvroot;
    411 	char *poolname;
    412 	int ret;
    413 	zpool_handle_t *zhp;
    414 	nvlist_t *config;
    415 
    416 	/* check options */
    417 	while ((c = getopt(argc, argv, "fn")) != -1) {
    418 		switch (c) {
    419 		case 'f':
    420 			force = B_TRUE;
    421 			break;
    422 		case 'n':
    423 			dryrun = B_TRUE;
    424 			break;
    425 		case '?':
    426 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
    427 			    optopt);
    428 			usage(B_FALSE);
    429 		}
    430 	}
    431 
    432 	argc -= optind;
    433 	argv += optind;
    434 
    435 	/* get pool name and check number of arguments */
    436 	if (argc < 1) {
    437 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
    438 		usage(B_FALSE);
    439 	}
    440 	if (argc < 2) {
    441 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
    442 		usage(B_FALSE);
    443 	}
    444 
    445 	poolname = argv[0];
    446 
    447 	argc--;
    448 	argv++;
    449 
    450 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
    451 		return (1);
    452 
    453 	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
    454 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
    455 		    poolname);
    456 		zpool_close(zhp);
    457 		return (1);
    458 	}
    459 
    460 	/* pass off to get_vdev_spec for processing */
    461 	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, argc, argv);
    462 	if (nvroot == NULL) {
    463 		zpool_close(zhp);
    464 		return (1);
    465 	}
    466 
    467 	if (dryrun) {
    468 		nvlist_t *poolnvroot;
    469 
    470 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
    471 		    &poolnvroot) == 0);
    472 
    473 		(void) printf(gettext("would update '%s' to the following "
    474 		    "configuration:\n"), zpool_get_name(zhp));
    475 
    476 		/* print original main pool and new tree */
    477 		print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
    478 		print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
    479 
    480 		/* Do the same for the logs */
    481 		if (num_logs(poolnvroot) > 0) {
    482 			print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
    483 			print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
    484 		} else if (num_logs(nvroot) > 0) {
    485 			print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
    486 		}
    487 
    488 		ret = 0;
    489 	} else {
    490 		ret = (zpool_add(zhp, nvroot) != 0);
    491 	}
    492 
    493 	nvlist_free(nvroot);
    494 	zpool_close(zhp);
    495 
    496 	return (ret);
    497 }
    498 
    499 /*
    500  * zpool remove <pool> <vdev> ...
    501  *
    502  * Removes the given vdev from the pool.  Currently, this only supports removing
    503  * spares and cache devices from the pool.  Eventually, we'll want to support
    504  * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
    505  */
    506 int
    507 zpool_do_remove(int argc, char **argv)
    508 {
    509 	char *poolname;
    510 	int i, ret = 0;
    511 	zpool_handle_t *zhp;
    512 
    513 	argc--;
    514 	argv++;
    515 
    516 	/* get pool name and check number of arguments */
    517 	if (argc < 1) {
    518 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
    519 		usage(B_FALSE);
    520 	}
    521 	if (argc < 2) {
    522 		(void) fprintf(stderr, gettext("missing device\n"));
    523 		usage(B_FALSE);
    524 	}
    525 
    526 	poolname = argv[0];
    527 
    528 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
    529 		return (1);
    530 
    531 	for (i = 1; i < argc; i++) {
    532 		if (zpool_vdev_remove(zhp, argv[i]) != 0)
    533 			ret = 1;
    534 	}
    535 
    536 	return (ret);
    537 }
    538 
    539 /*
    540  * zpool create [-fn] [-o property=value] ... [-R root] [-m mountpoint]
    541  *		<pool> <dev> ...
    542  *
    543  *	-f	Force creation, even if devices appear in use
    544  *	-n	Do not create the pool, but display the resulting layout if it
    545  *		were to be created.
    546  *      -R	Create a pool under an alternate root
    547  *      -m	Set default mountpoint for the root dataset.  By default it's
    548  *      	'/<pool>'
    549  *	-o	Set property=value.
    550  *
    551  * Creates the named pool according to the given vdev specification.  The
    552  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
    553  * we get the nvlist back from get_vdev_spec(), we either print out the contents
    554  * (if '-n' was specified), or pass it to libzfs to do the creation.
    555  */
    556 int
    557 zpool_do_create(int argc, char **argv)
    558 {
    559 	boolean_t force = B_FALSE;
    560 	boolean_t dryrun = B_FALSE;
    561 	int c;
    562 	nvlist_t *nvroot = NULL;
    563 	char *poolname;
    564 	int ret = 1;
    565 	char *altroot = NULL;
    566 	char *mountpoint = NULL;
    567 	nvlist_t *props = NULL;
    568 	char *propval;
    569 
    570 	/* check options */
    571 	while ((c = getopt(argc, argv, ":fnR:m:o:")) != -1) {
    572 		switch (c) {
    573 		case 'f':
    574 			force = B_TRUE;
    575 			break;
    576 		case 'n':
    577 			dryrun = B_TRUE;
    578 			break;
    579 		case 'R':
    580 			altroot = optarg;
    581 			if (add_prop_list(zpool_prop_to_name(
    582 			    ZPOOL_PROP_ALTROOT), optarg, &props))
    583 				goto errout;
    584 			if (nvlist_lookup_string(props,
    585 			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
    586 			    &propval) == 0)
    587 				break;
    588 			if (add_prop_list(zpool_prop_to_name(
    589 			    ZPOOL_PROP_CACHEFILE), "none", &props))
    590 				goto errout;
    591 			break;
    592 		case 'm':
    593 			mountpoint = optarg;
    594 			break;
    595 		case 'o':
    596 			if ((propval = strchr(optarg, '=')) == NULL) {
    597 				(void) fprintf(stderr, gettext("missing "
    598 				    "'=' for -o option\n"));
    599 				goto errout;
    600 			}
    601 			*propval = '\0';
    602 			propval++;
    603 
    604 			if (add_prop_list(optarg, propval, &props))
    605 				goto errout;
    606 			break;
    607 		case ':':
    608 			(void) fprintf(stderr, gettext("missing argument for "
    609 			    "'%c' option\n"), optopt);
    610 			goto badusage;
    611 		case '?':
    612 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
    613 			    optopt);
    614 			goto badusage;
    615 		}
    616 	}
    617 
    618 	argc -= optind;
    619 	argv += optind;
    620 
    621 	/* get pool name and check number of arguments */
    622 	if (argc < 1) {
    623 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
    624 		goto badusage;
    625 	}
    626 	if (argc < 2) {
    627 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
    628 		goto badusage;
    629 	}
    630 
    631 	poolname = argv[0];
    632 
    633 	/*
    634 	 * As a special case, check for use of '/' in the name, and direct the
    635 	 * user to use 'zfs create' instead.
    636 	 */
    637 	if (strchr(poolname, '/') != NULL) {
    638 		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
    639 		    "character '/' in pool name\n"), poolname);
    640 		(void) fprintf(stderr, gettext("use 'zfs create' to "
    641 		    "create a dataset\n"));
    642 		goto errout;
    643 	}
    644 
    645 	/* pass off to get_vdev_spec for bulk processing */
    646 	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1,
    647 	    argv + 1);
    648 	if (nvroot == NULL)
    649 		return (1);
    650 
    651 	/* make_root_vdev() allows 0 toplevel children if there are spares */
    652 	if (!zfs_allocatable_devs(nvroot)) {
    653 		(void) fprintf(stderr, gettext("invalid vdev "
    654 		    "specification: at least one toplevel vdev must be "
    655 		    "specified\n"));
    656 		goto errout;
    657 	}
    658 
    659 
    660 	if (altroot != NULL && altroot[0] != '/') {
    661 		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
    662 		    "must be an absolute path\n"), altroot);
    663 		goto errout;
    664 	}
    665 
    666 	/*
    667 	 * Check the validity of the mountpoint and direct the user to use the
    668 	 * '-m' mountpoint option if it looks like its in use.
    669 	 */
    670 	if (mountpoint == NULL ||
    671 	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
    672 	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
    673 		char buf[MAXPATHLEN];
    674 		DIR *dirp;
    675 
    676 		if (mountpoint && mountpoint[0] != '/') {
    677 			(void) fprintf(stderr, gettext("invalid mountpoint "
    678 			    "'%s': must be an absolute path, 'legacy', or "
    679 			    "'none'\n"), mountpoint);
    680 			goto errout;
    681 		}
    682 
    683 		if (mountpoint == NULL) {
    684 			if (altroot != NULL)
    685 				(void) snprintf(buf, sizeof (buf), "%s/%s",
    686 				    altroot, poolname);
    687 			else
    688 				(void) snprintf(buf, sizeof (buf), "/%s",
    689 				    poolname);
    690 		} else {
    691 			if (altroot != NULL)
    692 				(void) snprintf(buf, sizeof (buf), "%s%s",
    693 				    altroot, mountpoint);
    694 			else
    695 				(void) snprintf(buf, sizeof (buf), "%s",
    696 				    mountpoint);
    697 		}
    698 
    699 		if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
    700 			(void) fprintf(stderr, gettext("mountpoint '%s' : "
    701 			    "%s\n"), buf, strerror(errno));
    702 			(void) fprintf(stderr, gettext("use '-m' "
    703 			    "option to provide a different default\n"));
    704 			goto errout;
    705 		} else if (dirp) {
    706 			int count = 0;
    707 
    708 			while (count < 3 && readdir(dirp) != NULL)
    709 				count++;
    710 			(void) closedir(dirp);
    711 
    712 			if (count > 2) {
    713 				(void) fprintf(stderr, gettext("mountpoint "
    714 				    "'%s' exists and is not empty\n"), buf);
    715 				(void) fprintf(stderr, gettext("use '-m' "
    716 				    "option to provide a "
    717 				    "different default\n"));
    718 				goto errout;
    719 			}
    720 		}
    721 	}
    722 
    723 	if (dryrun) {
    724 		/*
    725 		 * For a dry run invocation, print out a basic message and run
    726 		 * through all the vdevs in the list and print out in an
    727 		 * appropriate hierarchy.
    728 		 */
    729 		(void) printf(gettext("would create '%s' with the "
    730 		    "following layout:\n\n"), poolname);
    731 
    732 		print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
    733 		if (num_logs(nvroot) > 0)
    734 			print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
    735 
    736 		ret = 0;
    737 	} else {
    738 		/*
    739 		 * Hand off to libzfs.
    740 		 */
    741 		if (zpool_create(g_zfs, poolname, nvroot, props) == 0) {
    742 			zfs_handle_t *pool = zfs_open(g_zfs, poolname,
    743 			    ZFS_TYPE_FILESYSTEM);
    744 			if (pool != NULL) {
    745 				if (mountpoint != NULL)
    746 					verify(zfs_prop_set(pool,
    747 					    zfs_prop_to_name(
    748 					    ZFS_PROP_MOUNTPOINT),
    749 					    mountpoint) == 0);
    750 				if (zfs_mount(pool, NULL, 0) == 0)
    751 					ret = zfs_shareall(pool);
    752 				zfs_close(pool);
    753 			}
    754 		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
    755 			(void) fprintf(stderr, gettext("pool name may have "
    756 			    "been omitted\n"));
    757 		}
    758 	}
    759 
    760 errout:
    761 	nvlist_free(nvroot);
    762 	nvlist_free(props);
    763 	return (ret);
    764 badusage:
    765 	nvlist_free(props);
    766 	usage(B_FALSE);
    767 	return (2);
    768 }
    769 
    770 /*
    771  * zpool destroy <pool>
    772  *
    773  * 	-f	Forcefully unmount any datasets
    774  *
    775  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
    776  */
    777 int
    778 zpool_do_destroy(int argc, char **argv)
    779 {
    780 	boolean_t force = B_FALSE;
    781 	int c;
    782 	char *pool;
    783 	zpool_handle_t *zhp;
    784 	int ret;
    785 
    786 	/* check options */
    787 	while ((c = getopt(argc, argv, "f")) != -1) {
    788 		switch (c) {
    789 		case 'f':
    790 			force = B_TRUE;
    791 			break;
    792 		case '?':
    793 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
    794 			    optopt);
    795 			usage(B_FALSE);
    796 		}
    797 	}
    798 
    799 	argc -= optind;
    800 	argv += optind;
    801 
    802 	/* check arguments */
    803 	if (argc < 1) {
    804 		(void) fprintf(stderr, gettext("missing pool argument\n"));
    805 		usage(B_FALSE);
    806 	}
    807 	if (argc > 1) {
    808 		(void) fprintf(stderr, gettext("too many arguments\n"));
    809 		usage(B_FALSE);
    810 	}
    811 
    812 	pool = argv[0];
    813 
    814 	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
    815 		/*
    816 		 * As a special case, check for use of '/' in the name, and
    817 		 * direct the user to use 'zfs destroy' instead.
    818 		 */
    819 		if (strchr(pool, '/') != NULL)
    820 			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
    821 			    "destroy a dataset\n"));
    822 		return (1);
    823 	}
    824 
    825 	if (zpool_disable_datasets(zhp, force) != 0) {
    826 		(void) fprintf(stderr, gettext("could not destroy '%s': "
    827 		    "could not unmount datasets\n"), zpool_get_name(zhp));
    828 		return (1);
    829 	}
    830 
    831 	ret = (zpool_destroy(zhp) != 0);
    832 
    833 	zpool_close(zhp);
    834 
    835 	return (ret);
    836 }
    837 
    838 /*
    839  * zpool export [-f] <pool> ...
    840  *
    841  *	-f	Forcefully unmount datasets
    842  *
    843  * Export the given pools.  By default, the command will attempt to cleanly
    844  * unmount any active datasets within the pool.  If the '-f' flag is specified,
    845  * then the datasets will be forcefully unmounted.
    846  */
    847 int
    848 zpool_do_export(int argc, char **argv)
    849 {
    850 	boolean_t force = B_FALSE;
    851 	int c;
    852 	zpool_handle_t *zhp;
    853 	int ret;
    854 	int i;
    855 
    856 	/* check options */
    857 	while ((c = getopt(argc, argv, "f")) != -1) {
    858 		switch (c) {
    859 		case 'f':
    860 			force = B_TRUE;
    861 			break;
    862 		case '?':
    863 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
    864 			    optopt);
    865 			usage(B_FALSE);
    866 		}
    867 	}
    868 
    869 	argc -= optind;
    870 	argv += optind;
    871 
    872 	/* check arguments */
    873 	if (argc < 1) {
    874 		(void) fprintf(stderr, gettext("missing pool argument\n"));
    875 		usage(B_FALSE);
    876 	}
    877 
    878 	ret = 0;
    879 	for (i = 0; i < argc; i++) {
    880 		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
    881 			ret = 1;
    882 			continue;
    883 		}
    884 
    885 		if (zpool_disable_datasets(zhp, force) != 0) {
    886 			ret = 1;
    887 			zpool_close(zhp);
    888 			continue;
    889 		}
    890 
    891 		if (zpool_export(zhp) != 0)
    892 			ret = 1;
    893 
    894 		zpool_close(zhp);
    895 	}
    896 
    897 	return (ret);
    898 }
    899 
    900 /*
    901  * Given a vdev configuration, determine the maximum width needed for the device
    902  * name column.
    903  */
    904 static int
    905 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
    906 {
    907 	char *name = zpool_vdev_name(g_zfs, zhp, nv);
    908 	nvlist_t **child;
    909 	uint_t c, children;
    910 	int ret;
    911 
    912 	if (strlen(name) + depth > max)
    913 		max = strlen(name) + depth;
    914 
    915 	free(name);
    916 
    917 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
    918 	    &child, &children) == 0) {
    919 		for (c = 0; c < children; c++)
    920 			if ((ret = max_width(zhp, child[c], depth + 2,
    921 			    max)) > max)
    922 				max = ret;
    923 	}
    924 
    925 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
    926 	    &child, &children) == 0) {
    927 		for (c = 0; c < children; c++)
    928 			if ((ret = max_width(zhp, child[c], depth + 2,
    929 			    max)) > max)
    930 				max = ret;
    931 	}
    932 
    933 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
    934 	    &child, &children) == 0) {
    935 		for (c = 0; c < children; c++)
    936 			if ((ret = max_width(zhp, child[c], depth + 2,
    937 			    max)) > max)
    938 				max = ret;
    939 	}
    940 
    941 
    942 	return (max);
    943 }
    944 
    945 
    946 /*
    947  * Print the configuration of an exported pool.  Iterate over all vdevs in the
    948  * pool, printing out the name and status for each one.
    949  */
    950 void
    951 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
    952     boolean_t print_logs)
    953 {
    954 	nvlist_t **child;
    955 	uint_t c, children;
    956 	vdev_stat_t *vs;
    957 	char *type, *vname;
    958 
    959 	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
    960 	if (strcmp(type, VDEV_TYPE_MISSING) == 0)
    961 		return;
    962 
    963 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
    964 	    (uint64_t **)&vs, &c) == 0);
    965 
    966 	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
    967 	(void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
    968 
    969 	if (vs->vs_aux != 0) {
    970 		(void) printf("  ");
    971 
    972 		switch (vs->vs_aux) {
    973 		case VDEV_AUX_OPEN_FAILED:
    974 			(void) printf(gettext("cannot open"));
    975 			break;
    976 
    977 		case VDEV_AUX_BAD_GUID_SUM:
    978 			(void) printf(gettext("missing device"));
    979 			break;
    980 
    981 		case VDEV_AUX_NO_REPLICAS:
    982 			(void) printf(gettext("insufficient replicas"));
    983 			break;
    984 
    985 		case VDEV_AUX_VERSION_NEWER:
    986 			(void) printf(gettext("newer version"));
    987 			break;
    988 
    989 		case VDEV_AUX_ERR_EXCEEDED:
    990 			(void) printf(gettext("too many errors"));
    991 			break;
    992 
    993 		default:
    994 			(void) printf(gettext("corrupted data"));
    995 			break;
    996 		}
    997 	}
    998 	(void) printf("\n");
    999 
   1000 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
   1001 	    &child, &children) != 0)
   1002 		return;
   1003 
   1004 	for (c = 0; c < children; c++) {
   1005 		uint64_t is_log = B_FALSE;
   1006 
   1007 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
   1008 		    &is_log);
   1009 		if ((is_log && !print_logs) || (!is_log && print_logs))
   1010 			continue;
   1011 
   1012 		vname = zpool_vdev_name(g_zfs, NULL, child[c]);
   1013 		print_import_config(vname, child[c],
   1014 		    namewidth, depth + 2, B_FALSE);
   1015 		free(vname);
   1016 	}
   1017 
   1018 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
   1019 	    &child, &children) == 0) {
   1020 		(void) printf(gettext("\tcache\n"));
   1021 		for (c = 0; c < children; c++) {
   1022 			vname = zpool_vdev_name(g_zfs, NULL, child[c]);
   1023 			(void) printf("\t  %s\n", vname);
   1024 			free(vname);
   1025 		}
   1026 	}
   1027 
   1028 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
   1029 	    &child, &children) == 0) {
   1030 		(void) printf(gettext("\tspares\n"));
   1031 		for (c = 0; c < children; c++) {
   1032 			vname = zpool_vdev_name(g_zfs, NULL, child[c]);
   1033 			(void) printf("\t  %s\n", vname);
   1034 			free(vname);
   1035 		}
   1036 	}
   1037 }
   1038 
   1039 /*
   1040  * Display the status for the given pool.
   1041  */
   1042 static void
   1043 show_import(nvlist_t *config)
   1044 {
   1045 	uint64_t pool_state;
   1046 	vdev_stat_t *vs;
   1047 	char *name;
   1048 	uint64_t guid;
   1049 	char *msgid;
   1050 	nvlist_t *nvroot;
   1051 	int reason;
   1052 	const char *health;
   1053 	uint_t vsc;
   1054 	int namewidth;
   1055 
   1056 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
   1057 	    &name) == 0);
   1058 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
   1059 	    &guid) == 0);
   1060 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
   1061 	    &pool_state) == 0);
   1062 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
   1063 	    &nvroot) == 0);
   1064 
   1065 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
   1066 	    (uint64_t **)&vs, &vsc) == 0);
   1067 	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
   1068 
   1069 	reason = zpool_import_status(config, &msgid);
   1070 
   1071 	(void) printf(gettext("  pool: %s\n"), name);
   1072 	(void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
   1073 	(void) printf(gettext(" state: %s"), health);
   1074 	if (pool_state == POOL_STATE_DESTROYED)
   1075 		(void) printf(gettext(" (DESTROYED)"));
   1076 	(void) printf("\n");
   1077 
   1078 	switch (reason) {
   1079 	case ZPOOL_STATUS_MISSING_DEV_R:
   1080 	case ZPOOL_STATUS_MISSING_DEV_NR:
   1081 	case ZPOOL_STATUS_BAD_GUID_SUM:
   1082 		(void) printf(gettext("status: One or more devices are missing "
   1083 		    "from the system.\n"));
   1084 		break;
   1085 
   1086 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
   1087 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
   1088 		(void) printf(gettext("status: One or more devices contains "
   1089 		    "corrupted data.\n"));
   1090 		break;
   1091 
   1092 	case ZPOOL_STATUS_CORRUPT_DATA:
   1093 		(void) printf(gettext("status: The pool data is corrupted.\n"));
   1094 		break;
   1095 
   1096 	case ZPOOL_STATUS_OFFLINE_DEV:
   1097 		(void) printf(gettext("status: One or more devices "
   1098 		    "are offlined.\n"));
   1099 		break;
   1100 
   1101 	case ZPOOL_STATUS_CORRUPT_POOL:
   1102 		(void) printf(gettext("status: The pool metadata is "
   1103 		    "corrupted.\n"));
   1104 		break;
   1105 
   1106 	case ZPOOL_STATUS_VERSION_OLDER:
   1107 		(void) printf(gettext("status: The pool is formatted using an "
   1108 		    "older on-disk version.\n"));
   1109 		break;
   1110 
   1111 	case ZPOOL_STATUS_VERSION_NEWER:
   1112 		(void) printf(gettext("status: The pool is formatted using an "
   1113 		    "incompatible version.\n"));
   1114 		break;
   1115 	case ZPOOL_STATUS_HOSTID_MISMATCH:
   1116 		(void) printf(gettext("status: The pool was last accessed by "
   1117 		    "another system.\n"));
   1118 		break;
   1119 	case ZPOOL_STATUS_FAULTED_DEV_R:
   1120 	case ZPOOL_STATUS_FAULTED_DEV_NR:
   1121 		(void) printf(gettext("status: One or more devices are "
   1122 		    "fa