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