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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25  * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26  * Copyright (c) 2012 Martin Matuska <[email protected]>. All rights reserved.
27  * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28  * Copyright 2016 Igor Kozhukhov <[email protected]>.
29  * Copyright 2016 Nexenta Systems, Inc.
30  * Copyright (c) 2017 Datto Inc.
31  */
32 
33 #include <solaris.h>
34 #include <assert.h>
35 #include <ctype.h>
36 #include <dirent.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <getopt.h>
40 #include <libgen.h>
41 #include <libintl.h>
42 #include <libuutil.h>
43 #include <locale.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <strings.h>
48 #include <unistd.h>
49 #include <priv.h>
50 #include <pwd.h>
51 #include <zone.h>
52 #include <sys/time.h>
53 #include <zfs_prop.h>
54 #include <sys/fs/zfs.h>
55 #include <sys/stat.h>
56 
57 #include <libzfs.h>
58 
59 #include "zpool_util.h"
60 #include "zfs_comutil.h"
61 #include "zfeature_common.h"
62 
63 #include "statcommon.h"
64 
65 static int zpool_do_create(int, char **);
66 static int zpool_do_destroy(int, char **);
67 
68 static int zpool_do_add(int, char **);
69 static int zpool_do_remove(int, char **);
70 static int zpool_do_labelclear(int, char **);
71 
72 static int zpool_do_checkpoint(int, char **);
73 
74 static int zpool_do_list(int, char **);
75 static int zpool_do_iostat(int, char **);
76 static int zpool_do_status(int, char **);
77 
78 static int zpool_do_online(int, char **);
79 static int zpool_do_offline(int, char **);
80 static int zpool_do_clear(int, char **);
81 static int zpool_do_reopen(int, char **);
82 
83 static int zpool_do_reguid(int, char **);
84 
85 static int zpool_do_attach(int, char **);
86 static int zpool_do_detach(int, char **);
87 static int zpool_do_replace(int, char **);
88 static int zpool_do_split(int, char **);
89 
90 static int zpool_do_initialize(int, char **);
91 static int zpool_do_scrub(int, char **);
92 
93 static int zpool_do_import(int, char **);
94 static int zpool_do_export(int, char **);
95 
96 static int zpool_do_upgrade(int, char **);
97 
98 static int zpool_do_history(int, char **);
99 
100 static int zpool_do_get(int, char **);
101 static int zpool_do_set(int, char **);
102 
103 /*
104  * These libumem hooks provide a reasonable set of defaults for the allocator's
105  * debugging facilities.
106  */
107 
108 #ifdef DEBUG
109 const char *
_umem_debug_init(void)110 _umem_debug_init(void)
111 {
112 	return ("default,verbose"); /* $UMEM_DEBUG setting */
113 }
114 
115 const char *
_umem_logging_init(void)116 _umem_logging_init(void)
117 {
118 	return ("fail,contents"); /* $UMEM_LOGGING setting */
119 }
120 #endif
121 
122 typedef enum {
123 	HELP_ADD,
124 	HELP_ATTACH,
125 	HELP_CLEAR,
126 	HELP_CREATE,
127 	HELP_CHECKPOINT,
128 	HELP_DESTROY,
129 	HELP_DETACH,
130 	HELP_EXPORT,
131 	HELP_HISTORY,
132 	HELP_IMPORT,
133 	HELP_IOSTAT,
134 	HELP_LABELCLEAR,
135 	HELP_LIST,
136 	HELP_OFFLINE,
137 	HELP_ONLINE,
138 	HELP_REPLACE,
139 	HELP_REMOVE,
140 	HELP_INITIALIZE,
141 	HELP_SCRUB,
142 	HELP_STATUS,
143 	HELP_UPGRADE,
144 	HELP_GET,
145 	HELP_SET,
146 	HELP_SPLIT,
147 	HELP_REGUID,
148 	HELP_REOPEN
149 } zpool_help_t;
150 
151 
152 typedef struct zpool_command {
153 	const char	*name;
154 	int		(*func)(int, char **);
155 	zpool_help_t	usage;
156 } zpool_command_t;
157 
158 /*
159  * Master command table.  Each ZFS command has a name, associated function, and
160  * usage message.  The usage messages need to be internationalized, so we have
161  * to have a function to return the usage message based on a command index.
162  *
163  * These commands are organized according to how they are displayed in the usage
164  * message.  An empty command (one with a NULL name) indicates an empty line in
165  * the generic usage message.
166  */
167 static zpool_command_t command_table[] = {
168 	{ "create",	zpool_do_create,	HELP_CREATE		},
169 	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
170 	{ NULL },
171 	{ "add",	zpool_do_add,		HELP_ADD		},
172 	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
173 	{ NULL },
174 	{ "labelclear",	zpool_do_labelclear,	HELP_LABELCLEAR		},
175 	{ NULL },
176 	{ "checkpoint",	zpool_do_checkpoint,	HELP_CHECKPOINT		},
177 	{ NULL },
178 	{ "list",	zpool_do_list,		HELP_LIST		},
179 	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
180 	{ "status",	zpool_do_status,	HELP_STATUS		},
181 	{ NULL },
182 	{ "online",	zpool_do_online,	HELP_ONLINE		},
183 	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
184 	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
185 	{ "reopen",	zpool_do_reopen,	HELP_REOPEN		},
186 	{ NULL },
187 	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
188 	{ "detach",	zpool_do_detach,	HELP_DETACH		},
189 	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
190 	{ "split",	zpool_do_split,		HELP_SPLIT		},
191 	{ NULL },
192 	{ "initialize",	zpool_do_initialize,	HELP_INITIALIZE		},
193 	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
194 	{ NULL },
195 	{ "import",	zpool_do_import,	HELP_IMPORT		},
196 	{ "export",	zpool_do_export,	HELP_EXPORT		},
197 	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
198 	{ "reguid",	zpool_do_reguid,	HELP_REGUID		},
199 	{ NULL },
200 	{ "history",	zpool_do_history,	HELP_HISTORY		},
201 	{ "get",	zpool_do_get,		HELP_GET		},
202 	{ "set",	zpool_do_set,		HELP_SET		},
203 };
204 
205 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
206 
207 static zpool_command_t *current_command;
208 static char history_str[HIS_MAX_RECORD_LEN];
209 static boolean_t log_history = B_TRUE;
210 static uint_t timestamp_fmt = NODATE;
211 
212 static const char *
get_usage(zpool_help_t idx)213 get_usage(zpool_help_t idx)
214 {
215 	switch (idx) {
216 	case HELP_ADD:
217 		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
218 	case HELP_ATTACH:
219 		return (gettext("\tattach [-f] <pool> <device> "
220 		    "<new-device>\n"));
221 	case HELP_CLEAR:
222 		return (gettext("\tclear [-nF] <pool> [device]\n"));
223 	case HELP_CREATE:
224 		return (gettext("\tcreate [-fnd] [-B] "
225 		    "[-o property=value] ... \n"
226 		    "\t    [-O file-system-property=value] ...\n"
227 		    "\t    [-m mountpoint] [-R root] [-t tempname] "
228 		    "<pool> <vdev> ...\n"));
229 	case HELP_CHECKPOINT:
230 		return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
231 	case HELP_DESTROY:
232 		return (gettext("\tdestroy [-f] <pool>\n"));
233 	case HELP_DETACH:
234 		return (gettext("\tdetach <pool> <device>\n"));
235 	case HELP_EXPORT:
236 		return (gettext("\texport [-f] <pool> ...\n"));
237 	case HELP_HISTORY:
238 		return (gettext("\thistory [-il] [<pool>] ...\n"));
239 	case HELP_IMPORT:
240 		return (gettext("\timport [-d dir] [-D]\n"
241 		    "\timport [-o mntopts] [-o property=value] ... \n"
242 		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
243 		    "[-R root] [-F [-n]] -a\n"
244 		    "\timport [-o mntopts] [-o property=value] ... \n"
245 		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
246 		    "[-R root] [-F [-n]] [-t]\n"
247 		    "\t    [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
248 	case HELP_IOSTAT:
249 		return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
250 		    "[count]]\n"));
251 	case HELP_LABELCLEAR:
252 		return (gettext("\tlabelclear [-f] <vdev>\n"));
253 	case HELP_LIST:
254 		return (gettext("\tlist [-Hpv] [-o property[,...]] "
255 		    "[-T d|u] [pool] ... [interval [count]]\n"));
256 	case HELP_OFFLINE:
257 		return (gettext("\toffline [-t] <pool> <device> ...\n"));
258 	case HELP_ONLINE:
259 		return (gettext("\tonline [-e] <pool> <device> ...\n"));
260 	case HELP_REPLACE:
261 		return (gettext("\treplace [-f] <pool> <device> "
262 		    "[new-device]\n"));
263 	case HELP_REMOVE:
264 		return (gettext("\tremove [-nps] <pool> <device> ...\n"));
265 	case HELP_REOPEN:
266 		return (gettext("\treopen <pool>\n"));
267 	case HELP_INITIALIZE:
268 		return (gettext("\tinitialize [-cs] <pool> [<device> ...]\n"));
269 	case HELP_SCRUB:
270 		return (gettext("\tscrub [-s | -p] <pool> ...\n"));
271 	case HELP_STATUS:
272 		return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
273 		    "[count]]\n"));
274 	case HELP_UPGRADE:
275 		return (gettext("\tupgrade [-v]\n"
276 		    "\tupgrade [-V version] <-a | pool ...>\n"));
277 	case HELP_GET:
278 		return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
279 		    "<\"all\" | property[,...]> <pool> ...\n"));
280 	case HELP_SET:
281 		return (gettext("\tset <property=value> <pool> \n"));
282 	case HELP_SPLIT:
283 		return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
284 		    "\t    [-o property=value] <pool> <newpool> "
285 		    "[<device> ...]\n"));
286 	case HELP_REGUID:
287 		return (gettext("\treguid <pool>\n"));
288 	}
289 
290 	abort();
291 	/* NOTREACHED */
292 }
293 
294 
295 /*
296  * Callback routine that will print out a pool property value.
297  */
298 static int
print_prop_cb(int prop,void * cb)299 print_prop_cb(int prop, void *cb)
300 {
301 	FILE *fp = cb;
302 
303 	(void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
304 
305 	if (zpool_prop_readonly(prop))
306 		(void) fprintf(fp, "  NO   ");
307 	else
308 		(void) fprintf(fp, " YES   ");
309 
310 	if (zpool_prop_values(prop) == NULL)
311 		(void) fprintf(fp, "-\n");
312 	else
313 		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
314 
315 	return (ZPROP_CONT);
316 }
317 
318 /*
319  * Display usage message.  If we're inside a command, display only the usage for
320  * that command.  Otherwise, iterate over the entire command table and display
321  * a complete usage message.
322  */
323 void
usage(boolean_t requested)324 usage(boolean_t requested)
325 {
326 	FILE *fp = requested ? stdout : stderr;
327 
328 	if (current_command == NULL) {
329 		int i;
330 
331 		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
332 		(void) fprintf(fp,
333 		    gettext("where 'command' is one of the following:\n\n"));
334 
335 		for (i = 0; i < NCOMMAND; i++) {
336 			if (command_table[i].name == NULL)
337 				(void) fprintf(fp, "\n");
338 			else
339 				(void) fprintf(fp, "%s",
340 				    get_usage(command_table[i].usage));
341 		}
342 	} else {
343 		(void) fprintf(fp, gettext("usage:\n"));
344 		(void) fprintf(fp, "%s", get_usage(current_command->usage));
345 	}
346 
347 	if (current_command != NULL &&
348 	    ((strcmp(current_command->name, "set") == 0) ||
349 	    (strcmp(current_command->name, "get") == 0) ||
350 	    (strcmp(current_command->name, "list") == 0))) {
351 
352 		(void) fprintf(fp,
353 		    gettext("\nthe following properties are supported:\n"));
354 
355 		(void) fprintf(fp, "\n\t%-15s  %s   %s\n\n",
356 		    "PROPERTY", "EDIT", "VALUES");
357 
358 		/* Iterate over all properties */
359 		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
360 		    ZFS_TYPE_POOL);
361 
362 		(void) fprintf(fp, "\t%-15s   ", "feature@...");
363 		(void) fprintf(fp, "YES   disabled | enabled | active\n");
364 
365 		(void) fprintf(fp, gettext("\nThe feature@ properties must be "
366 		    "appended with a feature name.\nSee zpool-features(7).\n"));
367 	}
368 
369 	/*
370 	 * See comments at end of main().
371 	 */
372 	if (getenv("ZFS_ABORT") != NULL) {
373 		(void) printf("dumping core by request\n");
374 		abort();
375 	}
376 
377 	exit(requested ? 0 : 2);
378 }
379 
380 void
print_vdev_tree(zpool_handle_t * zhp,const char * name,nvlist_t * nv,int indent,boolean_t print_logs)381 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
382     boolean_t print_logs)
383 {
384 	nvlist_t **child;
385 	uint_t c, children;
386 	char *vname;
387 
388 	if (name != NULL)
389 		(void) printf("\t%*s%s\n", indent, "", name);
390 
391 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
392 	    &child, &children) != 0)
393 		return;
394 
395 	for (c = 0; c < children; c++) {
396 		uint64_t is_log = B_FALSE;
397 
398 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
399 		    &is_log);
400 		if ((is_log && !print_logs) || (!is_log && print_logs))
401 			continue;
402 
403 		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
404 		print_vdev_tree(zhp, vname, child[c], indent + 2,
405 		    B_FALSE);
406 		free(vname);
407 	}
408 }
409 
410 static boolean_t
prop_list_contains_feature(nvlist_t * proplist)411 prop_list_contains_feature(nvlist_t *proplist)
412 {
413 	nvpair_t *nvp;
414 	for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
415 	    nvp = nvlist_next_nvpair(proplist, nvp)) {
416 		if (zpool_prop_feature(nvpair_name(nvp)))
417 			return (B_TRUE);
418 	}
419 	return (B_FALSE);
420 }
421 
422 /*
423  * Add a property pair (name, string-value) into a property nvlist.
424  */
425 static int
add_prop_list(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)426 add_prop_list(const char *propname, char *propval, nvlist_t **props,
427     boolean_t poolprop)
428 {
429 	zpool_prop_t prop = ZPROP_INVAL;
430 	zfs_prop_t fprop;
431 	nvlist_t *proplist;
432 	const char *normnm;
433 	char *strval;
434 
435 	if (*props == NULL &&
436 	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
437 		(void) fprintf(stderr,
438 		    gettext("internal error: out of memory\n"));
439 		return (1);
440 	}
441 
442 	proplist = *props;
443 
444 	if (poolprop) {
445 		const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
446 
447 		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
448 		    !zpool_prop_feature(propname)) {
449 			(void) fprintf(stderr, gettext("property '%s' is "
450 			    "not a valid pool property\n"), propname);
451 			return (2);
452 		}
453 
454 		/*
455 		 * feature@ properties and version should not be specified
456 		 * at the same time.
457 		 */
458 		if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
459 		    nvlist_exists(proplist, vname)) ||
460 		    (prop == ZPOOL_PROP_VERSION &&
461 		    prop_list_contains_feature(proplist))) {
462 			(void) fprintf(stderr, gettext("'feature@' and "
463 			    "'version' properties cannot be specified "
464 			    "together\n"));
465 			return (2);
466 		}
467 
468 
469 		if (zpool_prop_feature(propname))
470 			normnm = propname;
471 		else
472 			normnm = zpool_prop_to_name(prop);
473 	} else {
474 		if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
475 			normnm = zfs_prop_to_name(fprop);
476 		} else {
477 			normnm = propname;
478 		}
479 	}
480 
481 	if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
482 	    prop != ZPOOL_PROP_CACHEFILE) {
483 		(void) fprintf(stderr, gettext("property '%s' "
484 		    "specified multiple times\n"), propname);
485 		return (2);
486 	}
487 
488 	if (nvlist_add_string(proplist, normnm, propval) != 0) {
489 		(void) fprintf(stderr, gettext("internal "
490 		    "error: out of memory\n"));
491 		return (1);
492 	}
493 
494 	return (0);
495 }
496 
497 /*
498  * Set a default property pair (name, string-value) in a property nvlist
499  */
500 static int
add_prop_list_default(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)501 add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
502     boolean_t poolprop)
503 {
504 	char *pval;
505 
506 	if (nvlist_lookup_string(*props, propname, &pval) == 0)
507 		return (0);
508 
509 	return (add_prop_list(propname, propval, props, poolprop));
510 }
511 
512 /*
513  * zpool add [-fn] <pool> <vdev> ...
514  *
515  *	-f	Force addition of devices, even if they appear in use
516  *	-n	Do not add the devices, but display the resulting layout if
517  *		they were to be added.
518  *
519  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
520  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
521  * libzfs.
522  */
523 int
zpool_do_add(int argc,char ** argv)524 zpool_do_add(int argc, char **argv)
525 {
526 	boolean_t force = B_FALSE;
527 	boolean_t dryrun = B_FALSE;
528 	int c;
529 	nvlist_t *nvroot;
530 	char *poolname;
531 	zpool_boot_label_t boot_type;
532 	uint64_t boot_size;
533 	int ret;
534 	zpool_handle_t *zhp;
535 	nvlist_t *config;
536 
537 	/* check options */
538 	while ((c = getopt(argc, argv, "fn")) != -1) {
539 		switch (c) {
540 		case 'f':
541 			force = B_TRUE;
542 			break;
543 		case 'n':
544 			dryrun = B_TRUE;
545 			break;
546 		case '?':
547 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
548 			    optopt);
549 			usage(B_FALSE);
550 		}
551 	}
552 
553 	argc -= optind;
554 	argv += optind;
555 
556 	/* get pool name and check number of arguments */
557 	if (argc < 1) {
558 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
559 		usage(B_FALSE);
560 	}
561 	if (argc < 2) {
562 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
563 		usage(B_FALSE);
564 	}
565 
566 	poolname = argv[0];
567 
568 	argc--;
569 	argv++;
570 
571 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
572 		return (1);
573 
574 	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
575 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
576 		    poolname);
577 		zpool_close(zhp);
578 		return (1);
579 	}
580 
581 	if (zpool_is_bootable(zhp))
582 		boot_type = ZPOOL_COPY_BOOT_LABEL;
583 	else
584 		boot_type = ZPOOL_NO_BOOT_LABEL;
585 
586 	/* pass off to get_vdev_spec for processing */
587 	boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
588 	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
589 	    boot_type, boot_size, argc, argv);
590 	if (nvroot == NULL) {
591 		zpool_close(zhp);
592 		return (1);
593 	}
594 
595 	if (dryrun) {
596 		nvlist_t *poolnvroot;
597 
598 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
599 		    &poolnvroot) == 0);
600 
601 		(void) printf(gettext("would update '%s' to the following "
602 		    "configuration:\n"), zpool_get_name(zhp));
603 
604 		/* print original main pool and new tree */
605 		print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
606 		print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
607 
608 		/* Do the same for the logs */
609 		if (num_logs(poolnvroot) > 0) {
610 			print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
611 			print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
612 		} else if (num_logs(nvroot) > 0) {
613 			print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
614 		}
615 
616 		ret = 0;
617 	} else {
618 		ret = (zpool_add(zhp, nvroot) != 0);
619 	}
620 
621 	nvlist_free(nvroot);
622 	zpool_close(zhp);
623 
624 	return (ret);
625 }
626 
627 /*
628  * zpool remove  <pool> <vdev> ...
629  *
630  * Removes the given vdev from the pool.
631  */
632 int
zpool_do_remove(int argc,char ** argv)633 zpool_do_remove(int argc, char **argv)
634 {
635 	char *poolname;
636 	int i, ret = 0;
637 	zpool_handle_t *zhp;
638 	boolean_t stop = B_FALSE;
639 	boolean_t noop = B_FALSE;
640 	boolean_t parsable = B_FALSE;
641 	char c;
642 
643 	/* check options */
644 	while ((c = getopt(argc, argv, "nps")) != -1) {
645 		switch (c) {
646 		case 'n':
647 			noop = B_TRUE;
648 			break;
649 		case 'p':
650 			parsable = B_TRUE;
651 			break;
652 		case 's':
653 			stop = B_TRUE;
654 			break;
655 		case '?':
656 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
657 			    optopt);
658 			usage(B_FALSE);
659 		}
660 	}
661 
662 	argc -= optind;
663 	argv += optind;
664 
665 	/* get pool name and check number of arguments */
666 	if (argc < 1) {
667 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
668 		usage(B_FALSE);
669 	}
670 
671 	poolname = argv[0];
672 
673 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
674 		return (1);
675 
676 	if (stop && noop) {
677 		(void) fprintf(stderr, gettext("stop request ignored\n"));
678 		return (0);
679 	}
680 
681 	if (stop) {
682 		if (argc > 1) {
683 			(void) fprintf(stderr, gettext("too many arguments\n"));
684 			usage(B_FALSE);
685 		}
686 		if (zpool_vdev_remove_cancel(zhp) != 0)
687 			ret = 1;
688 	} else {
689 		if (argc < 2) {
690 			(void) fprintf(stderr, gettext("missing device\n"));
691 			usage(B_FALSE);
692 		}
693 
694 		for (i = 1; i < argc; i++) {
695 			if (noop) {
696 				uint64_t size;
697 
698 				if (zpool_vdev_indirect_size(zhp, argv[i],
699 				    &size) != 0) {
700 					ret = 1;
701 					break;
702 				}
703 				if (parsable) {
704 					(void) printf("%s %llu\n",
705 					    argv[i], size);
706 				} else {
707 					char valstr[32];
708 					zfs_nicenum(size, valstr,
709 					    sizeof (valstr));
710 					(void) printf("Memory that will be "
711 					    "used after removing %s: %s\n",
712 					    argv[i], valstr);
713 				}
714 			} else {
715 				if (zpool_vdev_remove(zhp, argv[i]) != 0)
716 					ret = 1;
717 			}
718 		}
719 	}
720 
721 	return (ret);
722 }
723 
724 /*
725  * zpool labelclear [-f] <vdev>
726  *
727  *	-f	Force clearing the label for the vdevs which are members of
728  *		the exported or foreign pools.
729  *
730  * Verifies that the vdev is not active and zeros out the label information
731  * on the device.
732  */
733 int
zpool_do_labelclear(int argc,char ** argv)734 zpool_do_labelclear(int argc, char **argv)
735 {
736 	char vdev[MAXPATHLEN];
737 	char *name = NULL;
738 	struct stat st;
739 	int c, fd, ret = 0;
740 	nvlist_t *config;
741 	pool_state_t state;
742 	boolean_t inuse = B_FALSE;
743 	boolean_t force = B_FALSE;
744 
745 	/* check options */
746 	while ((c = getopt(argc, argv, "f")) != -1) {
747 		switch (c) {
748 		case 'f':
749 			force = B_TRUE;
750 			break;
751 		default:
752 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
753 			    optopt);
754 			usage(B_FALSE);
755 		}
756 	}
757 
758 	argc -= optind;
759 	argv += optind;
760 
761 	/* get vdev name */
762 	if (argc < 1) {
763 		(void) fprintf(stderr, gettext("missing vdev name\n"));
764 		usage(B_FALSE);
765 	}
766 	if (argc > 1) {
767 		(void) fprintf(stderr, gettext("too many arguments\n"));
768 		usage(B_FALSE);
769 	}
770 
771 	/*
772 	 * Check if we were given absolute path and use it as is.
773 	 * Otherwise if the provided vdev name doesn't point to a file,
774 	 * try prepending dsk path and appending s0.
775 	 */
776 	(void) strlcpy(vdev, argv[0], sizeof (vdev));
777 	if (vdev[0] != '/' && stat(vdev, &st) != 0) {
778 		char *s;
779 
780 		(void) snprintf(vdev, sizeof (vdev), "%s/%s",
781 #ifdef illumos
782 		    ZFS_DISK_ROOT, argv[0]);
783 		if ((s = strrchr(argv[0], 's')) == NULL ||
784 		    !isdigit(*(s + 1)))
785 			(void) strlcat(vdev, "s0", sizeof (vdev));
786 #else
787 		    "/dev", argv[0]);
788 #endif
789 		if (stat(vdev, &st) != 0) {
790 			(void) fprintf(stderr, gettext(
791 			    "failed to find device %s, try specifying absolute "
792 			    "path instead\n"), argv[0]);
793 			return (1);
794 		}
795 	}
796 
797 	if ((fd = open(vdev, O_RDWR)) < 0) {
798 		(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
799 		    vdev, strerror(errno));
800 		return (1);
801 	}
802 
803 	if (zpool_read_label(fd, &config) != 0) {
804 		(void) fprintf(stderr,
805 		    gettext("failed to read label from %s\n"), vdev);
806 		return (1);
807 	}
808 	nvlist_free(config);
809 
810 	ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
811 	if (ret != 0) {
812 		(void) fprintf(stderr,
813 		    gettext("failed to check state for %s\n"), vdev);
814 		return (1);
815 	}
816 
817 	if (!inuse)
818 		goto wipe_label;
819 
820 	switch (state) {
821 	default:
822 	case POOL_STATE_ACTIVE:
823 	case POOL_STATE_SPARE:
824 	case POOL_STATE_L2CACHE:
825 		(void) fprintf(stderr, gettext(
826 		    "%s is a member (%s) of pool \"%s\"\n"),
827 		    vdev, zpool_pool_state_to_name(state), name);
828 		ret = 1;
829 		goto errout;
830 
831 	case POOL_STATE_EXPORTED:
832 		if (force)
833 			break;
834 		(void) fprintf(stderr, gettext(
835 		    "use '-f' to override the following error:\n"
836 		    "%s is a member of exported pool \"%s\"\n"),
837 		    vdev, name);
838 		ret = 1;
839 		goto errout;
840 
841 	case POOL_STATE_POTENTIALLY_ACTIVE:
842 		if (force)
843 			break;
844 		(void) fprintf(stderr, gettext(
845 		    "use '-f' to override the following error:\n"
846 		    "%s is a member of potentially active pool \"%s\"\n"),
847 		    vdev, name);
848 		ret = 1;
849 		goto errout;
850 
851 	case POOL_STATE_DESTROYED:
852 		/* inuse should never be set for a destroyed pool */
853 		assert(0);
854 		break;
855 	}
856 
857 wipe_label:
858 	ret = zpool_clear_label(fd);
859 	if (ret != 0) {
860 		(void) fprintf(stderr,
861 		    gettext("failed to clear label for %s\n"), vdev);
862 	}
863 
864 errout:
865 	free(name);
866 	(void) close(fd);
867 
868 	return (ret);
869 }
870 
871 /*
872  * zpool create [-fnd] [-B] [-o property=value] ...
873  *		[-O file-system-property=value] ...
874  *		[-R root] [-m mountpoint] [-t tempname] <pool> <dev> ...
875  *
876  *	-B	Create boot partition.
877  *	-f	Force creation, even if devices appear in use
878  *	-n	Do not create the pool, but display the resulting layout if it
879  *		were to be created.
880  *	-R	Create a pool under an alternate root
881  *	-m	Set default mountpoint for the root dataset.  By default it's
882  *		'/<pool>'
883  *	-t	Use the temporary name until the pool is exported.
884  *	-o	Set property=value.
885  *	-d	Don't automatically enable all supported pool features
886  *		(individual features can be enabled with -o).
887  *	-O	Set fsproperty=value in the pool's root file system
888  *
889  * Creates the named pool according to the given vdev specification.  The
890  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
891  * we get the nvlist back from get_vdev_spec(), we either print out the contents
892  * (if '-n' was specified), or pass it to libzfs to do the creation.
893  */
894 
895 #define	SYSTEM256	(256 * 1024 * 1024)
896 int
zpool_do_create(int argc,char ** argv)897 zpool_do_create(int argc, char **argv)
898 {
899 	boolean_t force = B_FALSE;
900 	boolean_t dryrun = B_FALSE;
901 	boolean_t enable_all_pool_feat = B_TRUE;
902 	zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
903 	uint64_t boot_size = 0;
904 	int c;
905 	nvlist_t *nvroot = NULL;
906 	char *poolname;
907 	char *tname = NULL;
908 	int ret = 1;
909 	char *altroot = NULL;
910 	char *mountpoint = NULL;
911 	nvlist_t *fsprops = NULL;
912 	nvlist_t *props = NULL;
913 	char *propval;
914 
915 	/* check options */
916 	while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) {
917 		switch (c) {
918 		case 'f':
919 			force = B_TRUE;
920 			break;
921 		case 'n':
922 			dryrun = B_TRUE;
923 			break;
924 		case 'd':
925 			enable_all_pool_feat = B_FALSE;
926 			break;
927 		case 'B':
928 #ifdef illumos
929 			/*
930 			 * We should create the system partition.
931 			 * Also make sure the size is set.
932 			 */
933 			boot_type = ZPOOL_CREATE_BOOT_LABEL;
934 			if (boot_size == 0)
935 				boot_size = SYSTEM256;
936 			break;
937 #else
938 			(void) fprintf(stderr,
939 			    gettext("option '%c' is not supported\n"),
940 			    optopt);
941 			goto badusage;
942 #endif
943 		case 'R':
944 			altroot = optarg;
945 			if (add_prop_list(zpool_prop_to_name(
946 			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
947 				goto errout;
948 			if (add_prop_list_default(zpool_prop_to_name(
949 			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
950 				goto errout;
951 			break;
952 		case 'm':
953 			/* Equivalent to -O mountpoint=optarg */
954 			mountpoint = optarg;
955 			break;
956 		case 'o':
957 			if ((propval = strchr(optarg, '=')) == NULL) {
958 				(void) fprintf(stderr, gettext("missing "
959 				    "'=' for -o option\n"));
960 				goto errout;
961 			}
962 			*propval = '\0';
963 			propval++;
964 
965 			if (add_prop_list(optarg, propval, &props, B_TRUE))
966 				goto errout;
967 
968 			/*
969 			 * Get bootsize value for make_root_vdev().
970 			 */
971 			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
972 				if (zfs_nicestrtonum(g_zfs, propval,
973 				    &boot_size) < 0 || boot_size == 0) {
974 					(void) fprintf(stderr,
975 					    gettext("bad boot partition size "
976 					    "'%s': %s\n"),  propval,
977 					    libzfs_error_description(g_zfs));
978 					goto errout;
979 				}
980 			}
981 
982 			/*
983 			 * If the user is creating a pool that doesn't support
984 			 * feature flags, don't enable any features.
985 			 */
986 			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
987 				char *end;
988 				u_longlong_t ver;
989 
990 				ver = strtoull(propval, &end, 10);
991 				if (*end == '\0' &&
992 				    ver < SPA_VERSION_FEATURES) {
993 					enable_all_pool_feat = B_FALSE;
994 				}
995 			}
996 			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
997 				altroot = propval;
998 			break;
999 		case 'O':
1000 			if ((propval = strchr(optarg, '=')) == NULL) {
1001 				(void) fprintf(stderr, gettext("missing "
1002 				    "'=' for -O option\n"));
1003 				goto errout;
1004 			}
1005 			*propval = '\0';
1006 			propval++;
1007 
1008 			/*
1009 			 * Mountpoints are checked and then added later.
1010 			 * Uniquely among properties, they can be specified
1011 			 * more than once, to avoid conflict with -m.
1012 			 */
1013 			if (0 == strcmp(optarg,
1014 			    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1015 				mountpoint = propval;
1016 			} else if (add_prop_list(optarg, propval, &fsprops,
1017 			    B_FALSE)) {
1018 				goto errout;
1019 			}
1020 			break;
1021 		case 't':
1022 			/*
1023 			 * Sanity check temporary pool name.
1024 			 */
1025 			if (strchr(optarg, '/') != NULL) {
1026 				(void) fprintf(stderr, gettext("cannot create "
1027 				    "'%s': invalid character '/' in temporary "
1028 				    "name\n"), optarg);
1029 				(void) fprintf(stderr, gettext("use 'zfs "
1030 				    "create' to create a dataset\n"));
1031 				goto errout;
1032 			}
1033 
1034 			if (add_prop_list(zpool_prop_to_name(
1035 			    ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1036 				goto errout;
1037 			if (add_prop_list_default(zpool_prop_to_name(
1038 			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1039 				goto errout;
1040 			tname = optarg;
1041 			break;
1042 		case ':':
1043 			(void) fprintf(stderr, gettext("missing argument for "
1044 			    "'%c' option\n"), optopt);
1045 			goto badusage;
1046 		case '?':
1047 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1048 			    optopt);
1049 			goto badusage;
1050 		}
1051 	}
1052 
1053 	argc -= optind;
1054 	argv += optind;
1055 
1056 	/* get pool name and check number of arguments */
1057 	if (argc < 1) {
1058 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
1059 		goto badusage;
1060 	}
1061 	if (argc < 2) {
1062 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
1063 		goto badusage;
1064 	}
1065 
1066 	poolname = argv[0];
1067 
1068 	/*
1069 	 * As a special case, check for use of '/' in the name, and direct the
1070 	 * user to use 'zfs create' instead.
1071 	 */
1072 	if (strchr(poolname, '/') != NULL) {
1073 		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
1074 		    "character '/' in pool name\n"), poolname);
1075 		(void) fprintf(stderr, gettext("use 'zfs create' to "
1076 		    "create a dataset\n"));
1077 		goto errout;
1078 	}
1079 
1080 	/*
1081 	 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1082 	 * and not set otherwise.
1083 	 */
1084 	if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1085 		const char *propname;
1086 		char *strptr, *buf = NULL;
1087 		int rv;
1088 
1089 		propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1090 		if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1091 			(void) asprintf(&buf, "%" PRIu64, boot_size);
1092 			if (buf == NULL) {
1093 				(void) fprintf(stderr,
1094 				    gettext("internal error: out of memory\n"));
1095 				goto errout;
1096 			}
1097 			rv = add_prop_list(propname, buf, &props, B_TRUE);
1098 			free(buf);
1099 			if (rv != 0)
1100 				goto errout;
1101 		}
1102 	} else {
1103 		const char *propname;
1104 		char *strptr;
1105 
1106 		propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1107 		if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1108 			(void) fprintf(stderr, gettext("error: setting boot "
1109 			    "partition size requires option '-B'\n"));
1110 			goto errout;
1111 		}
1112 	}
1113 
1114 	/* pass off to get_vdev_spec for bulk processing */
1115 	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1116 	    boot_type, boot_size, argc - 1, argv + 1);
1117 	if (nvroot == NULL)
1118 		goto errout;
1119 
1120 	/* make_root_vdev() allows 0 toplevel children if there are spares */
1121 	if (!zfs_allocatable_devs(nvroot)) {
1122 		(void) fprintf(stderr, gettext("invalid vdev "
1123 		    "specification: at least one toplevel vdev must be "
1124 		    "specified\n"));
1125 		goto errout;
1126 	}
1127 
1128 	if (altroot != NULL && altroot[0] != '/') {
1129 		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
1130 		    "must be an absolute path\n"), altroot);
1131 		goto errout;
1132 	}
1133 
1134 	/*
1135 	 * Check the validity of the mountpoint and direct the user to use the
1136 	 * '-m' mountpoint option if it looks like its in use.
1137 	 * Ignore the checks if the '-f' option is given.
1138 	 */
1139 	if (!force && (mountpoint == NULL ||
1140 	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1141 	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) {
1142 		char buf[MAXPATHLEN];
1143 		DIR *dirp;
1144 
1145 		if (mountpoint && mountpoint[0] != '/') {
1146 			(void) fprintf(stderr, gettext("invalid mountpoint "
1147 			    "'%s': must be an absolute path, 'legacy', or "
1148 			    "'none'\n"), mountpoint);
1149 			goto errout;
1150 		}
1151 
1152 		if (mountpoint == NULL) {
1153 			if (altroot != NULL)
1154 				(void) snprintf(buf, sizeof (buf), "%s/%s",
1155 				    altroot, poolname);
1156 			else
1157 				(void) snprintf(buf, sizeof (buf), "/%s",
1158 				    poolname);
1159 		} else {
1160 			if (altroot != NULL)
1161 				(void) snprintf(buf, sizeof (buf), "%s%s",
1162 				    altroot, mountpoint);
1163 			else
1164 				(void) snprintf(buf, sizeof (buf), "%s",
1165 				    mountpoint);
1166 		}
1167 
1168 		if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1169 			(void) fprintf(stderr, gettext("mountpoint '%s' : "
1170 			    "%s\n"), buf, strerror(errno));
1171 			(void) fprintf(stderr, gettext("use '-m' "
1172 			    "option to provide a different default\n"));
1173 			goto errout;
1174 		} else if (dirp) {
1175 			int count = 0;
1176 
1177 			while (count < 3 && readdir(dirp) != NULL)
1178 				count++;
1179 			(void) closedir(dirp);
1180 
1181 			if (count > 2) {
1182 				(void) fprintf(stderr, gettext("mountpoint "
1183 				    "'%s' exists and is not empty\n"), buf);
1184 				(void) fprintf(stderr, gettext("use '-m' "
1185 				    "option to provide a "
1186 				    "different default\n"));
1187 				goto errout;
1188 			}
1189 		}
1190 	}
1191 
1192 	/*
1193 	 * Now that the mountpoint's validity has been checked, ensure that
1194 	 * the property is set appropriately prior to creating the pool.
1195 	 */
1196 	if (mountpoint != NULL) {
1197 		ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1198 		    mountpoint, &fsprops, B_FALSE);
1199 		if (ret != 0)
1200 			goto errout;
1201 	}
1202 
1203 	ret = 1;
1204 	if (dryrun) {
1205 		/*
1206 		 * For a dry run invocation, print out a basic message and run
1207 		 * through all the vdevs in the list and print out in an
1208 		 * appropriate hierarchy.
1209 		 */
1210 		(void) printf(gettext("would create '%s' with the "
1211 		    "following layout:\n\n"), poolname);
1212 
1213 		print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1214 		if (num_logs(nvroot) > 0)
1215 			print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1216 
1217 		ret = 0;
1218 	} else {
1219 		/*
1220 		 * Hand off to libzfs.
1221 		 */
1222 		if (enable_all_pool_feat) {
1223 			spa_feature_t i;
1224 			for (i = 0; i < SPA_FEATURES; i++) {
1225 				char propname[MAXPATHLEN];
1226 				zfeature_info_t *feat = &spa_feature_table[i];
1227 
1228 				(void) snprintf(propname, sizeof (propname),
1229 				    "feature@%s", feat->fi_uname);
1230 
1231 				/*
1232 				 * Skip feature if user specified it manually
1233 				 * on the command line.
1234 				 */
1235 				if (nvlist_exists(props, propname))
1236 					continue;
1237 
1238 				ret = add_prop_list(propname,
1239 				    ZFS_FEATURE_ENABLED, &props, B_TRUE);
1240 				if (ret != 0)
1241 					goto errout;
1242 			}
1243 		}
1244 
1245 		ret = 1;
1246 		if (zpool_create(g_zfs, poolname,
1247 		    nvroot, props, fsprops) == 0) {
1248 			zfs_handle_t *pool = zfs_open(g_zfs,
1249 			    tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1250 			if (pool != NULL) {
1251 				if (zfs_mount(pool, NULL, 0) == 0)
1252 					ret = zfs_shareall(pool);
1253 				zfs_close(pool);
1254 			}
1255 		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1256 			(void) fprintf(stderr, gettext("pool name may have "
1257 			    "been omitted\n"));
1258 		}
1259 	}
1260 
1261 errout:
1262 	nvlist_free(nvroot);
1263 	nvlist_free(fsprops);
1264 	nvlist_free(props);
1265 	return (ret);
1266 badusage:
1267 	nvlist_free(fsprops);
1268 	nvlist_free(props);
1269 	usage(B_FALSE);
1270 	return (2);
1271 }
1272 
1273 /*
1274  * zpool destroy <pool>
1275  *
1276  *	-f	Forcefully unmount any datasets
1277  *
1278  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
1279  */
1280 int
zpool_do_destroy(int argc,char ** argv)1281 zpool_do_destroy(int argc, char **argv)
1282 {
1283 	boolean_t force = B_FALSE;
1284 	int c;
1285 	char *pool;
1286 	zpool_handle_t *zhp;
1287 	int ret;
1288 
1289 	/* check options */
1290 	while ((c = getopt(argc, argv, "f")) != -1) {
1291 		switch (c) {
1292 		case 'f':
1293 			force = B_TRUE;
1294 			break;
1295 		case '?':
1296 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1297 			    optopt);
1298 			usage(B_FALSE);
1299 		}
1300 	}
1301 
1302 	argc -= optind;
1303 	argv += optind;
1304 
1305 	/* check arguments */
1306 	if (argc < 1) {
1307 		(void) fprintf(stderr, gettext("missing pool argument\n"));
1308 		usage(B_FALSE);
1309 	}
1310 	if (argc > 1) {
1311 		(void) fprintf(stderr, gettext("too many arguments\n"));
1312 		usage(B_FALSE);
1313 	}
1314 
1315 	pool = argv[0];
1316 
1317 	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1318 		/*
1319 		 * As a special case, check for use of '/' in the name, and
1320 		 * direct the user to use 'zfs destroy' instead.
1321 		 */
1322 		if (strchr(pool, '/') != NULL)
1323 			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
1324 			    "destroy a dataset\n"));
1325 		return (1);
1326 	}
1327 
1328 	if (zpool_disable_datasets(zhp, force) != 0) {
1329 		(void) fprintf(stderr, gettext("could not destroy '%s': "
1330 		    "could not unmount datasets\n"), zpool_get_name(zhp));
1331 		return (1);
1332 	}
1333 
1334 	/* The history must be logged as part of the export */
1335 	log_history = B_FALSE;
1336 
1337 	ret = (zpool_destroy(zhp, history_str) != 0);
1338 
1339 	zpool_close(zhp);
1340 
1341 	return (ret);
1342 }
1343 
1344 /*
1345  * zpool export [-f] <pool> ...
1346  *
1347  *	-f	Forcefully unmount datasets
1348  *
1349  * Export the given pools.  By default, the command will attempt to cleanly
1350  * unmount any active datasets within the pool.  If the '-f' flag is specified,
1351  * then the datasets will be forcefully unmounted.
1352  */
1353 int
zpool_do_export(int argc,char ** argv)1354 zpool_do_export(int argc, char **argv)
1355 {
1356 	boolean_t force = B_FALSE;
1357 	boolean_t hardforce = B_FALSE;
1358 	int c;
1359 	zpool_handle_t *zhp;
1360 	int ret;
1361 	int i;
1362 
1363 	/* check options */
1364 	while ((c = getopt(argc, argv, "fF")) != -1) {
1365 		switch (c) {
1366 		case 'f':
1367 			force = B_TRUE;
1368 			break;
1369 		case 'F':
1370 			hardforce = B_TRUE;
1371 			break;
1372 		case '?':
1373 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1374 			    optopt);
1375 			usage(B_FALSE);
1376 		}
1377 	}
1378 
1379 	argc -= optind;
1380 	argv += optind;
1381 
1382 	/* check arguments */
1383 	if (argc < 1) {
1384 		(void) fprintf(stderr, gettext("missing pool argument\n"));
1385 		usage(B_FALSE);
1386 	}
1387 
1388 	ret = 0;
1389 	for (i = 0; i < argc; i++) {
1390 		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1391 			ret = 1;
1392 			continue;
1393 		}
1394 
1395 		if (zpool_disable_datasets(zhp, force) != 0) {
1396 			ret = 1;
1397 			zpool_close(zhp);
1398 			continue;
1399 		}
1400 
1401 		/* The history must be logged as part of the export */
1402 		log_history = B_FALSE;
1403 
1404 		if (hardforce) {
1405 			if (zpool_export_force(zhp, history_str) != 0)
1406 				ret = 1;
1407 		} else if (zpool_export(zhp, force, history_str) != 0) {
1408 			ret = 1;
1409 		}
1410 
1411 		zpool_close(zhp);
1412 	}
1413 
1414 	return (ret);
1415 }
1416 
1417 /*
1418  * Given a vdev configuration, determine the maximum width needed for the device
1419  * name column.
1420  */
1421 static int
max_width(zpool_handle_t * zhp,nvlist_t * nv,int depth,int max)1422 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1423 {
1424 	char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1425 	nvlist_t **child;
1426 	uint_t c, children;
1427 	int ret;
1428 
1429 	if (strlen(name) + depth > max)
1430 		max = strlen(name) + depth;
1431 
1432 	free(name);
1433 
1434 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1435 	    &child, &children) == 0) {
1436 		for (c = 0; c < children; c++)
1437 			if ((ret = max_width(zhp, child[c], depth + 2,
1438 			    max)) > max)
1439 				max = ret;
1440 	}
1441 
1442 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1443 	    &child, &children) == 0) {
1444 		for (c = 0; c < children; c++)
1445 			if ((ret = max_width(zhp, child[c], depth + 2,
1446 			    max)) > max)
1447 				max = ret;
1448 	}
1449 
1450 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1451 	    &child, &children) == 0) {
1452 		for (c = 0; c < children; c++)
1453 			if ((ret = max_width(zhp, child[c], depth + 2,
1454 			    max)) > max)
1455 				max = ret;
1456 	}
1457 
1458 
1459 	return (max);
1460 }
1461 
1462 typedef struct spare_cbdata {
1463 	uint64_t	cb_guid;
1464 	zpool_handle_t	*cb_zhp;
1465 } spare_cbdata_t;
1466 
1467 static boolean_t
find_vdev(nvlist_t * nv,uint64_t search)1468 find_vdev(nvlist_t *nv, uint64_t search)
1469 {
1470 	uint64_t guid;
1471 	nvlist_t **child;
1472 	uint_t c, children;
1473 
1474 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1475 	    search == guid)
1476 		return (B_TRUE);
1477 
1478 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1479 	    &child, &children) == 0) {
1480 		for (c = 0; c < children; c++)
1481 			if (find_vdev(child[c], search))
1482 				return (B_TRUE);
1483 	}
1484 
1485 	return (B_FALSE);
1486 }
1487 
1488 static int
find_spare(zpool_handle_t * zhp,void * data)1489 find_spare(zpool_handle_t *zhp, void *data)
1490 {
1491 	spare_cbdata_t *cbp = data;
1492 	nvlist_t *config, *nvroot;
1493 
1494 	config = zpool_get_config(zhp, NULL);
1495 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1496 	    &nvroot) == 0);
1497 
1498 	if (find_vdev(nvroot, cbp->cb_guid)) {
1499 		cbp->cb_zhp = zhp;
1500 		return (1);
1501 	}
1502 
1503 	zpool_close(zhp);
1504 	return (0);
1505 }
1506 
1507 /*
1508  * Print out configuration state as requested by status_callback.
1509  */
1510 void
print_status_config(zpool_handle_t * zhp,const char * name,nvlist_t * nv,int namewidth,int depth,boolean_t isspare)1511 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1512     int namewidth, int depth, boolean_t isspare)
1513 {
1514 	nvlist_t **child;
1515 	uint_t c, vsc, children;
1516 	pool_scan_stat_t *ps = NULL;
1517 	vdev_stat_t *vs;
1518 	char rbuf[6], wbuf[6], cbuf[6];
1519 	char *vname;
1520 	uint64_t notpresent;
1521 	uint64_t ashift;
1522 	spare_cbdata_t cb;
1523 	const char *state;
1524 	char *type;
1525 
1526 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1527 	    &child, &children) != 0)
1528 		children = 0;
1529 
1530 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1531 	    (uint64_t **)&vs, &vsc) == 0);
1532 
1533 	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1534 
1535 	if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1536 		return;
1537 
1538 	state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1539 	if (isspare) {
1540 		/*
1541 		 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1542 		 * online drives.
1543 		 */
1544 		if (vs->vs_aux == VDEV_AUX_SPARED)
1545 			state = "INUSE";
1546 		else if (vs->vs_state == VDEV_STATE_HEALTHY)
1547 			state = "AVAIL";
1548 	}
1549 
1550 	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1551 	    name, state);
1552 
1553 	if (!isspare) {
1554 		zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1555 		zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1556 		zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1557 		(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1558 	}
1559 
1560 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1561 	    &notpresent) == 0 ||
1562 	    vs->vs_state <= VDEV_STATE_CANT_OPEN) {
1563 		char *path;
1564 		if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0)
1565 			(void) printf("  was %s", path);
1566 	} else if (vs->vs_aux != 0) {
1567 		(void) printf("  ");
1568 
1569 		switch (vs->vs_aux) {
1570 		case VDEV_AUX_OPEN_FAILED:
1571 			(void) printf(gettext("cannot open"));
1572 			break;
1573 
1574 		case VDEV_AUX_BAD_GUID_SUM:
1575 			(void) printf(gettext("missing device"));
1576 			break;
1577 
1578 		case VDEV_AUX_NO_REPLICAS:
1579 			(void) printf(gettext("insufficient replicas"));
1580 			break;
1581 
1582 		case VDEV_AUX_VERSION_NEWER:
1583 			(void) printf(gettext("newer version"));
1584 			break;
1585 
1586 		case VDEV_AUX_UNSUP_FEAT:
1587 			(void) printf(gettext("unsupported feature(s)"));
1588 			break;
1589 
1590 		case VDEV_AUX_ASHIFT_TOO_BIG:
1591 			(void) printf(gettext("unsupported minimum blocksize"));
1592 			break;
1593 
1594 		case VDEV_AUX_SPARED:
1595 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1596 			    &cb.cb_guid) == 0);
1597 			if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1598 				if (strcmp(zpool_get_name(cb.cb_zhp),
1599 				    zpool_get_name(zhp)) == 0)
1600 					(void) printf(gettext("currently in "
1601 					    "use"));
1602 				else
1603 					(void) printf(gettext("in use by "
1604 					    "pool '%s'"),
1605 					    zpool_get_name(cb.cb_zhp));
1606 				zpool_close(cb.cb_zhp);
1607 			} else {
1608 				(void) printf(gettext("currently in use"));
1609 			}
1610 			break;
1611 
1612 		case VDEV_AUX_ERR_EXCEEDED:
1613 			(void) printf(gettext("too many errors"));
1614 			break;
1615 
1616 		case VDEV_AUX_IO_FAILURE:
1617 			(void) printf(gettext("experienced I/O failures"));
1618 			break;
1619 
1620 		case VDEV_AUX_BAD_LOG:
1621 			(void) printf(gettext("bad intent log"));
1622 			break;
1623 
1624 		case VDEV_AUX_EXTERNAL:
1625 			(void) printf(gettext("external device fault"));
1626 			break;
1627 
1628 		case VDEV_AUX_SPLIT_POOL:
1629 			(void) printf(gettext("split into new pool"));
1630 			break;
1631 
1632 		case VDEV_AUX_CHILDREN_OFFLINE:
1633 			(void) printf(gettext("all children offline"));
1634 			break;
1635 
1636 		default:
1637 			(void) printf(gettext("corrupted data"));
1638 			break;
1639 		}
1640 	} else if (children == 0 && !isspare &&
1641 	    VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
1642 	    vs->vs_configured_ashift < vs->vs_physical_ashift) {
1643 		(void) printf(
1644 		    gettext("  block size: %dB configured, %dB native"),
1645 		    1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
1646 	}
1647 
1648 	(void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1649 	    (uint64_t **)&ps, &c);
1650 
1651 	if (ps != NULL && ps->pss_state == DSS_SCANNING &&
1652 	    vs->vs_scan_processed != 0 && children == 0) {
1653 		(void) printf(gettext("  (%s)"),
1654 		    (ps->pss_func == POOL_SCAN_RESILVER) ?
1655 		    "resilvering" : "repairing");
1656 	}
1657 
1658 	if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
1659 	    vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
1660 	    vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
1661 	    !vs->vs_scan_removing) {
1662 		char zbuf[1024];
1663 		char tbuf[256];
1664 		struct tm zaction_ts;
1665 
1666 		time_t t = vs->vs_initialize_action_time;
1667 		int initialize_pct = 100;
1668 		if (vs->vs_initialize_state != VDEV_INITIALIZE_COMPLETE) {
1669 			initialize_pct = (vs->vs_initialize_bytes_done * 100 /
1670 			    (vs->vs_initialize_bytes_est + 1));
1671 		}
1672 
1673 		(void) localtime_r(&t, &zaction_ts);
1674 		(void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1675 
1676 		switch (vs->vs_initialize_state) {
1677 		case VDEV_INITIALIZE_SUSPENDED:
1678 			(void) snprintf(zbuf, sizeof (zbuf),
1679 			    ", suspended, started at %s", tbuf);
1680 			break;
1681 		case VDEV_INITIALIZE_ACTIVE:
1682 			(void) snprintf(zbuf, sizeof (zbuf),
1683 			    ", started at %s", tbuf);
1684 			break;
1685 		case VDEV_INITIALIZE_COMPLETE:
1686 			(void) snprintf(zbuf, sizeof (zbuf),
1687 			    ", completed at %s", tbuf);
1688 			break;
1689 		}
1690 
1691 		(void) printf(gettext("  (%d%% initialized%s)"),
1692 		    initialize_pct, zbuf);
1693 	}
1694 
1695 	(void) printf("\n");
1696 
1697 	for (c = 0; c < children; c++) {
1698 		uint64_t islog = B_FALSE, ishole = B_FALSE;
1699 
1700 		/* Don't print logs or holes here */
1701 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1702 		    &islog);
1703 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1704 		    &ishole);
1705 		if (islog || ishole)
1706 			continue;
1707 		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1708 		print_status_config(zhp, vname, child[c],
1709 		    namewidth, depth + 2, isspare);
1710 		free(vname);
1711 	}
1712 }
1713 
1714 
1715 /*
1716  * Print the configuration of an exported pool.  Iterate over all vdevs in the
1717  * pool, printing out the name and status for each one.
1718  */
1719 void
print_import_config(const char * name,nvlist_t * nv,int namewidth,int depth)1720 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1721 {
1722 	nvlist_t **child;
1723 	uint_t c, children;
1724 	vdev_stat_t *vs;
1725 	char *type, *vname;
1726 
1727 	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1728 	if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1729 	    strcmp(type, VDEV_TYPE_HOLE) == 0)
1730 		return;
1731 
1732 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1733 	    (uint64_t **)&vs, &c) == 0);
1734 
1735 	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1736 	(void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1737 
1738 	if (vs->vs_aux != 0) {
1739 		(void) printf("  ");
1740 
1741 		switch (vs->vs_aux) {
1742 		case VDEV_AUX_OPEN_FAILED:
1743 			(void) printf(gettext("cannot open"));
1744 			break;
1745 
1746 		case VDEV_AUX_BAD_GUID_SUM:
1747 			(void) printf(gettext("missing device"));
1748 			break;
1749 
1750 		case VDEV_AUX_NO_REPLICAS:
1751 			(void) printf(gettext("insufficient replicas"));
1752 			break;
1753 
1754 		case VDEV_AUX_VERSION_NEWER:
1755 			(void) printf(gettext("newer version"));
1756 			break;
1757 
1758 		case VDEV_AUX_UNSUP_FEAT:
1759 			(void) printf(gettext("unsupported feature(s)"));
1760 			break;
1761 
1762 		case VDEV_AUX_ERR_EXCEEDED:
1763 			(void) printf(gettext("too many errors"));
1764 			break;
1765 
1766 		case VDEV_AUX_CHILDREN_OFFLINE:
1767 			(void) printf(gettext("all children offline"));
1768 			break;
1769 
1770 		default:
1771 			(void) printf(gettext("corrupted data"));
1772 			break;
1773 		}
1774 	}
1775 	(void) printf("\n");
1776 
1777 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1778 	    &child, &children) != 0)
1779 		return;
1780 
1781 	for (c = 0; c < children; c++) {
1782 		uint64_t is_log = B_FALSE;
1783 
1784 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1785 		    &is_log);
1786 		if (is_log)
1787 			continue;
1788 
1789 		vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1790 		print_import_config(vname, child[c], namewidth, depth + 2);
1791 		free(vname);
1792 	}
1793 
1794 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1795 	    &child, &children) == 0) {
1796 		(void) printf(gettext("\tcache\n"));
1797 		for (c = 0; c < children; c++) {
1798 			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1799 			(void) printf("\t  %s\n", vname);
1800 			free(vname);
1801 		}
1802 	}
1803 
1804 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1805 	    &child, &children) == 0) {
1806 		(void) printf(gettext("\tspares\n"));
1807 		for (c = 0; c < children; c++) {
1808 			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1809 			(void) printf("\t  %s\n", vname);
1810 			free(vname);
1811 		}
1812 	}
1813 }
1814 
1815 /*
1816  * Print log vdevs.
1817  * Logs are recorded as top level vdevs in the main pool child array
1818  * but with "is_log" set to 1. We use either print_status_config() or
1819  * print_import_config() to print the top level logs then any log
1820  * children (eg mirrored slogs) are printed recursively - which
1821  * works because only the top level vdev is marked "is_log"
1822  */
1823 static void
print_logs(zpool_handle_t * zhp,nvlist_t * nv,int namewidth,boolean_t verbose)1824 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1825 {
1826 	uint_t c, children;
1827 	nvlist_t **child;
1828 
1829 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1830 	    &children) != 0)
1831 		return;
1832 
1833 	(void) printf(gettext("\tlogs\n"));
1834 
1835 	for (c = 0; c < children; c++) {
1836 		uint64_t is_log = B_FALSE;
1837 		char *name;
1838 
1839 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1840 		    &is_log);
1841 		if (!is_log)
1842 			continue;
1843 		name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1844 		if (verbose)
1845 			print_status_config(zhp, name, child[c], namewidth,
1846 			    2, B_FALSE);
1847 		else
1848 			print_import_config(name, child[c], namewidth, 2);
1849 		free(name);
1850 	}
1851 }
1852 
1853 /*
1854  * Display the status for the given pool.
1855  */
1856 static void
show_import(nvlist_t * config)1857 show_import(nvlist_t *config)
1858 {
1859 	uint64_t pool_state;
1860 	vdev_stat_t *vs;
1861 	char *name;
1862 	uint64_t guid;
1863 	char *msgid;
1864 	nvlist_t *nvroot;
1865 	int reason;
1866 	const char *health;
1867 	uint_t vsc;
1868 	int namewidth;
1869 	char *comment;
1870 
1871 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1872 	    &name) == 0);
1873 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1874 	    &guid) == 0);
1875 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1876 	    &pool_state) == 0);
1877 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1878 	    &nvroot) == 0);
1879 
1880 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1881 	    (uint64_t **)&vs, &vsc) == 0);
1882 	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1883 
1884 	reason = zpool_import_status(config, &msgid);
1885 
1886 	(void) printf(gettext("   pool: %s\n"), name);
1887 	(void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
1888 	(void) printf(gettext("  state: %s"), health);
1889 	if (pool_state == POOL_STATE_DESTROYED)
1890 		(void) printf(gettext(" (DESTROYED)"));
1891 	(void) printf("\n");
1892 
1893 	switch (reason) {
1894 	case ZPOOL_STATUS_MISSING_DEV_R:
1895 	case ZPOOL_STATUS_MISSING_DEV_NR:
1896 	case ZPOOL_STATUS_BAD_GUID_SUM:
1897 		(void) printf(gettext(" status: One or more devices are "
1898 		    "missing from the system.\n"));
1899 		break;
1900 
1901 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
1902 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1903 		(void) printf(gettext(" status: One or more devices contains "
1904 		    "corrupted data.\n"));
1905 		break;
1906 
1907 	case ZPOOL_STATUS_CORRUPT_DATA:
1908 		(void) printf(
1909 		    gettext(" status: The pool data is corrupted.\n"));
1910 		break;
1911 
1912 	case ZPOOL_STATUS_OFFLINE_DEV:
1913 		(void) printf(gettext(" status: One or more devices "
1914 		    "are offlined.\n"));
1915 		break;
1916 
1917 	case ZPOOL_STATUS_CORRUPT_POOL:
1918 		(void) printf(gettext(" status: The pool metadata is "
1919 		    "corrupted.\n"));
1920 		break;
1921 
1922 	case ZPOOL_STATUS_VERSION_OLDER:
1923 		(void) printf(gettext(" status: The pool is formatted using a "
1924 		    "legacy on-disk version.\n"));
1925 		break;
1926 
1927 	case ZPOOL_STATUS_VERSION_NEWER:
1928 		(void) printf(gettext(" status: The pool is formatted using an "
1929 		    "incompatible version.\n"));
1930 		break;
1931 
1932 	case ZPOOL_STATUS_FEAT_DISABLED:
1933 		(void) printf(gettext(" status: Some supported features are "
1934 		    "not enabled on the pool.\n"));
1935 		break;
1936 
1937 	case ZPOOL_STATUS_UNSUP_FEAT_READ:
1938 		(void) printf(gettext("status: The pool uses the following "
1939 		    "feature(s) not supported on this system:\n"));
1940 		zpool_print_unsup_feat(config);
1941 		break;
1942 
1943 	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1944 		(void) printf(gettext("status: The pool can only be accessed "
1945 		    "in read-only mode on this system. It\n\tcannot be "
1946 		    "accessed in read-write mode because it uses the "
1947 		    "following\n\tfeature(s) not supported on this system:\n"));
1948 		zpool_print_unsup_feat(config);
1949 		break;
1950 
1951 	case ZPOOL_STATUS_HOSTID_MISMATCH:
1952 		(void) printf(gettext(" status: The pool was last accessed by "
1953 		    "another system.\n"));
1954 		break;
1955 
1956 	case ZPOOL_STATUS_FAULTED_DEV_R:
1957 	case ZPOOL_STATUS_FAULTED_DEV_NR:
1958 		(void) printf(gettext(" status: One or more devices are "
1959 		    "faulted.\n"));
1960 		break;
1961 
1962 	case ZPOOL_STATUS_BAD_LOG:
1963 		(void) printf(gettext(" status: An intent log record cannot be "
1964 		    "read.\n"));
1965 		break;
1966 
1967 	case ZPOOL_STATUS_RESILVERING:
1968 		(void) printf(gettext(" status: One or more devices were being "
1969 		    "resilvered.\n"));
1970 		break;
1971 
1972 	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
1973 		(void) printf(gettext("status: One or more devices were "
1974 		    "configured to use a non-native block size.\n"
1975 		    "\tExpect reduced performance.\n"));
1976 		break;
1977 
1978 	default:
1979 		/*
1980 		 * No other status can be seen when importing pools.
1981 		 */
1982 		assert(reason == ZPOOL_STATUS_OK);
1983 	}
1984 
1985 	/*
1986 	 * Print out an action according to the overall state of the pool.
1987 	 */
1988 	if (vs->vs_state == VDEV_STATE_HEALTHY) {
1989 		if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1990 		    reason == ZPOOL_STATUS_FEAT_DISABLED) {
1991 			(void) printf(gettext(" action: The pool can be "
1992 			    "imported using its name or numeric identifier, "
1993 			    "though\n\tsome features will not be available "
1994 			    "without an explicit 'zpool upgrade'.\n"));
1995 		} else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1996 			(void) printf(gettext(" action: The pool can be "
1997 			    "imported using its name or numeric "
1998 			    "identifier and\n\tthe '-f' flag.\n"));
1999 		} else {
2000 			(void) printf(gettext(" action: The pool can be "
2001 			    "imported using its name or numeric "
2002 			    "identifier.\n"));
2003 		}
2004 	} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2005 		(void) printf(gettext(" action: The pool can be imported "
2006 		    "despite missing or damaged devices.  The\n\tfault "
2007 		    "tolerance of the pool may be compromised if imported.\n"));
2008 	} else {
2009 		switch (reason) {
2010 		case ZPOOL_STATUS_VERSION_NEWER:
2011 			(void) printf(gettext(" action: The pool cannot be "
2012 			    "imported.  Access the pool on a system running "
2013 			    "newer\n\tsoftware, or recreate the pool from "
2014 			    "backup.\n"));
2015 			break;
2016 		case ZPOOL_STATUS_UNSUP_FEAT_READ:
2017 			(void) printf(gettext("action: The pool cannot be "
2018 			    "imported. Access the pool on a system that "
2019 			    "supports\n\tthe required feature(s), or recreate "
2020 			    "the pool from backup.\n"));
2021 			break;
2022 		case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2023 			(void) printf(gettext("action: The pool cannot be "
2024 			    "imported in read-write mode. Import the pool "
2025 			    "with\n"
2026 			    "\t\"-o readonly=on\", access the pool on a system "
2027 			    "that supports the\n\trequired feature(s), or "
2028 			    "recreate the pool from backup.\n"));
2029 			break;
2030 		case ZPOOL_STATUS_MISSING_DEV_R:
2031 		case ZPOOL_STATUS_MISSING_DEV_NR:
2032 		case ZPOOL_STATUS_BAD_GUID_SUM:
2033 			(void) printf(gettext(" action: The pool cannot be "
2034 			    "imported. Attach the missing\n\tdevices and try "
2035 			    "again.\n"));
2036 			break;
2037 		default:
2038 			(void) printf(gettext(" action: The pool cannot be "
2039 			    "imported due to damaged devices or data.\n"));
2040 		}
2041 	}
2042 
2043 	/* Print the comment attached to the pool. */
2044 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2045 		(void) printf(gettext("comment: %s\n"), comment);
2046 
2047 	/*
2048 	 * If the state is "closed" or "can't open", and the aux state
2049 	 * is "corrupt data":
2050 	 */
2051 	if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2052 	    (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2053 	    (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2054 		if (pool_state == POOL_STATE_DESTROYED)
2055 			(void) printf(gettext("\tThe pool was destroyed, "
2056 			    "but can be imported using the '-Df' flags.\n"));
2057 		else if (pool_state != POOL_STATE_EXPORTED)
2058 			(void) printf(gettext("\tThe pool may be active on "
2059 			    "another system, but can be imported using\n\t"
2060 			    "the '-f' flag.\n"));
2061 	}
2062 
2063 	if (msgid != NULL)
2064 		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
2065 		    msgid);
2066 
2067 	(void) printf(gettext(" config:\n\n"));
2068 
2069 	namewidth = max_width(NULL, nvroot, 0, 0);
2070 	if (namewidth < 10)
2071 		namewidth = 10;
2072 
2073 	print_import_config(name, nvroot, namewidth, 0);
2074 	if (num_logs(nvroot) > 0)
2075 		print_logs(NULL, nvroot, namewidth, B_FALSE);
2076 
2077 	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2078 		(void) printf(gettext("\n\tAdditional devices are known to "
2079 		    "be part of this pool, though their\n\texact "
2080 		    "configuration cannot be determined.\n"));
2081 	}
2082 }
2083 
2084 /*
2085  * Perform the import for the given configuration.  This passes the heavy
2086  * lifting off to zpool_import_props(), and then mounts the datasets contained
2087  * within the pool.
2088  */
2089 static int
do_import(nvlist_t * config,const char * newname,const char * mntopts,nvlist_t * props,int flags)2090 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2091     nvlist_t *props, int flags)
2092 {
2093 	zpool_handle_t *zhp;
2094 	char *name;
2095 	uint64_t state;
2096 	uint64_t version;
2097 
2098 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2099 	    &name) == 0);
2100 
2101 	verify(nvlist_lookup_uint64(config,
2102 	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2103 	verify(nvlist_lookup_uint64(config,
2104 	    ZPOOL_CONFIG_VERSION, &version) == 0);
2105 	if (!SPA_VERSION_IS_SUPPORTED(version)) {
2106 		(void) fprintf(stderr, gettext("cannot import '%s': pool "
2107 		    "is formatted using an unsupported ZFS version\n"), name);
2108 		return (1);
2109 	} else if (state != POOL_STATE_EXPORTED &&
2110 	    !(flags & ZFS_IMPORT_ANY_HOST)) {
2111 		uint64_t hostid;
2112 
2113 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
2114 		    &hostid) == 0) {
2115 			if ((unsigned long)hostid != gethostid()) {
2116 				char *hostname;
2117 				uint64_t timestamp;
2118 				time_t t;
2119 
2120 				verify(nvlist_lookup_string(config,
2121 				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2122 				verify(nvlist_lookup_uint64(config,
2123 				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
2124 				t = timestamp;
2125 				(void) fprintf(stderr, gettext("cannot import "
2126 				    "'%s': pool may be in use from other "
2127 				    "system, it was last accessed by %s "
2128 				    "(hostid: 0x%lx) on %s"), name, hostname,
2129 				    (unsigned long)hostid,
2130 				    asctime(localtime(&t)));
2131 				(void) fprintf(stderr, gettext("use '-f' to "
2132 				    "import anyway\n"));
2133 				return (1);
2134 			}
2135 		} else {
2136 			(void) fprintf(stderr, gettext("cannot import '%s': "
2137 			    "pool may be in use from other system\n"), name);
2138 			(void) fprintf(stderr, gettext("use '-f' to import "
2139 			    "anyway\n"));
2140 			return (1);
2141 		}
2142 	}
2143 
2144 	if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2145 		return (1);
2146 
2147 	if (newname != NULL)
2148 		name = (char *)newname;
2149 
2150 	if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2151 		return (1);
2152 
2153 	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2154 	    !(flags & ZFS_IMPORT_ONLY) &&
2155 	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2156 		zpool_close(zhp);
2157 		return (1);
2158 	}
2159 
2160 	zpool_close(zhp);
2161 	return (0);
2162 }
2163 
2164 /*
2165  * zpool checkpoint <pool>
2166  *       checkpoint --discard <pool>
2167  *
2168  *	-d	Discard the checkpoint from a checkpointed
2169  *	--discard  pool.
2170  *
2171  * Checkpoints the specified pool, by taking a "snapshot" of its
2172  * current state. A pool can only have one checkpoint at a time.
2173  */
2174 int
zpool_do_checkpoint(int argc,char ** argv)2175 zpool_do_checkpoint(int argc, char **argv)
2176 {
2177 	boolean_t discard;
2178 	char *pool;
2179 	zpool_handle_t *zhp;
2180 	int c, err;
2181 
2182 	struct option long_options[] = {
2183 		{"discard", no_argument, NULL, 'd'},
2184 		{0, 0, 0, 0}
2185 	};
2186 
2187 	discard = B_FALSE;
2188 	while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2189 		switch (c) {
2190 		case 'd':
2191 			discard = B_TRUE;
2192 			break;
2193 		case '?':
2194 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2195 			    optopt);
2196 			usage(B_FALSE);
2197 		}
2198 	}
2199 
2200 	argc -= optind;
2201 	argv += optind;
2202 
2203 	if (argc < 1) {
2204 		(void) fprintf(stderr, gettext("missing pool argument\n"));
2205 		usage(B_FALSE);
2206 	}
2207 
2208 	if (argc > 1) {
2209 		(void) fprintf(stderr, gettext("too many arguments\n"));
2210 		usage(B_FALSE);
2211 	}
2212 
2213 	pool = argv[0];
2214 
2215 	if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2216 		/* As a special case, check for use of '/' in the name */
2217 		if (strchr(pool, '/') != NULL)
2218 			(void) fprintf(stderr, gettext("'zpool checkpoint' "
2219 			    "doesn't work on datasets. To save the state "
2220 			    "of a dataset from a specific point in time "
2221 			    "please use 'zfs snapshot'\n"));
2222 		return (1);
2223 	}
2224 
2225 	if (discard)
2226 		err = (zpool_discard_checkpoint(zhp) != 0);
2227 	else
2228 		err = (zpool_checkpoint(zhp) != 0);
2229 
2230 	zpool_close(zhp);
2231 
2232 	return (err);
2233 }
2234 
2235 #define	CHECKPOINT_OPT	1024
2236 
2237 /*
2238  * zpool import [-d dir] [-D]
2239  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2240  *              [-d dir | -c cachefile] [-f] -a
2241  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2242  *              [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
2243  *              <pool | id> [newpool]
2244  *
2245  *	-c	Read pool information from a cachefile instead of searching
2246  *		devices.
2247  *
2248  *	-d	Scan in a specific directory, other than /dev/dsk.  More than
2249  *		one directory can be specified using multiple '-d' options.
2250  *
2251  *	-D	Scan for previously destroyed pools or import all or only
2252  *		specified destroyed pools.
2253  *
2254  *	-R	Temporarily import the pool, with all mountpoints relative to
2255  *		the given root.  The pool will remain exported when the machine
2256  *		is rebooted.
2257  *
2258  *	-V	Import even in the presence of faulted vdevs.  This is an
2259  *		intentionally undocumented option for testing purposes, and
2260  *		treats the pool configuration as complete, leaving any bad
2261  *		vdevs in the FAULTED state. In other words, it does verbatim
2262  *		import.
2263  *
2264  *	-f	Force import, even if it appears that the pool is active.
2265  *
2266  *	-F	Attempt rewind if necessary.
2267  *
2268  *	-n	See if rewind would work, but don't actually rewind.
2269  *
2270  *	-N	Import the pool but don't mount datasets.
2271  *
2272  *	-t	Use newpool as a temporary pool name instead of renaming
2273  *		the pool.
2274  *
2275  *	-T	Specify a starting txg to use for import. This option is
2276  *		intentionally undocumented option for testing purposes.
2277  *
2278  *	-a	Import all pools found.
2279  *
2280  *	-o	Set property=value and/or temporary mount options (without '=').
2281  *
2282  *	--rewind-to-checkpoint
2283  *		Import the pool and revert back to the checkpoint.
2284  *
2285  * The import command scans for pools to import, and import pools based on pool
2286  * name and GUID.  The pool can also be renamed as part of the import process.
2287  */
2288 int
zpool_do_import(int argc,char ** argv)2289 zpool_do_import(int argc, char **argv)
2290 {
2291 	char **searchdirs = NULL;
2292 	int nsearch = 0;
2293 	int c;
2294 	int err = 0;
2295 	nvlist_t *pools = NULL;
2296 	boolean_t do_all = B_FALSE;
2297 	boolean_t do_destroyed = B_FALSE;
2298 	char *mntopts = NULL;
2299 	nvpair_t *elem;
2300 	nvlist_t *config;
2301 	uint64_t searchguid = 0;
2302 	char *searchname = NULL;
2303 	char *propval;
2304 	nvlist_t *found_config;
2305 	nvlist_t *policy = NULL;
2306 	nvlist_t *props = NULL;
2307 	boolean_t first;
2308 	int flags = ZFS_IMPORT_NORMAL;
2309 	uint32_t rewind_policy = ZPOOL_NO_REWIND;
2310 	boolean_t dryrun = B_FALSE;
2311 	boolean_t do_rewind = B_FALSE;
2312 	boolean_t xtreme_rewind = B_FALSE;
2313 	uint64_t pool_state, txg = -1ULL;
2314 	char *cachefile = NULL;
2315 	importargs_t idata = { 0 };
2316 	char *endptr;
2317 
2318 
2319 	struct option long_options[] = {
2320 		{"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2321 		{0, 0, 0, 0}
2322 	};
2323 
2324 	/* check options */
2325 	while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:tT:VX",
2326 	    long_options, NULL)) != -1) {
2327 		switch (c) {
2328 		case 'a':
2329 			do_all = B_TRUE;
2330 			break;
2331 		case 'c':
2332 			cachefile = optarg;
2333 			break;
2334 		case 'd':
2335 			if (searchdirs == NULL) {
2336 				searchdirs = safe_malloc(sizeof (char *));
2337 			} else {
2338 				char **tmp = safe_malloc((nsearch + 1) *
2339 				    sizeof (char *));
2340 				bcopy(searchdirs, tmp, nsearch *
2341 				    sizeof (char *));
2342 				free(searchdirs);
2343 				searchdirs = tmp;
2344 			}
2345 			searchdirs[nsearch++] = optarg;
2346 			break;
2347 		case 'D':
2348 			do_destroyed = B_TRUE;
2349 			break;
2350 		case 'f':
2351 			flags |= ZFS_IMPORT_ANY_HOST;
2352 			break;
2353 		case 'F':
2354 			do_rewind = B_TRUE;
2355 			break;
2356 		case 'm':
2357 			flags |= ZFS_IMPORT_MISSING_LOG;
2358 			break;
2359 		case 'n':
2360 			dryrun = B_TRUE;
2361 			break;
2362 		case 'N':
2363 			flags |= ZFS_IMPORT_ONLY;
2364 			break;
2365 		case 'o':
2366 			if ((propval = strchr(optarg, '=')) != NULL) {
2367 				*propval = '\0';
2368 				propval++;
2369 				if (add_prop_list(optarg, propval,
2370 				    &props, B_TRUE))
2371 					goto error;
2372 			} else {
2373 				mntopts = optarg;
2374 			}
2375 			break;
2376 		case 'R':
2377 			if (add_prop_list(zpool_prop_to_name(
2378 			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2379 				goto error;
2380 			if (add_prop_list_default(zpool_prop_to_name(
2381 			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2382 				goto error;
2383 			break;
2384 		case 't':
2385 			flags |= ZFS_IMPORT_TEMP_NAME;
2386 			if (add_prop_list_default(zpool_prop_to_name(
2387 			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2388 				goto error;
2389 			break;
2390 		case 'T':
2391 			errno = 0;
2392 			txg = strtoull(optarg, &endptr, 0);
2393 			if (errno != 0 || *endptr != '\0') {
2394 				(void) fprintf(stderr,
2395 				    gettext("invalid txg value\n"));
2396 				usage(B_FALSE);
2397 			}
2398 			rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2399 			break;
2400 		case 'V':
2401 			flags |= ZFS_IMPORT_VERBATIM;
2402 			break;
2403 		case 'X':
2404 			xtreme_rewind = B_TRUE;
2405 			break;
2406 		case CHECKPOINT_OPT:
2407 			flags |= ZFS_IMPORT_CHECKPOINT;
2408 			break;
2409 		case ':':
2410 			(void) fprintf(stderr, gettext("missing argument for "
2411 			    "'%c' option\n"), optopt);
2412 			usage(B_FALSE);
2413 			break;
2414 		case '?':
2415 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2416 			    optopt);
2417 			usage(B_FALSE);
2418 		}
2419 	}
2420 
2421 	argc -= optind;
2422 	argv += optind;
2423 
2424 	if (cachefile && nsearch != 0) {
2425 		(void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2426 		usage(B_FALSE);
2427 	}
2428 
2429 	if ((dryrun || xtreme_rewind) && !do_rewind) {
2430 		(void) fprintf(stderr,
2431 		    gettext("-n or -X only meaningful with -F\n"));
2432 		usage(B_FALSE);
2433 	}
2434 	if (dryrun)
2435 		rewind_policy = ZPOOL_TRY_REWIND;
2436 	else if (do_rewind)
2437 		rewind_policy = ZPOOL_DO_REWIND;
2438 	if (xtreme_rewind)
2439 		rewind_policy |= ZPOOL_EXTREME_REWIND;
2440 
2441 	/* In the future, we can capture further policy and include it here */
2442 	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2443 	    nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
2444 	    nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
2445 	    rewind_policy) != 0)
2446 		goto error;
2447 
2448 	if (searchdirs == NULL) {
2449 		searchdirs = safe_malloc(sizeof (char *));
2450 		searchdirs[0] = "/dev";
2451 		nsearch = 1;
2452 	}
2453 
2454 	/* check argument count */
2455 	if (do_all) {
2456 		if (argc != 0) {
2457 			(void) fprintf(stderr, gettext("too many arguments\n"));
2458 			usage(B_FALSE);
2459 		}
2460 	} else {
2461 		if (argc > 2) {
2462 			(void) fprintf(stderr, gettext("too many arguments\n"));
2463 			usage(B_FALSE);
2464 		}
2465 
2466 		/*
2467 		 * Check for the SYS_CONFIG privilege.  We do this explicitly
2468 		 * here because otherwise any attempt to discover pools will
2469 		 * silently fail.
2470 		 */
2471 		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2472 			(void) fprintf(stderr, gettext("cannot "
2473 			    "discover pools: permission denied\n"));
2474 			free(searchdirs);
2475 			nvlist_free(policy);
2476 			return (1);
2477 		}
2478 	}
2479 
2480 	/*
2481 	 * Depending on the arguments given, we do one of the following:
2482 	 *
2483 	 *	<none>	Iterate through all pools and display information about
2484 	 *		each one.
2485 	 *
2486 	 *	-a	Iterate through all pools and try to import each one.
2487 	 *
2488 	 *	<id>	Find the pool that corresponds to the given GUID/pool
2489 	 *		name and import that one.
2490 	 *
2491 	 *	-D	Above options applies only to destroyed pools.
2492 	 */
2493 	if (argc != 0) {
2494 		char *endptr;
2495 
2496 		errno = 0;
2497 		searchguid = strtoull(argv[0], &endptr, 10);
2498 		if (errno != 0 || *endptr != '\0') {
2499 			searchname = argv[0];
2500 			searchguid = 0;
2501 		}
2502 		found_config = NULL;
2503 
2504 		/*
2505 		 * User specified a name or guid.  Ensure it's unique.
2506 		 */
2507 		idata.unique = B_TRUE;
2508 	}
2509 
2510 
2511 	idata.path = searchdirs;
2512 	idata.paths = nsearch;
2513 	idata.poolname = searchname;
2514 	idata.guid = searchguid;
2515 	idata.cachefile = cachefile;
2516 	idata.policy = policy;
2517 
2518 	pools = zpool_search_import(g_zfs, &idata);
2519 
2520 	if (pools != NULL && idata.exists &&
2521 	    (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2522 		(void) fprintf(stderr, gettext("cannot import '%s': "
2523 		    "a pool with that name already exists\n"),
2524 		    argv[0]);
2525 		(void) fprintf(stderr, gettext("use the form 'zpool import "
2526 		    "[-t] <pool | id> <newpool>' to give it a new temporary "
2527 		    "or permanent name\n"));
2528 		err = 1;
2529 	} else if (pools == NULL && idata.exists) {
2530 		(void) fprintf(stderr, gettext("cannot import '%s': "
2531 		    "a pool with that name is already created/imported,\n"),
2532 		    argv[0]);
2533 		(void) fprintf(stderr, gettext("and no additional pools "
2534 		    "with that name were found\n"));
2535 		err = 1;
2536 	} else if (pools == NULL) {
2537 		if (argc != 0) {
2538 			(void) fprintf(stderr, gettext("cannot import '%s': "
2539 			    "no such pool available\n"), argv[0]);
2540 		}
2541 		err = 1;
2542 	}
2543 
2544 	if (err == 1) {
2545 		free(searchdirs);
2546 		nvlist_free(policy);
2547 		return (1);
2548 	}
2549 
2550 	/*
2551 	 * At this point we have a list of import candidate configs. Even if
2552 	 * we were searching by pool name or guid, we still need to
2553 	 * post-process the list to deal with pool state and possible
2554 	 * duplicate names.
2555 	 */
2556 	err = 0;
2557 	elem = NULL;
2558 	first = B_TRUE;
2559 	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2560 
2561 		verify(nvpair_value_nvlist(elem, &config) == 0);
2562 
2563 		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2564 		    &pool_state) == 0);
2565 		if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2566 			continue;
2567 		if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2568 			continue;
2569 
2570 		verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
2571 		    policy) == 0);
2572 
2573 		if (argc == 0) {
2574 			if (first)
2575 				first = B_FALSE;
2576 			else if (!do_all)
2577 				(void) printf("\n");
2578 
2579 			if (do_all) {
2580 				err |= do_import(config, NULL, mntopts,
2581 				    props, flags);
2582 			} else {
2583 				show_import(config);
2584 			}
2585 		} else if (searchname != NULL) {
2586 			char *name;
2587 
2588 			/*
2589 			 * We are searching for a pool based on name.
2590 			 */
2591 			verify(nvlist_lookup_string(config,
2592 			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2593 
2594 			if (strcmp(name, searchname) == 0) {
2595 				if (found_config != NULL) {
2596 					(void) fprintf(stderr, gettext(
2597 					    "cannot import '%s': more than "
2598 					    "one matching pool\n"), searchname);
2599 					(void) fprintf(stderr, gettext(
2600 					    "import by numeric ID instead\n"));
2601 					err = B_TRUE;
2602 				}
2603 				found_config = config;
2604 			}
2605 		} else {
2606 			uint64_t guid;
2607 
2608 			/*
2609 			 * Search for a pool by guid.
2610 			 */
2611 			verify(nvlist_lookup_uint64(config,
2612 			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2613 
2614 			if (guid == searchguid)
2615 				found_config = config;
2616 		}
2617 	}
2618 
2619 	/*
2620 	 * If we were searching for a specific pool, verify that we found a
2621 	 * pool, and then do the import.
2622 	 */
2623 	if (argc != 0 && err == 0) {
2624 		if (found_config == NULL) {
2625 			(void) fprintf(stderr, gettext("cannot import '%s': "
2626 			    "no such pool available\n"), argv[0]);
2627 			err = B_TRUE;
2628 		} else {
2629 			err |= do_import(found_config, argc == 1 ? NULL :
2630 			    argv[1], mntopts, props, flags);
2631 		}
2632 	}
2633 
2634 	/*
2635 	 * If we were just looking for pools, report an error if none were
2636 	 * found.
2637 	 */
2638 	if (argc == 0 && first)
2639 		(void) fprintf(stderr,
2640 		    gettext("no pools available to import\n"));
2641 
2642 error:
2643 	nvlist_free(props);
2644 	nvlist_free(pools);
2645 	nvlist_free(policy);
2646 	free(searchdirs);
2647 
2648 	return (err ? 1 : 0);
2649 }
2650 
2651 typedef struct iostat_cbdata {
2652 	boolean_t cb_verbose;
2653 	int cb_namewidth;
2654 	int cb_iteration;
2655 	zpool_list_t *cb_list;
2656 } iostat_cbdata_t;
2657 
2658 static void
print_iostat_separator(iostat_cbdata_t * cb)2659 print_iostat_separator(iostat_cbdata_t *cb)
2660 {
2661 	int i = 0;
2662 
2663 	for (i = 0; i < cb->cb_namewidth; i++)
2664 		(void) printf("-");
2665 	(void) printf("  -----  -----  -----  -----  -----  -----\n");
2666 }
2667 
2668 static void
print_iostat_header(iostat_cbdata_t * cb)2669 print_iostat_header(iostat_cbdata_t *cb)
2670 {
2671 	(void) printf("%*s     capacity     operations    bandwidth\n",
2672 	    cb->cb_namewidth, "");
2673 	(void) printf("%-*s  alloc   free   read  write   read  write\n",
2674 	    cb->cb_namewidth, "pool");
2675 	print_iostat_separator(cb);
2676 }
2677 
2678 /*
2679  * Display a single statistic.
2680  */
2681 static void
print_one_stat(uint64_t value)2682 print_one_stat(uint64_t value)
2683 {
2684 	char buf[64];
2685 
2686 	zfs_nicenum(value, buf, sizeof (buf));
2687 	(void) printf("  %5s", buf);
2688 }
2689 
2690 /*
2691  * Print out all the statistics for the given vdev.  This can either be the
2692  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2693  * is a verbose output, and we don't want to display the toplevel pool stats.
2694  */
2695 void
print_vdev_stats(zpool_handle_t * zhp,const char * name,nvlist_t * oldnv,nvlist_t * newnv,iostat_cbdata_t * cb,int depth)2696 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2697     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2698 {
2699 	nvlist_t **oldchild, **newchild;
2700 	uint_t c, children;
2701 	vdev_stat_t *oldvs, *newvs;
2702 	vdev_stat_t zerovs = { 0 };
2703 	uint64_t tdelta;
2704 	double scale;
2705 	char *vname;
2706 
2707 	if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2708 		return;
2709 
2710 	if (oldnv != NULL) {
2711 		verify(nvlist_lookup_uint64_array(oldnv,
2712 		    ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2713 	} else {
2714 		oldvs = &zerovs;
2715 	}
2716 
2717 	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2718 	    (uint64_t **)&newvs, &c) == 0);
2719 
2720 	if (strlen(name) + depth > cb->cb_namewidth)
2721 		(void) printf("%*s%s", depth, "", name);
2722 	else
2723 		(void) printf("%*s%s%*s", depth, "", name,
2724 		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
2725 
2726 	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2727 
2728 	if (tdelta == 0)
2729 		scale = 1.0;
2730 	else
2731 		scale = (double)NANOSEC / tdelta;
2732 
2733 	/* only toplevel vdevs have capacity stats */
2734 	if (newvs->vs_space == 0) {
2735 		(void) printf("      -      -");
2736 	} else {
2737 		print_one_stat(newvs->vs_alloc);
2738 		print_one_stat(newvs->vs_space - newvs->vs_alloc);
2739 	}
2740 
2741 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2742 	    oldvs->vs_ops[ZIO_TYPE_READ])));
2743 
2744 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2745 	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
2746 
2747 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2748 	    oldvs->vs_bytes[ZIO_TYPE_READ])));
2749 
2750 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2751 	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2752 
2753 	(void) printf("\n");
2754 
2755 	if (!cb->cb_verbose)
2756 		return;
2757 
2758 	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2759 	    &newchild, &children) != 0)
2760 		return;
2761 
2762 	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2763 	    &oldchild, &c) != 0)
2764 		return;
2765 
2766 	for (c = 0; c < children; c++) {
2767 		uint64_t ishole = B_FALSE, islog = B_FALSE;
2768 
2769 		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2770 		    &ishole);
2771 
2772 		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2773 		    &islog);
2774 
2775 		if (ishole || islog)
2776 			continue;
2777 
2778 		vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2779 		print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2780 		    newchild[c], cb, depth + 2);
2781 		free(vname);
2782 	}
2783 
2784 	/*
2785 	 * Log device section
2786 	 */
2787 
2788 	if (num_logs(newnv) > 0) {
2789 		(void) printf("%-*s      -      -      -      -      -      "
2790 		    "-\n", cb->cb_namewidth, "logs");
2791 
2792 		for (c = 0; c < children; c++) {
2793 			uint64_t islog = B_FALSE;
2794 			(void) nvlist_lookup_uint64(newchild[c],
2795 			    ZPOOL_CONFIG_IS_LOG, &islog);
2796 
2797 			if (islog) {
2798 				vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2799 				    B_FALSE);
2800 				print_vdev_stats(zhp, vname, oldnv ?
2801 				    oldchild[c] : NULL, newchild[c],
2802 				    cb, depth + 2);
2803 				free(vname);
2804 			}
2805 		}
2806 
2807 	}
2808 
2809 	/*
2810 	 * Include level 2 ARC devices in iostat output
2811 	 */
2812 	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2813 	    &newchild, &children) != 0)
2814 		return;
2815 
2816 	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2817 	    &oldchild, &c) != 0)
2818 		return;
2819 
2820 	if (children > 0) {
2821 		(void) printf("%-*s      -      -      -      -      -      "
2822 		    "-\n", cb->cb_namewidth, "cache");
2823 		for (c = 0; c < children; c++) {
2824 			vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2825 			    B_FALSE);
2826 			print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2827 			    newchild[c], cb, depth + 2);
2828 			free(vname);
2829 		}
2830 	}
2831 }
2832 
2833 static int
refresh_iostat(zpool_handle_t * zhp,void * data)2834 refresh_iostat(zpool_handle_t *zhp, void *data)
2835 {
2836 	iostat_cbdata_t *cb = data;
2837 	boolean_t missing;
2838 
2839 	/*
2840 	 * If the pool has disappeared, remove it from the list and continue.
2841 	 */
2842 	if (zpool_refresh_stats(zhp, &missing) != 0)
2843 		return (-1);
2844 
2845 	if (missing)
2846 		pool_list_remove(cb->cb_list, zhp);
2847 
2848 	return (0);
2849 }
2850 
2851 /*
2852  * Callback to print out the iostats for the given pool.
2853  */
2854 int
print_iostat(zpool_handle_t * zhp,void * data)2855 print_iostat(zpool_handle_t *zhp, void *data)
2856 {
2857 	iostat_cbdata_t *cb = data;
2858 	nvlist_t *oldconfig, *newconfig;
2859 	nvlist_t *oldnvroot, *newnvroot;
2860 
2861 	newconfig = zpool_get_config(zhp, &oldconfig);
2862 
2863 	if (cb->cb_iteration == 1)
2864 		oldconfig = NULL;
2865 
2866 	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2867 	    &newnvroot) == 0);
2868 
2869 	if (oldconfig == NULL)
2870 		oldnvroot = NULL;
2871 	else
2872 		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2873 		    &oldnvroot) == 0);
2874 
2875 	/*
2876 	 * Print out the statistics for the pool.
2877 	 */
2878 	print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2879 
2880 	if (cb->cb_verbose)
2881 		print_iostat_separator(cb);
2882 
2883 	return (0);
2884 }
2885 
2886 int
get_namewidth(zpool_handle_t * zhp,void * data)2887 get_namewidth(zpool_handle_t *zhp, void *data)
2888 {
2889 	iostat_cbdata_t *cb = data;
2890 	nvlist_t *config, *nvroot;
2891 
2892 	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2893 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2894 		    &nvroot) == 0);
2895 		if (!cb->cb_verbose)
2896 			cb->cb_namewidth = strlen(zpool_get_name(zhp));
2897 		else
2898 			cb->cb_namewidth = max_width(zhp, nvroot, 0,
2899 			    cb->cb_namewidth);
2900 	}
2901 
2902 	/*
2903 	 * The width must fall into the range [10,38].  The upper limit is the
2904 	 * maximum we can have and still fit in 80 columns.
2905 	 */
2906 	if (cb->cb_namewidth < 10)
2907 		cb->cb_namewidth = 10;
2908 	if (cb->cb_namewidth > 38)
2909 		cb->cb_namewidth = 38;
2910 
2911 	return (0);
2912 }
2913 
2914 /*
2915  * Parse the input string, get the 'interval' and 'count' value if there is one.
2916  */
2917 static void
get_interval_count(int * argcp,char ** argv,unsigned long * iv,unsigned long * cnt)2918 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2919     unsigned long *cnt)
2920 {
2921 	unsigned long interval = 0, count = 0;
2922 	int argc = *argcp, errno;
2923 
2924 	/*
2925 	 * Determine if the last argument is an integer or a pool name
2926 	 */
2927 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2928 		char *end;
2929 
2930 		errno = 0;
2931 		interval = strtoul(argv[argc - 1], &end, 10);
2932 
2933 		if (*end == '\0' && errno == 0) {
2934 			if (interval == 0) {
2935 				(void) fprintf(stderr, gettext("interval "
2936 				    "cannot be zero\n"));
2937 				usage(B_FALSE);
2938 			}
2939 			/*
2940 			 * Ignore the last parameter
2941 			 */
2942 			argc--;
2943 		} else {
2944 			/*
2945 			 * If this is not a valid number, just plow on.  The
2946 			 * user will get a more informative error message later
2947 			 * on.
2948 			 */
2949 			interval = 0;
2950 		}
2951 	}
2952 
2953 	/*
2954 	 * If the last argument is also an integer, then we have both a count
2955 	 * and an interval.
2956 	 */
2957 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2958 		char *end;
2959 
2960 		errno = 0;
2961 		count = interval;
2962 		interval = strtoul(argv[argc - 1], &end, 10);
2963 
2964 		if (*end == '\0' && errno == 0) {
2965 			if (interval == 0) {
2966 				(void) fprintf(stderr, gettext("interval "
2967 				    "cannot be zero\n"));
2968 				usage(B_FALSE);
2969 			}
2970 
2971 			/*
2972 			 * Ignore the last parameter
2973 			 */
2974 			argc--;
2975 		} else {
2976 			interval = 0;
2977 		}
2978 	}
2979 
2980 	*iv = interval;
2981 	*cnt = count;
2982 	*argcp = argc;
2983 }
2984 
2985 static void
get_timestamp_arg(char c)2986 get_timestamp_arg(char c)
2987 {
2988 	if (c == 'u')
2989 		timestamp_fmt = UDATE;
2990 	else if (c == 'd')
2991 		timestamp_fmt = DDATE;
2992 	else
2993 		usage(B_FALSE);
2994 }
2995 
2996 /*
2997  * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2998  *
2999  *	-v	Display statistics for individual vdevs
3000  *	-T	Display a timestamp in date(1) or Unix format
3001  *
3002  * This command can be tricky because we want to be able to deal with pool
3003  * creation/destruction as well as vdev configuration changes.  The bulk of this
3004  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
3005  * on pool_list_update() to detect the addition of new pools.  Configuration
3006  * changes are all handled within libzfs.
3007  */
3008 int
zpool_do_iostat(int argc,char ** argv)3009 zpool_do_iostat(int argc, char **argv)
3010 {
3011 	int c;
3012 	int ret;
3013 	int npools;
3014 	unsigned long interval = 0, count = 0;
3015 	zpool_list_t *list;
3016 	boolean_t verbose = B_FALSE;
3017 	iostat_cbdata_t cb;
3018 
3019 	/* check options */
3020 	while ((c = getopt(argc, argv, "T:v")) != -1) {
3021 		switch (c) {
3022 		case 'T':
3023 			get_timestamp_arg(*optarg);
3024 			break;
3025 		case 'v':
3026 			verbose = B_TRUE;
3027 			break;
3028 		case '?':
3029 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3030 			    optopt);
3031 			usage(B_FALSE);
3032 		}
3033 	}
3034 
3035 	argc -= optind;
3036 	argv += optind;
3037 
3038 	get_interval_count(&argc, argv, &interval, &count);
3039 
3040 	/*
3041 	 * Construct the list of all interesting pools.
3042 	 */
3043 	ret = 0;
3044 	if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
3045 		return (1);
3046 
3047 	if (pool_list_count(list) == 0 && argc != 0) {
3048 		pool_list_free(list);
3049 		return (1);
3050 	}
3051 
3052 	if (pool_list_count(list) == 0 && interval == 0) {
3053 		pool_list_free(list);
3054 		(void) fprintf(stderr, gettext("no pools available\n"));
3055 		return (1);
3056 	}
3057 
3058 	/*
3059 	 * Enter the main iostat loop.
3060 	 */
3061 	cb.cb_list = list;
3062 	cb.cb_verbose = verbose;
3063 	cb.cb_iteration = 0;
3064 	cb.cb_namewidth = 0;
3065 
3066 	for (;;) {
3067 		pool_list_update(list);
3068 
3069 		if ((npools = pool_list_count(list)) == 0)
3070 			break;
3071 
3072 		/*
3073 		 * Refresh all statistics.  This is done as an explicit step
3074 		 * before calculating the maximum name width, so that any
3075 		 * configuration changes are properly accounted for.
3076 		 */
3077 		(void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
3078 
3079 		/*
3080 		 * Iterate over all pools to determine the maximum width
3081 		 * for the pool / device name column across all pools.
3082 		 */
3083 		cb.cb_namewidth = 0;
3084 		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3085 
3086 		if (timestamp_fmt != NODATE)
3087 			print_timestamp(timestamp_fmt);
3088 
3089 		/*
3090 		 * If it's the first time, or verbose mode, print the header.
3091 		 */
3092 		if (++cb.cb_iteration == 1 || verbose)
3093 			print_iostat_header(&cb);
3094 
3095 		(void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
3096 
3097 		/*
3098 		 * If there's more than one pool, and we're not in verbose mode
3099 		 * (which prints a separator for us), then print a separator.
3100 		 */
3101 		if (npools > 1 && !verbose)
3102 			print_iostat_separator(&cb);
3103 
3104 		if (verbose)
3105 			(void) printf("\n");
3106 
3107 		/*
3108 		 * Flush the output so that redirection to a file isn't buffered
3109 		 * indefinitely.
3110 		 */
3111 		(void) fflush(stdout);
3112 
3113 		if (interval == 0)
3114 			break;
3115 
3116 		if (count != 0 && --count == 0)
3117 			break;
3118 
3119 		(void) sleep(interval);
3120 	}
3121 
3122 	pool_list_free(list);
3123 
3124 	return (ret);
3125 }
3126 
3127 typedef struct list_cbdata {
3128 	boolean_t	cb_verbose;
3129 	int		cb_namewidth;
3130 	boolean_t	cb_scripted;
3131 	zprop_list_t	*cb_proplist;
3132 	boolean_t	cb_literal;
3133 } list_cbdata_t;
3134 
3135 /*
3136  * Given a list of columns to display, output appropriate headers for each one.
3137  */
3138 static void
print_header(list_cbdata_t * cb)3139 print_header(list_cbdata_t *cb)
3140 {
3141 	zprop_list_t *pl = cb->cb_proplist;
3142 	char headerbuf[ZPOOL_MAXPROPLEN];
3143 	const char *header;
3144 	boolean_t first = B_TRUE;
3145 	boolean_t right_justify;
3146 	size_t width = 0;
3147 
3148 	for (; pl != NULL; pl = pl->pl_next) {
3149 		width = pl->pl_width;
3150 		if (first && cb->cb_verbose) {
3151 			/*
3152 			 * Reset the width to accommodate the verbose listing
3153 			 * of devices.
3154 			 */
3155 			width = cb->cb_namewidth;
3156 		}
3157 
3158 		if (!first)
3159 			(void) printf("  ");
3160 		else
3161 			first = B_FALSE;
3162 
3163 		right_justify = B_FALSE;
3164 		if (pl->pl_prop != ZPROP_INVAL) {
3165 			header = zpool_prop_column_name(pl->pl_prop);
3166 			right_justify = zpool_prop_align_right(pl->pl_prop);
3167 		} else {
3168 			int i;
3169 
3170 			for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3171 				headerbuf[i] = toupper(pl->pl_user_prop[i]);
3172 			headerbuf[i] = '\0';
3173 			header = headerbuf;
3174 		}
3175 
3176 		if (pl->pl_next == NULL && !right_justify)
3177 			(void) printf("%s", header);
3178 		else if (right_justify)
3179 			(void) printf("%*s", width, header);
3180 		else
3181 			(void) printf("%-*s", width, header);
3182 
3183 	}
3184 
3185 	(void) printf("\n");
3186 }
3187 
3188 /*
3189  * Given a pool and a list of properties, print out all the properties according
3190  * to the described layout.
3191  */
3192 static void
print_pool(zpool_handle_t * zhp,list_cbdata_t * cb)3193 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3194 {
3195 	zprop_list_t *pl = cb->cb_proplist;
3196 	boolean_t first = B_TRUE;
3197 	char property[ZPOOL_MAXPROPLEN];
3198 	char *propstr;
3199 	boolean_t right_justify;
3200 	size_t width;
3201 
3202 	for (; pl != NULL; pl = pl->pl_next) {
3203 
3204 		width = pl->pl_width;
3205 		if (first && cb->cb_verbose) {
3206 			/*
3207 			 * Reset the width to accommodate the verbose listing
3208 			 * of devices.
3209 			 */
3210 			width = cb->cb_namewidth;
3211 		}
3212 
3213 		if (!first) {
3214 			if (cb->cb_scripted)
3215 				(void) printf("\t");
3216 			else
3217 				(void) printf("  ");
3218 		} else {
3219 			first = B_FALSE;
3220 		}
3221 
3222 		right_justify = B_FALSE;
3223 		if (pl->pl_prop != ZPROP_INVAL) {
3224 			if (zpool_get_prop(zhp, pl->pl_prop, property,
3225 			    sizeof (property), NULL, cb->cb_literal) != 0)
3226 				propstr = "-";
3227 			else
3228 				propstr = property;
3229 
3230 			right_justify = zpool_prop_align_right(pl->pl_prop);
3231 		} else if ((zpool_prop_feature(pl->pl_user_prop) ||
3232 		    zpool_prop_unsupported(pl->pl_user_prop)) &&
3233 		    zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3234 		    sizeof (property)) == 0) {
3235 			propstr = property;
3236 		} else {
3237 			propstr = "-";
3238 		}
3239 
3240 
3241 		/*
3242 		 * If this is being called in scripted mode, or if this is the
3243 		 * last column and it is left-justified, don't include a width
3244 		 * format specifier.
3245 		 */
3246 		if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3247 			(void) printf("%s", propstr);
3248 		else if (right_justify)
3249 			(void) printf("%*s", width, propstr);
3250 		else
3251 			(void) printf("%-*s", width, propstr);
3252 	}
3253 
3254 	(void) printf("\n");
3255 }
3256 
3257 static void
print_one_column(zpool_prop_t prop,uint64_t value,boolean_t scripted,boolean_t valid)3258 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3259     boolean_t valid)
3260 {
3261 	char propval[64];
3262 	boolean_t fixed;
3263 	size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3264 
3265 	switch (prop) {
3266 	case ZPOOL_PROP_EXPANDSZ:
3267 	case ZPOOL_PROP_CHECKPOINT:
3268 		if (value == 0)
3269 			(void) strlcpy(propval, "-", sizeof (propval));
3270 		else
3271 			zfs_nicenum(value, propval, sizeof (propval));
3272 		break;
3273 	case ZPOOL_PROP_FRAGMENTATION:
3274 		if (value == ZFS_FRAG_INVALID) {
3275 			(void) strlcpy(propval, "-", sizeof (propval));
3276 		} else {
3277 			(void) snprintf(propval, sizeof (propval), "%llu%%",
3278 			    value);
3279 		}
3280 		break;
3281 	case ZPOOL_PROP_CAPACITY:
3282 		(void) snprintf(propval, sizeof (propval), "%llu%%", value);
3283 		break;
3284 	default:
3285 		zfs_nicenum(value, propval, sizeof (propval));
3286 	}
3287 
3288 	if (!valid)
3289 		(void) strlcpy(propval, "-", sizeof (propval));
3290 
3291 	if (scripted)
3292 		(void) printf("\t%s", propval);
3293 	else
3294 		(void) printf("  %*s", width, propval);
3295 }
3296 
3297 void
print_list_stats(zpool_handle_t * zhp,const char * name,nvlist_t * nv,list_cbdata_t * cb,int depth)3298 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3299     list_cbdata_t *cb, int depth)
3300 {
3301 	nvlist_t **child;
3302 	vdev_stat_t *vs;
3303 	uint_t c, children;
3304 	char *vname;
3305 	boolean_t scripted = cb->cb_scripted;
3306 	uint64_t islog = B_FALSE;
3307 	boolean_t haslog = B_FALSE;
3308 	char *dashes = "%-*s      -      -      -         -      -      -\n";
3309 
3310 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3311 	    (uint64_t **)&vs, &c) == 0);
3312 
3313 	if (name != NULL) {
3314 		boolean_t toplevel = (vs->vs_space != 0);
3315 		uint64_t cap;
3316 
3317 		if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3318 			return;
3319 
3320 		if (scripted)
3321 			(void) printf("\t%s", name);
3322 		else if (strlen(name) + depth > cb->cb_namewidth)
3323 			(void) printf("%*s%s", depth, "", name);
3324 		else
3325 			(void) printf("%*s%s%*s", depth, "", name,
3326 			    (int)(cb->cb_namewidth - strlen(name) - depth), "");
3327 
3328 		/*
3329 		 * Print the properties for the individual vdevs. Some
3330 		 * properties are only applicable to toplevel vdevs. The
3331 		 * 'toplevel' boolean value is passed to the print_one_column()
3332 		 * to indicate that the value is valid.
3333 		 */
3334 		print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3335 		    toplevel);
3336 		print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3337 		    toplevel);
3338 		print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3339 		    scripted, toplevel);
3340 		print_one_column(ZPOOL_PROP_CHECKPOINT,
3341 		    vs->vs_checkpoint_space, scripted, toplevel);
3342 		print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3343 		    B_TRUE);
3344 		print_one_column(ZPOOL_PROP_FRAGMENTATION,
3345 		    vs->vs_fragmentation, scripted,
3346 		    (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3347 		cap = (vs->vs_space == 0) ? 0 :
3348 		    (vs->vs_alloc * 100 / vs->vs_space);
3349 		print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3350 		(void) printf("\n");
3351 	}
3352 
3353 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3354 	    &child, &children) != 0)
3355 		return;
3356 
3357 	for (c = 0; c < children; c++) {
3358 		uint64_t ishole = B_FALSE;
3359 
3360 		if (nvlist_lookup_uint64(child[c],
3361 		    ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3362 			continue;
3363 
3364 		if (nvlist_lookup_uint64(child[c],
3365 		    ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3366 			haslog = B_TRUE;
3367 			continue;
3368 		}
3369 
3370 		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3371 		print_list_stats(zhp, vname, child[c], cb, depth + 2);
3372 		free(vname);
3373 	}
3374 
3375 	if (haslog == B_TRUE) {
3376 		/* LINTED E_SEC_PRINTF_VAR_FMT */
3377 		(void) printf(dashes, cb->cb_namewidth, "log");
3378 		for (c = 0; c < children; c++) {
3379 			if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3380 			    &islog) != 0 || !islog)
3381 				continue;
3382 			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3383 			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3384 			free(vname);
3385 		}
3386 	}
3387 
3388 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3389 	    &child, &children) == 0 && children > 0) {
3390 		/* LINTED E_SEC_PRINTF_VAR_FMT */
3391 		(void) printf(dashes, cb->cb_namewidth, "cache");
3392 		for (c = 0; c < children; c++) {
3393 			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3394 			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3395 			free(vname);
3396 		}
3397 	}
3398 
3399 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3400 	    &children) == 0 && children > 0) {
3401 		/* LINTED E_SEC_PRINTF_VAR_FMT */
3402 		(void) printf(dashes, cb->cb_namewidth, "spare");
3403 		for (c = 0; c < children; c++) {
3404 			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3405 			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3406 			free(vname);
3407 		}
3408 	}
3409 }
3410 
3411 
3412 /*
3413  * Generic callback function to list a pool.
3414  */
3415 int
list_callback(zpool_handle_t * zhp,void * data)3416 list_callback(zpool_handle_t *zhp, void *data)
3417 {
3418 	list_cbdata_t *cbp = data;
3419 	nvlist_t *config;
3420 	nvlist_t *nvroot;
3421 
3422 	config = zpool_get_config(zhp, NULL);
3423 
3424 	print_pool(zhp, cbp);
3425 	if (!cbp->cb_verbose)
3426 		return (0);
3427 
3428 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3429 	    &nvroot) == 0);
3430 	print_list_stats(zhp, NULL, nvroot, cbp, 0);
3431 
3432 	return (0);
3433 }
3434 
3435 /*
3436  * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3437  *
3438  *	-H	Scripted mode.  Don't display headers, and separate properties
3439  *		by a single tab.
3440  *	-o	List of properties to display.  Defaults to
3441  *		"name,size,allocated,free,expandsize,fragmentation,capacity,"
3442  *		"dedupratio,health,altroot"
3443  *	-p	Diplay values in parsable (exact) format.
3444  *	-T	Display a timestamp in date(1) or Unix format
3445  *
3446  * List all pools in the system, whether or not they're healthy.  Output space
3447  * statistics for each one, as well as health status summary.
3448  */
3449 int
zpool_do_list(int argc,char ** argv)3450 zpool_do_list(int argc, char **argv)
3451 {
3452 	int c;
3453 	int ret;
3454 	list_cbdata_t cb = { 0 };
3455 	static char default_props[] =
3456 	    "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
3457 	    "capacity,dedupratio,health,altroot";
3458 	char *props = default_props;
3459 	unsigned long interval = 0, count = 0;
3460 	zpool_list_t *list;
3461 	boolean_t first = B_TRUE;
3462 
3463 	/* check options */
3464 	while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3465 		switch (c) {
3466 		case 'H':
3467 			cb.cb_scripted = B_TRUE;
3468 			break;
3469 		case 'o':
3470 			props = optarg;
3471 			break;
3472 		case 'p':
3473 			cb.cb_literal = B_TRUE;
3474 			break;
3475 		case 'T':
3476 			get_timestamp_arg(*optarg);
3477 			break;
3478 		case 'v':
3479 			cb.cb_verbose = B_TRUE;
3480 			break;
3481 		case ':':
3482 			(void) fprintf(stderr, gettext("missing argument for "
3483 			    "'%c' option\n"), optopt);
3484 			usage(B_FALSE);
3485 			break;
3486 		case '?':
3487 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3488 			    optopt);
3489 			usage(B_FALSE);
3490 		}
3491 	}
3492 
3493 	argc -= optind;
3494 	argv += optind;
3495 
3496 	get_interval_count(&argc, argv, &interval, &count);
3497 
3498 	if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3499 		usage(B_FALSE);
3500 
3501 	for (;;) {
3502 		if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3503 		    &ret)) == NULL)
3504 			return (1);
3505 
3506 		if (pool_list_count(list) == 0)
3507 			break;
3508 
3509 		cb.cb_namewidth = 0;
3510 		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3511 
3512 		if (timestamp_fmt != NODATE)
3513 			print_timestamp(timestamp_fmt);
3514 
3515 		if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3516 			print_header(&cb);
3517 			first = B_FALSE;
3518 		}
3519 		ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3520 
3521 		if (interval == 0)
3522 			break;
3523 
3524 		if (count != 0 && --count == 0)
3525 			break;
3526 
3527 		pool_list_free(list);
3528 		(void) sleep(interval);
3529 	}
3530 
3531 	if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3532 		(void) printf(gettext("no pools available\n"));
3533 		ret = 0;
3534 	}
3535 
3536 	pool_list_free(list);
3537 	zprop_free_list(cb.cb_proplist);
3538 	return (ret);
3539 }
3540 
3541 static int
zpool_do_attach_or_replace(int argc,char ** argv,int replacing)3542 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3543 {
3544 	boolean_t force = B_FALSE;
3545 	int c;
3546 	nvlist_t *nvroot;
3547 	char *poolname, *old_disk, *new_disk;
3548 	zpool_handle_t *zhp;
3549 	zpool_boot_label_t boot_type;
3550 	uint64_t boot_size;
3551 	int ret;
3552 
3553 	/* check options */
3554 	while ((c = getopt(argc, argv, "f")) != -1) {
3555 		switch (c) {
3556 		case 'f':
3557 			force = B_TRUE;
3558 			break;
3559 		case '?':
3560 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3561 			    optopt);
3562 			usage(B_FALSE);
3563 		}
3564 	}
3565 
3566 	argc -= optind;
3567 	argv += optind;
3568 
3569 	/* get pool name and check number of arguments */
3570 	if (argc < 1) {
3571 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3572 		usage(B_FALSE);
3573 	}
3574 
3575 	poolname = argv[0];
3576 
3577 	if (argc < 2) {
3578 		(void) fprintf(stderr,
3579 		    gettext("missing <device> specification\n"));
3580 		usage(B_FALSE);
3581 	}
3582 
3583 	old_disk = argv[1];
3584 
3585 	if (argc < 3) {
3586 		if (!replacing) {
3587 			(void) fprintf(stderr,
3588 			    gettext("missing <new_device> specification\n"));
3589 			usage(B_FALSE);
3590 		}
3591 		new_disk = old_disk;
3592 		argc -= 1;
3593 		argv += 1;
3594 	} else {
3595 		new_disk = argv[2];
3596 		argc -= 2;
3597 		argv += 2;
3598 	}
3599 
3600 	if (argc > 1) {
3601 		(void) fprintf(stderr, gettext("too many arguments\n"));
3602 		usage(B_FALSE);
3603 	}
3604 
3605 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3606 		return (1);
3607 
3608 	if (zpool_get_config(zhp, NULL) == NULL) {
3609 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3610 		    poolname);
3611 		zpool_close(zhp);
3612 		return (1);
3613 	}
3614 
3615 	if (zpool_is_bootable(zhp))
3616 		boot_type = ZPOOL_COPY_BOOT_LABEL;
3617 	else
3618 		boot_type = ZPOOL_NO_BOOT_LABEL;
3619 
3620 	boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3621 	nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3622 	    boot_type, boot_size, argc, argv);
3623 	if (nvroot == NULL) {
3624 		zpool_close(zhp);
3625 		return (1);
3626 	}
3627 
3628 	ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3629 
3630 	nvlist_free(nvroot);
3631 	zpool_close(zhp);
3632 
3633 	return (ret);
3634 }
3635 
3636 /*
3637  * zpool replace [-f] <pool> <device> <new_device>
3638  *
3639  *	-f	Force attach, even if <new_device> appears to be in use.
3640  *
3641  * Replace <device> with <new_device>.
3642  */
3643 /* ARGSUSED */
3644 int
zpool_do_replace(int argc,char ** argv)3645 zpool_do_replace(int argc, char **argv)
3646 {
3647 	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3648 }
3649 
3650 /*
3651  * zpool attach [-f] <pool> <device> <new_device>
3652  *
3653  *	-f	Force attach, even if <new_device> appears to be in use.
3654  *
3655  * Attach <new_device> to the mirror containing <device>.  If <device> is not
3656  * part of a mirror, then <device> will be transformed into a mirror of
3657  * <device> and <new_device>.  In either case, <new_device> will begin life
3658  * with a DTL of [0, now], and will immediately begin to resilver itself.
3659  */
3660 int
zpool_do_attach(int argc,char ** argv)3661 zpool_do_attach(int argc, char **argv)
3662 {
3663 	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3664 }
3665 
3666 /*
3667  * zpool detach [-f] <pool> <device>
3668  *
3669  *	-f	Force detach of <device>, even if DTLs argue against it
3670  *		(not supported yet)
3671  *
3672  * Detach a device from a mirror.  The operation will be refused if <device>
3673  * is the last device in the mirror, or if the DTLs indicate that this device
3674  * has the only valid copy of some data.
3675  */
3676 /* ARGSUSED */
3677 int
zpool_do_detach(int argc,char ** argv)3678 zpool_do_detach(int argc, char **argv)
3679 {
3680 	int c;
3681 	char *poolname, *path;
3682 	zpool_handle_t *zhp;
3683 	int ret;
3684 
3685 	/* check options */
3686 	while ((c = getopt(argc, argv, "f")) != -1) {
3687 		switch (c) {
3688 		case 'f':
3689 		case '?':
3690 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3691 			    optopt);
3692 			usage(B_FALSE);
3693 		}
3694 	}
3695 
3696 	argc -= optind;
3697 	argv += optind;
3698 
3699 	/* get pool name and check number of arguments */
3700 	if (argc < 1) {
3701 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3702 		usage(B_FALSE);
3703 	}
3704 
3705 	if (argc < 2) {
3706 		(void) fprintf(stderr,
3707 		    gettext("missing <device> specification\n"));
3708 		usage(B_FALSE);
3709 	}
3710 
3711 	poolname = argv[0];
3712 	path = argv[1];
3713 
3714 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3715 		return (1);
3716 
3717 	ret = zpool_vdev_detach(zhp, path);
3718 
3719 	zpool_close(zhp);
3720 
3721 	return (ret);
3722 }
3723 
3724 /*
3725  * zpool split [-n] [-o prop=val] ...
3726  *		[-o mntopt] ...
3727  *		[-R altroot] <pool> <newpool> [<device> ...]
3728  *
3729  *	-n	Do not split the pool, but display the resulting layout if
3730  *		it were to be split.
3731  *	-o	Set property=value, or set mount options.
3732  *	-R	Mount the split-off pool under an alternate root.
3733  *
3734  * Splits the named pool and gives it the new pool name.  Devices to be split
3735  * off may be listed, provided that no more than one device is specified
3736  * per top-level vdev mirror.  The newly split pool is left in an exported
3737  * state unless -R is specified.
3738  *
3739  * Restrictions: the top-level of the pool pool must only be made up of
3740  * mirrors; all devices in the pool must be healthy; no device may be
3741  * undergoing a resilvering operation.
3742  */
3743 int
zpool_do_split(int argc,char ** argv)3744 zpool_do_split(int argc, char **argv)
3745 {
3746 	char *srcpool, *newpool, *propval;
3747 	char *mntopts = NULL;
3748 	splitflags_t flags;
3749 	int c, ret = 0;
3750 	zpool_handle_t *zhp;
3751 	nvlist_t *config, *props = NULL;
3752 
3753 	flags.dryrun = B_FALSE;
3754 	flags.import = B_FALSE;
3755 
3756 	/* check options */
3757 	while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3758 		switch (c) {
3759 		case 'R':
3760 			flags.import = B_TRUE;
3761 			if (add_prop_list(
3762 			    zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3763 			    &props, B_TRUE) != 0) {
3764 				nvlist_free(props);
3765 				usage(B_FALSE);
3766 			}
3767 			break;
3768 		case 'n':
3769 			flags.dryrun = B_TRUE;
3770 			break;
3771 		case 'o':
3772 			if ((propval = strchr(optarg, '=')) != NULL) {
3773 				*propval = '\0';
3774 				propval++;
3775 				if (add_prop_list(optarg, propval,
3776 				    &props, B_TRUE) != 0) {
3777 					nvlist_free(props);
3778 					usage(B_FALSE);
3779 				}
3780 			} else {
3781 				mntopts = optarg;
3782 			}
3783 			break;
3784 		case ':':
3785 			(void) fprintf(stderr, gettext("missing argument for "
3786 			    "'%c' option\n"), optopt);
3787 			usage(B_FALSE);
3788 			break;
3789 		case '?':
3790 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3791 			    optopt);
3792 			usage(B_FALSE);
3793 			break;
3794 		}
3795 	}
3796 
3797 	if (!flags.import && mntopts != NULL) {
3798 		(void) fprintf(stderr, gettext("setting mntopts is only "
3799 		    "valid when importing the pool\n"));
3800 		usage(B_FALSE);
3801 	}
3802 
3803 	argc -= optind;
3804 	argv += optind;
3805 
3806 	if (argc < 1) {
3807 		(void) fprintf(stderr, gettext("Missing pool name\n"));
3808 		usage(B_FALSE);
3809 	}
3810 	if (argc < 2) {
3811 		(void) fprintf(stderr, gettext("Missing new pool name\n"));
3812 		usage(B_FALSE);
3813 	}
3814 
3815 	srcpool = argv[0];
3816 	newpool = argv[1];
3817 
3818 	argc -= 2;
3819 	argv += 2;
3820 
3821 	if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3822 		return (1);
3823 
3824 	config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3825 	if (config == NULL) {
3826 		ret = 1;
3827 	} else {
3828 		if (flags.dryrun) {
3829 			(void) printf(gettext("would create '%s' with the "
3830 			    "following layout:\n\n"), newpool);
3831 			print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3832 		}
3833 		nvlist_free(config);
3834 	}
3835 
3836 	zpool_close(zhp);
3837 
3838 	if (ret != 0 || flags.dryrun || !flags.import)
3839 		return (ret);
3840 
3841 	/*
3842 	 * The split was successful. Now we need to open the new
3843 	 * pool and import it.
3844 	 */
3845 	if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3846 		return (1);
3847 	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3848 	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3849 		ret = 1;
3850 		(void) fprintf(stderr, gettext("Split was successful, but "
3851 		    "the datasets could not all be mounted\n"));
3852 		(void) fprintf(stderr, gettext("Try doing '%s' with a "
3853 		    "different altroot\n"), "zpool import");
3854 	}
3855 	zpool_close(zhp);
3856 
3857 	return (ret);
3858 }
3859 
3860 
3861 
3862 /*
3863  * zpool online <pool> <device> ...
3864  */
3865 int
zpool_do_online(int argc,char ** argv)3866 zpool_do_online(int argc, char **argv)
3867 {
3868 	int c, i;
3869 	char *poolname;
3870 	zpool_handle_t *zhp;
3871 	int ret = 0;
3872 	vdev_state_t newstate;
3873 	int flags = 0;
3874 
3875 	/* check options */
3876 	while ((c = getopt(argc, argv, "et")) != -1) {
3877 		switch (c) {
3878 		case 'e':
3879 			flags |= ZFS_ONLINE_EXPAND;
3880 			break;
3881 		case 't':
3882 		case '?':
3883 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3884 			    optopt);
3885 			usage(B_FALSE);
3886 		}
3887 	}
3888 
3889 	argc -= optind;
3890 	argv += optind;
3891 
3892 	/* get pool name and check number of arguments */
3893 	if (argc < 1) {
3894 		(void) fprintf(stderr, gettext("missing pool name\n"));
3895 		usage(B_FALSE);
3896 	}
3897 	if (argc < 2) {
3898 		(void) fprintf(stderr, gettext("missing device name\n"));
3899 		usage(B_FALSE);
3900 	}
3901 
3902 	poolname = argv[0];
3903 
3904 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3905 		return (1);
3906 
3907 	for (i = 1; i < argc; i++) {
3908 		if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3909 			if (newstate != VDEV_STATE_HEALTHY) {
3910 				(void) printf(gettext("warning: device '%s' "
3911 				    "onlined, but remains in faulted state\n"),
3912 				    argv[i]);
3913 				if (newstate == VDEV_STATE_FAULTED)
3914 					(void) printf(gettext("use 'zpool "
3915 					    "clear' to restore a faulted "
3916 					    "device\n"));
3917 				else
3918 					(void) printf(gettext("use 'zpool "
3919 					    "replace' to replace devices "
3920 					    "that are no longer present\n"));
3921 			}
3922 		} else {
3923 			ret = 1;
3924 		}
3925 	}
3926 
3927 	zpool_close(zhp);
3928 
3929 	return (ret);
3930 }
3931 
3932 /*
3933  * zpool offline [-ft] <pool> <device> ...
3934  *
3935  *	-f	Force the device into the offline state, even if doing
3936  *		so would appear to compromise pool availability.
3937  *		(not supported yet)
3938  *
3939  *	-t	Only take the device off-line temporarily.  The offline
3940  *		state will not be persistent across reboots.
3941  */
3942 /* ARGSUSED */
3943 int
zpool_do_offline(int argc,char ** argv)3944 zpool_do_offline(int argc, char **argv)
3945 {
3946 	int c, i;
3947 	char *poolname;
3948 	zpool_handle_t *zhp;
3949 	int ret = 0;
3950 	boolean_t istmp = B_FALSE;
3951 
3952 	/* check options */
3953 	while ((c = getopt(argc, argv, "ft")) != -1) {
3954 		switch (c) {
3955 		case 't':
3956 			istmp = B_TRUE;
3957 			break;
3958 		case 'f':
3959 		case '?':
3960 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3961 			    optopt);
3962 			usage(B_FALSE);
3963 		}
3964 	}
3965 
3966 	argc -= optind;
3967 	argv += optind;
3968 
3969 	/* get pool name and check number of arguments */
3970 	if (argc < 1) {
3971 		(void) fprintf(stderr, gettext("missing pool name\n"));
3972 		usage(B_FALSE);
3973 	}
3974 	if (argc < 2) {
3975 		(void) fprintf(stderr, gettext("missing device name\n"));
3976 		usage(B_FALSE);
3977 	}
3978 
3979 	poolname = argv[0];
3980 
3981 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3982 		return (1);
3983 
3984 	for (i = 1; i < argc; i++) {
3985 		if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3986 			ret = 1;
3987 	}
3988 
3989 	zpool_close(zhp);
3990 
3991 	return (ret);
3992 }
3993 
3994 /*
3995  * zpool clear <pool> [device]
3996  *
3997  * Clear all errors associated with a pool or a particular device.
3998  */
3999 int
zpool_do_clear(int argc,char ** argv)4000 zpool_do_clear(int argc, char **argv)
4001 {
4002 	int c;
4003 	int ret = 0;
4004 	boolean_t dryrun = B_FALSE;
4005 	boolean_t do_rewind = B_FALSE;
4006 	boolean_t xtreme_rewind = B_FALSE;
4007 	uint32_t rewind_policy = ZPOOL_NO_REWIND;
4008 	nvlist_t *policy = NULL;
4009 	zpool_handle_t *zhp;
4010 	char *pool, *device;
4011 
4012 	/* check options */
4013 	while ((c = getopt(argc, argv, "FnX")) != -1) {
4014 		switch (c) {
4015 		case 'F':
4016 			do_rewind = B_TRUE;
4017 			break;
4018 		case 'n':
4019 			dryrun = B_TRUE;
4020 			break;
4021 		case 'X':
4022 			xtreme_rewind = B_TRUE;
4023 			break;
4024 		case '?':
4025 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4026 			    optopt);
4027 			usage(B_FALSE);
4028 		}
4029 	}
4030 
4031 	argc -= optind;
4032 	argv += optind;
4033 
4034 	if (argc < 1) {
4035 		(void) fprintf(stderr, gettext("missing pool name\n"));
4036 		usage(B_FALSE);
4037 	}
4038 
4039 	if (argc > 2) {
4040 		(void) fprintf(stderr, gettext("too many arguments\n"));
4041 		usage(B_FALSE);
4042 	}
4043 
4044 	if ((dryrun || xtreme_rewind) && !do_rewind) {
4045 		(void) fprintf(stderr,
4046 		    gettext("-n or -X only meaningful with -F\n"));
4047 		usage(B_FALSE);
4048 	}
4049 	if (dryrun)
4050 		rewind_policy = ZPOOL_TRY_REWIND;
4051 	else if (do_rewind)
4052 		rewind_policy = ZPOOL_DO_REWIND;
4053 	if (xtreme_rewind)
4054 		rewind_policy |= ZPOOL_EXTREME_REWIND;
4055 
4056 	/* In future, further rewind policy choices can be passed along here */
4057 	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
4058 	    nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
4059 	    rewind_policy) != 0) {
4060 		return (1);
4061 	}
4062 
4063 	pool = argv[0];
4064 	device = argc == 2 ? argv[1] : NULL;
4065 
4066 	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
4067 		nvlist_free(policy);
4068 		return (1);
4069 	}
4070 
4071 	if (zpool_clear(zhp, device, policy) != 0)
4072 		ret = 1;
4073 
4074 	zpool_close(zhp);
4075 
4076 	nvlist_free(policy);
4077 
4078 	return (ret);
4079 }
4080 
4081 /*
4082  * zpool reguid <pool>
4083  */
4084 int
zpool_do_reguid(int argc,char ** argv)4085 zpool_do_reguid(int argc, char **argv)
4086 {
4087 	int c;
4088 	char *poolname;
4089 	zpool_handle_t *zhp;
4090 	int ret = 0;
4091 
4092 	/* check options */
4093 	while ((c = getopt(argc, argv, "")) != -1) {
4094 		switch (c) {
4095 		case '?':
4096 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4097 			    optopt);
4098 			usage(B_FALSE);
4099 		}
4100 	}
4101 
4102 	argc -= optind;
4103 	argv += optind;
4104 
4105 	/* get pool name and check number of arguments */
4106 	if (argc < 1) {
4107 		(void) fprintf(stderr, gettext("missing pool name\n"));
4108 		usage(B_FALSE);
4109 	}
4110 
4111 	if (argc > 1) {
4112 		(void) fprintf(stderr, gettext("too many arguments\n"));
4113 		usage(B_FALSE);
4114 	}
4115 
4116 	poolname = argv[0];
4117 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4118 		return (1);
4119 
4120 	ret = zpool_reguid(zhp);
4121 
4122 	zpool_close(zhp);
4123 	return (ret);
4124 }
4125 
4126 
4127 /*
4128  * zpool reopen <pool>
4129  *
4130  * Reopen the pool so that the kernel can update the sizes of all vdevs.
4131  */
4132 int
zpool_do_reopen(int argc,char ** argv)4133 zpool_do_reopen(int argc, char **argv)
4134 {
4135 	int c;
4136 	int ret = 0;
4137 	zpool_handle_t *zhp;
4138 	char *pool;
4139 
4140 	/* check options */
4141 	while ((c = getopt(argc, argv, "")) != -1) {
4142 		switch (c) {
4143 		case '?':
4144 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4145 			    optopt);
4146 			usage(B_FALSE);
4147 		}
4148 	}
4149 
4150 	argc--;
4151 	argv++;
4152 
4153 	if (argc < 1) {
4154 		(void) fprintf(stderr, gettext("missing pool name\n"));
4155 		usage(B_FALSE);
4156 	}
4157 
4158 	if (argc > 1) {
4159 		(void) fprintf(stderr, gettext("too many arguments\n"));
4160 		usage(B_FALSE);
4161 	}
4162 
4163 	pool = argv[0];
4164 	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4165 		return (1);
4166 
4167 	ret = zpool_reopen(zhp);
4168 	zpool_close(zhp);
4169 	return (ret);
4170 }
4171 
4172 typedef struct scrub_cbdata {
4173 	int	cb_type;
4174 	int	cb_argc;
4175 	char	**cb_argv;
4176 	pool_scrub_cmd_t cb_scrub_cmd;
4177 } scrub_cbdata_t;
4178 
4179 static boolean_t
zpool_has_checkpoint(zpool_handle_t * zhp)4180 zpool_has_checkpoint(zpool_handle_t *zhp)
4181 {
4182 	nvlist_t *config, *nvroot;
4183 
4184 	config = zpool_get_config(zhp, NULL);
4185 
4186 	if (config != NULL) {
4187 		pool_checkpoint_stat_t *pcs = NULL;
4188 		uint_t c;
4189 
4190 		nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4191 		(void) nvlist_lookup_uint64_array(nvroot,
4192 		    ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4193 
4194 		if (pcs == NULL || pcs->pcs_state == CS_NONE)
4195 			return (B_FALSE);
4196 
4197 		assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
4198 		    pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4199 		return (B_TRUE);
4200 	}
4201 
4202 	return (B_FALSE);
4203 }
4204 
4205 int
scrub_callback(zpool_handle_t * zhp,void * data)4206 scrub_callback(zpool_handle_t *zhp, void *data)
4207 {
4208 	scrub_cbdata_t *cb = data;
4209 	int err;
4210 
4211 	/*
4212 	 * Ignore faulted pools.
4213 	 */
4214 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4215 		(void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4216 		    "currently unavailable\n"), zpool_get_name(zhp));
4217 		return (1);
4218 	}
4219 
4220 	err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4221 
4222 	if (err == 0 && zpool_has_checkpoint(zhp) &&
4223 	    cb->cb_type == POOL_SCAN_SCRUB) {
4224 		(void) printf(gettext("warning: will not scrub state that "
4225 		    "belongs to the checkpoint of pool '%s'\n"),
4226 		    zpool_get_name(zhp));
4227 	}
4228 
4229 	return (err != 0);
4230 }
4231 
4232 /*
4233  * zpool scrub [-s | -p] <pool> ...
4234  *
4235  *	-s	Stop.  Stops any in-progress scrub.
4236  *	-p	Pause. Pause in-progress scrub.
4237  */
4238 int
zpool_do_scrub(int argc,char ** argv)4239 zpool_do_scrub(int argc, char **argv)
4240 {
4241 	int c;
4242 	scrub_cbdata_t cb;
4243 
4244 	cb.cb_type = POOL_SCAN_SCRUB;
4245 	cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4246 
4247 	/* check options */
4248 	while ((c = getopt(argc, argv, "sp")) != -1) {
4249 		switch (c) {
4250 		case 's':
4251 			cb.cb_type = POOL_SCAN_NONE;
4252 			break;
4253 		case 'p':
4254 			cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4255 			break;
4256 		case '?':
4257 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4258 			    optopt);
4259 			usage(B_FALSE);
4260 		}
4261 	}
4262 
4263 	if (cb.cb_type == POOL_SCAN_NONE &&
4264 	    cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4265 		(void) fprintf(stderr, gettext("invalid option combination: "
4266 		    "-s and -p are mutually exclusive\n"));
4267 		usage(B_FALSE);
4268 	}
4269 
4270 	cb.cb_argc = argc;
4271 	cb.cb_argv = argv;
4272 	argc -= optind;
4273 	argv += optind;
4274 
4275 	if (argc < 1) {
4276 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
4277 		usage(B_FALSE);
4278 	}
4279 
4280 	return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4281 }
4282 
4283 static void
zpool_collect_leaves(zpool_handle_t * zhp,nvlist_t * nvroot,nvlist_t * res)4284 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
4285 {
4286 	uint_t children = 0;
4287 	nvlist_t **child;
4288 	uint_t i;
4289 
4290 	(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4291 	    &child, &children);
4292 
4293 	if (children == 0) {
4294 		char *path = zpool_vdev_name(g_zfs, zhp, nvroot, B_FALSE);
4295 		fnvlist_add_boolean(res, path);
4296 		free(path);
4297 		return;
4298 	}
4299 
4300 	for (i = 0; i < children; i++) {
4301 		zpool_collect_leaves(zhp, child[i], res);
4302 	}
4303 }
4304 
4305 /*
4306  * zpool initialize [-cs] <pool> [<vdev> ...]
4307  * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
4308  * if none specified.
4309  *
4310  *	-c	Cancel. Ends active initializing.
4311  *	-s	Suspend. Initializing can then be restarted with no flags.
4312  */
4313 int
zpool_do_initialize(int argc,char ** argv)4314 zpool_do_initialize(int argc, char **argv)
4315 {
4316 	int c;
4317 	char *poolname;
4318 	zpool_handle_t *zhp;
4319 	nvlist_t *vdevs;
4320 	int err = 0;
4321 
4322 	struct option long_options[] = {
4323 		{"cancel",	no_argument,		NULL, 'c'},
4324 		{"suspend",	no_argument,		NULL, 's'},
4325 		{0, 0, 0, 0}
4326 	};
4327 
4328 	pool_initialize_func_t cmd_type = POOL_INITIALIZE_DO;
4329 	while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) {
4330 		switch (c) {
4331 		case 'c':
4332 			if (cmd_type != POOL_INITIALIZE_DO) {
4333 				(void) fprintf(stderr, gettext("-c cannot be "
4334 				    "combined with other options\n"));
4335 				usage(B_FALSE);
4336 			}
4337 			cmd_type = POOL_INITIALIZE_CANCEL;
4338 			break;
4339 		case 's':
4340 			if (cmd_type != POOL_INITIALIZE_DO) {
4341 				(void) fprintf(stderr, gettext("-s cannot be "
4342 				    "combined with other options\n"));
4343 				usage(B_FALSE);
4344 			}
4345 			cmd_type = POOL_INITIALIZE_SUSPEND;
4346 			break;
4347 		case '?':
4348 			if (optopt != 0) {
4349 				(void) fprintf(stderr,
4350 				    gettext("invalid option '%c'\n"), optopt);
4351 			} else {
4352 				(void) fprintf(stderr,
4353 				    gettext("invalid option '%s'\n"),
4354 				    argv[optind - 1]);
4355 			}
4356 			usage(B_FALSE);
4357 		}
4358 	}
4359 
4360 	argc -= optind;
4361 	argv += optind;
4362 
4363 	if (argc < 1) {
4364 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
4365 		usage(B_FALSE);
4366 		return (-1);
4367 	}
4368 
4369 	poolname = argv[0];
4370 	zhp = zpool_open(g_zfs, poolname);
4371 	if (zhp == NULL)
4372 		return (-1);
4373 
4374 	vdevs = fnvlist_alloc();
4375 	if (argc == 1) {
4376 		/* no individual leaf vdevs specified, so add them all */
4377 		nvlist_t *config = zpool_get_config(zhp, NULL);
4378 		nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
4379 		    ZPOOL_CONFIG_VDEV_TREE);
4380 		zpool_collect_leaves(zhp, nvroot, vdevs);
4381 	} else {
4382 		int i;
4383 		for (i = 1; i < argc; i++) {
4384 			fnvlist_add_boolean(vdevs, argv[i]);
4385 		}
4386 	}
4387 
4388 	err = zpool_initialize(zhp, cmd_type, vdevs);
4389 
4390 	fnvlist_free(vdevs);
4391 	zpool_close(zhp);
4392 
4393 	return (err);
4394 }
4395 
4396 typedef struct status_cbdata {
4397 	int		cb_count;
4398 	boolean_t	cb_allpools;
4399 	boolean_t	cb_verbose;
4400 	boolean_t	cb_explain;
4401 	boolean_t	cb_first;
4402 	boolean_t	cb_dedup_stats;
4403 } status_cbdata_t;
4404 
4405 /*
4406  * Print out detailed scrub status.
4407  */
4408 static void
print_scan_status(pool_scan_stat_t * ps)4409 print_scan_status(pool_scan_stat_t *ps)
4410 {
4411 	time_t start, end, pause;
4412 	uint64_t total_secs_left;
4413 	uint64_t elapsed, secs_left, mins_left, hours_left, days_left;
4414 	uint64_t pass_scanned, scanned, pass_issued, issued, total;
4415 	uint_t scan_rate, issue_rate;
4416 	double fraction_done;
4417 	char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
4418 	char srate_buf[7], irate_buf[7];
4419 
4420 	(void) printf(gettext("  scan: "));
4421 
4422 	/* If there's never been a scan, there's not much to say. */
4423 	if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4424 	    ps->pss_func >= POOL_SCAN_FUNCS) {
4425 		(void) printf(gettext("none requested\n"));
4426 		return;
4427 	}
4428 
4429 	start = ps->pss_start_time;
4430 	end = ps->pss_end_time;
4431 	pause = ps->pss_pass_scrub_pause;
4432 
4433 	zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4434 
4435 	assert(ps->pss_func == POOL_SCAN_SCRUB ||
4436 	    ps->pss_func == POOL_SCAN_RESILVER);
4437 
4438 	/* Scan is finished or canceled. */
4439 	if (ps->pss_state == DSS_FINISHED) {
4440 		total_secs_left = end - start;
4441 		days_left = total_secs_left / 60 / 60 / 24;
4442 		hours_left = (total_secs_left / 60 / 60) % 24;
4443 		mins_left = (total_secs_left / 60) % 60;
4444 		secs_left = (total_secs_left % 60);
4445 
4446 		if (ps->pss_func == POOL_SCAN_SCRUB) {
4447 			(void) printf(gettext("scrub repaired %s "
4448                             "in %llu days %02llu:%02llu:%02llu "
4449 			    "with %llu errors on %s"), processed_buf,
4450                             (u_longlong_t)days_left, (u_longlong_t)hours_left,
4451                             (u_longlong_t)mins_left, (u_longlong_t)secs_left,
4452                             (u_longlong_t)ps->pss_errors, ctime(&end));
4453 		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4454                        (void) printf(gettext("resilvered %s "
4455                            "in %llu days %02llu:%02llu:%02llu "
4456                            "with %llu errors on %s"), processed_buf,
4457                            (u_longlong_t)days_left, (u_longlong_t)hours_left,
4458                            (u_longlong_t)mins_left, (u_longlong_t)secs_left,
4459                            (u_longlong_t)ps->pss_errors, ctime(&end));
4460 
4461 		}
4462 
4463 		return;
4464 	} else if (ps->pss_state == DSS_CANCELED) {
4465 		if (ps->pss_func == POOL_SCAN_SCRUB) {
4466 			(void) printf(gettext("scrub canceled on %s"),
4467 			    ctime(&end));
4468 		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4469 			(void) printf(gettext("resilver canceled on %s"),
4470 			    ctime(&end));
4471 		}
4472 		return;
4473 	}
4474 
4475 	assert(ps->pss_state == DSS_SCANNING);
4476 
4477 	/* Scan is in progress. Resilvers can't be paused. */
4478 	if (ps->pss_func == POOL_SCAN_SCRUB) {
4479 		if (pause == 0) {
4480 			(void) printf(gettext("scrub in progress since %s"),
4481 			    ctime(&start));
4482 		} else {
4483 			(void) printf(gettext("scrub paused since %s"),
4484 			    ctime(&pause));
4485 			(void) printf(gettext("\tscrub started on %s"),
4486 			    ctime(&start));
4487 		}
4488 	} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4489 		(void) printf(gettext("resilver in progress since %s"),
4490 		    ctime(&start));
4491 	}
4492 
4493 	scanned = ps->pss_examined;
4494 	pass_scanned = ps->pss_pass_exam;
4495 	issued = ps->pss_issued;
4496 	pass_issued = ps->pss_pass_issued;
4497 	total = ps->pss_to_examine;
4498 
4499 	/* we are only done with a block once we have issued the IO for it */
4500 	fraction_done = (double)issued / total;
4501 
4502 	/* elapsed time for this pass, rounding up to 1 if it's 0 */
4503 	elapsed = time(NULL) - ps->pss_pass_start;
4504 	elapsed -= ps->pss_pass_scrub_spent_paused;
4505 	elapsed = (elapsed != 0) ? elapsed : 1;
4506 
4507 	scan_rate = pass_scanned / elapsed;
4508 	issue_rate = pass_issued / elapsed;
4509 	total_secs_left = (issue_rate != 0) ?
4510 	    ((total - issued) / issue_rate) : UINT64_MAX;
4511 
4512 	days_left = total_secs_left / 60 / 60 / 24;
4513 	hours_left = (total_secs_left / 60 / 60) % 24;
4514 	mins_left = (total_secs_left / 60) % 60;
4515 	secs_left = (total_secs_left % 60);
4516 
4517 	/* format all of the numbers we will be reporting */
4518 	zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf));
4519 	zfs_nicenum(issued, issued_buf, sizeof (issued_buf));
4520 	zfs_nicenum(total, total_buf, sizeof (total_buf));
4521 	zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf));
4522 	zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf));
4523 
4524 	/* doo not print estimated time if we have a paused scrub */
4525 	if (pause == 0) {
4526 		(void) printf(gettext("\t%s scanned at %s/s, "
4527 		    "%s issued at %s/s, %s total\n"),
4528 		    scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
4529 	} else {
4530 		(void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
4531                     scanned_buf, issued_buf, total_buf);
4532 	}
4533 
4534 	if (ps->pss_func == POOL_SCAN_RESILVER) {
4535 		(void) printf(gettext("\t%s resilvered, %.2f%% done"),
4536 		    processed_buf, 100 * fraction_done);
4537 	} else if (ps->pss_func == POOL_SCAN_SCRUB) {
4538 		(void) printf(gettext("\t%s repaired, %.2f%% done"),
4539 		    processed_buf, 100 * fraction_done);
4540 	}
4541 
4542 	if (pause == 0) {
4543 		if (issue_rate >= 10 * 1024 * 1024) {
4544 			(void) printf(gettext(", %llu days "
4545                             "%02llu:%02llu:%02llu to go\n"),
4546                             (u_longlong_t)days_left, (u_longlong_t)hours_left,
4547                             (u_longlong_t)mins_left, (u_longlong_t)secs_left);
4548 		} else {
4549 			(void) printf(gettext(", no estimated "
4550                             "completion time\n"));
4551 		}
4552 	} else {
4553 		(void) printf(gettext("\n"));
4554 	}
4555 }
4556 
4557 /*
4558  * As we don't scrub checkpointed blocks, we want to warn the
4559  * user that we skipped scanning some blocks if a checkpoint exists
4560  * or existed at any time during the scan.
4561  */
4562 static void
print_checkpoint_scan_warning(pool_scan_stat_t * ps,pool_checkpoint_stat_t * pcs)4563 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
4564 {
4565 	if (ps == NULL || pcs == NULL)
4566 		return;
4567 
4568 	if (pcs->pcs_state == CS_NONE ||
4569 	    pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
4570 		return;
4571 
4572 	assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
4573 
4574 	if (ps->pss_state == DSS_NONE)
4575 		return;
4576 
4577 	if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
4578 	    ps->pss_end_time < pcs->pcs_start_time)
4579 		return;
4580 
4581 	if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
4582 		(void) printf(gettext("    scan warning: skipped blocks "
4583 		    "that are only referenced by the checkpoint.\n"));
4584 	} else {
4585 		assert(ps->pss_state == DSS_SCANNING);
4586 		(void) printf(gettext("    scan warning: skipping blocks "
4587 		    "that are only referenced by the checkpoint.\n"));
4588 	}
4589 }
4590 
4591 /*
4592  * Print out detailed removal status.
4593  */
4594 static void
print_removal_status(zpool_handle_t * zhp,pool_removal_stat_t * prs)4595 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4596 {
4597 	char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4598 	time_t start, end;
4599 	nvlist_t *config, *nvroot;
4600 	nvlist_t **child;
4601 	uint_t children;
4602 	char *vdev_name;
4603 
4604 	if (prs == NULL || prs->prs_state == DSS_NONE)
4605 		return;
4606 
4607 	/*
4608 	 * Determine name of vdev.
4609 	 */
4610 	config = zpool_get_config(zhp, NULL);
4611 	nvroot = fnvlist_lookup_nvlist(config,
4612 	    ZPOOL_CONFIG_VDEV_TREE);
4613 	verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4614 	    &child, &children) == 0);
4615 	assert(prs->prs_removing_vdev < children);
4616 	vdev_name = zpool_vdev_name(g_zfs, zhp,
4617 	    child[prs->prs_removing_vdev], B_TRUE);
4618 
4619 	(void) printf(gettext("remove: "));
4620 
4621 	start = prs->prs_start_time;
4622 	end = prs->prs_end_time;
4623 	zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4624 
4625 	/*
4626 	 * Removal is finished or canceled.
4627 	 */
4628 	if (prs->prs_state == DSS_FINISHED) {
4629 		uint64_t minutes_taken = (end - start) / 60;
4630 
4631 		(void) printf(gettext("Removal of vdev %llu copied %s "
4632 		    "in %lluh%um, completed on %s"),
4633 		    (longlong_t)prs->prs_removing_vdev,
4634 		    copied_buf,
4635 		    (u_longlong_t)(minutes_taken / 60),
4636 		    (uint_t)(minutes_taken % 60),
4637 		    ctime((time_t *)&end));
4638 	} else if (prs->prs_state == DSS_CANCELED) {
4639 		(void) printf(gettext("Removal of %s canceled on %s"),
4640 		    vdev_name, ctime(&end));
4641 	} else {
4642 		uint64_t copied, total, elapsed, mins_left, hours_left;
4643 		double fraction_done;
4644 		uint_t rate;
4645 
4646 		assert(prs->prs_state == DSS_SCANNING);
4647 
4648 		/*
4649 		 * Removal is in progress.
4650 		 */
4651 		(void) printf(gettext(
4652 		    "Evacuation of %s in progress since %s"),
4653 		    vdev_name, ctime(&start));
4654 
4655 		copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4656 		total = prs->prs_to_copy;
4657 		fraction_done = (double)copied / total;
4658 
4659 		/* elapsed time for this pass */
4660 		elapsed = time(NULL) - prs->prs_start_time;
4661 		elapsed = elapsed > 0 ? elapsed : 1;
4662 		rate = copied / elapsed;
4663 		rate = rate > 0 ? rate : 1;
4664 		mins_left = ((total - copied) / rate) / 60;
4665 		hours_left = mins_left / 60;
4666 
4667 		zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4668 		zfs_nicenum(total, total_buf, sizeof (total_buf));
4669 		zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4670 
4671 		/*
4672 		 * do not print estimated time if hours_left is more than
4673 		 * 30 days
4674 		 */
4675 		(void) printf(gettext("    %s copied out of %s at %s/s, "
4676 		    "%.2f%% done"),
4677 		    examined_buf, total_buf, rate_buf, 100 * fraction_done);
4678 		if (hours_left < (30 * 24)) {
4679 			(void) printf(gettext(", %lluh%um to go\n"),
4680 			    (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4681 		} else {
4682 			(void) printf(gettext(
4683 			    ", (copy is slow, no estimated time)\n"));
4684 		}
4685 	}
4686 
4687 	if (prs->prs_mapping_memory > 0) {
4688 		char mem_buf[7];
4689 		zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4690 		(void) printf(gettext("    %s memory used for "
4691 		    "removed device mappings\n"),
4692 		    mem_buf);
4693 	}
4694 }
4695 
4696 static void
print_checkpoint_status(pool_checkpoint_stat_t * pcs)4697 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
4698 {
4699 	time_t start;
4700 	char space_buf[7];
4701 
4702 	if (pcs == NULL || pcs->pcs_state == CS_NONE)
4703 		return;
4704 
4705 	(void) printf(gettext("checkpoint: "));
4706 
4707 	start = pcs->pcs_start_time;
4708 	zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
4709 
4710 	if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
4711 		char *date = ctime(&start);
4712 
4713 		/*
4714 		 * ctime() adds a newline at the end of the generated
4715 		 * string, thus the weird format specifier and the
4716 		 * strlen() call used to chop it off from the output.
4717 		 */
4718 		(void) printf(gettext("created %.*s, consumes %s\n"),
4719 		    strlen(date) - 1, date, space_buf);
4720 		return;
4721 	}
4722 
4723 	assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4724 
4725 	(void) printf(gettext("discarding, %s remaining.\n"),
4726 	    space_buf);
4727 }
4728 
4729 static void
print_error_log(zpool_handle_t * zhp)4730 print_error_log(zpool_handle_t *zhp)
4731 {
4732 	nvlist_t *nverrlist = NULL;
4733 	nvpair_t *elem;
4734 	char *pathname;
4735 	size_t len = MAXPATHLEN * 2;
4736 
4737 	if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4738 		(void) printf("errors: List of errors unavailable "
4739 		    "(insufficient privileges)\n");
4740 		return;
4741 	}
4742 
4743 	(void) printf("errors: Permanent errors have been "
4744 	    "detected in the following files:\n\n");
4745 
4746 	pathname = safe_malloc(len);
4747 	elem = NULL;
4748 	while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4749 		nvlist_t *nv;
4750 		uint64_t dsobj, obj;
4751 
4752 		verify(nvpair_value_nvlist(elem, &nv) == 0);
4753 		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4754 		    &dsobj) == 0);
4755 		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4756 		    &obj) == 0);
4757 		zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4758 		(void) printf("%7s %s\n", "", pathname);
4759 	}
4760 	free(pathname);
4761 	nvlist_free(nverrlist);
4762 }
4763 
4764 static void
print_spares(zpool_handle_t * zhp,nvlist_t ** spares,uint_t nspares,int namewidth)4765 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4766     int namewidth)
4767 {
4768 	uint_t i;
4769 	char *name;
4770 
4771 	if (nspares == 0)
4772 		return;
4773 
4774 	(void) printf(gettext("\tspares\n"));
4775 
4776 	for (i = 0; i < nspares; i++) {
4777 		name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4778 		print_status_config(zhp, name, spares[i],
4779 		    namewidth, 2, B_TRUE);
4780 		free(name);
4781 	}
4782 }
4783 
4784 static void
print_l2cache(zpool_handle_t * zhp,nvlist_t ** l2cache,uint_t nl2cache,int namewidth)4785 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4786     int namewidth)
4787 {
4788 	uint_t i;
4789 	char *name;
4790 
4791 	if (nl2cache == 0)
4792 		return;
4793 
4794 	(void) printf(gettext("\tcache\n"));
4795 
4796 	for (i = 0; i < nl2cache; i++) {
4797 		name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4798 		print_status_config(zhp, name, l2cache[i],
4799 		    namewidth, 2, B_FALSE);
4800 		free(name);
4801 	}
4802 }
4803 
4804 static void
print_dedup_stats(nvlist_t * config)4805 print_dedup_stats(nvlist_t *config)
4806 {
4807 	ddt_histogram_t *ddh;
4808 	ddt_stat_t *dds;
4809 	ddt_object_t *ddo;
4810 	uint_t c;
4811 
4812 	/*
4813 	 * If the pool was faulted then we may not have been able to
4814 	 * obtain the config. Otherwise, if we have anything in the dedup
4815 	 * table continue processing the stats.
4816 	 */
4817 	if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4818 	    (uint64_t **)&ddo, &c) != 0)
4819 		return;
4820 
4821 	(void) printf("\n");
4822 	(void) printf(gettext(" dedup: "));
4823 	if (ddo->ddo_count == 0) {
4824 		(void) printf(gettext("no DDT entries\n"));
4825 		return;
4826 	}
4827 
4828 	(void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4829 	    (u_longlong_t)ddo->ddo_count,
4830 	    (u_longlong_t)ddo->ddo_dspace,
4831 	    (u_longlong_t)ddo->ddo_mspace);
4832 
4833 	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4834 	    (uint64_t **)&dds, &c) == 0);
4835 	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4836 	    (uint64_t **)&ddh, &c) == 0);
4837 	zpool_dump_ddt(dds, ddh);
4838 }
4839 
4840 /*
4841  * Display a summary of pool status.  Displays a summary such as:
4842  *
4843  *        pool: tank
4844  *	status: DEGRADED
4845  *	reason: One or more devices ...
4846  *         see: http://illumos.org/msg/ZFS-xxxx-01
4847  *	config:
4848  *		mirror		DEGRADED
4849  *                c1t0d0	OK
4850  *                c2t0d0	UNAVAIL
4851  *
4852  * When given the '-v' option, we print out the complete config.  If the '-e'
4853  * option is specified, then we print out error rate information as well.
4854  */
4855 int
status_callback(zpool_handle_t * zhp,void * data)4856 status_callback(zpool_handle_t *zhp, void *data)
4857 {
4858 	status_cbdata_t *cbp = data;
4859 	nvlist_t *config, *nvroot;
4860 	char *msgid;
4861 	int reason;
4862 	const char *health;
4863 	uint_t c;
4864 	vdev_stat_t *vs;
4865 
4866 	config = zpool_get_config(zhp, NULL);
4867 	reason = zpool_get_status(zhp, &msgid);
4868 
4869 	cbp->cb_count++;
4870 
4871 	/*
4872 	 * If we were given 'zpool status -x', only report those pools with
4873 	 * problems.
4874 	 */
4875 	if (cbp->cb_explain &&
4876 	    (reason == ZPOOL_STATUS_OK ||
4877 	    reason == ZPOOL_STATUS_VERSION_OLDER ||
4878 	    reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
4879 	    reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4880 		if (!cbp->cb_allpools) {
4881 			(void) printf(gettext("pool '%s' is healthy\n"),
4882 			    zpool_get_name(zhp));
4883 			if (cbp->cb_first)
4884 				cbp->cb_first = B_FALSE;
4885 		}
4886 		return (0);
4887 	}
4888 
4889 	if (cbp->cb_first)
4890 		cbp->cb_first = B_FALSE;
4891 	else
4892 		(void) printf("\n");
4893 
4894 	nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4895 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4896 	    (uint64_t **)&vs, &c) == 0);
4897 	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4898 
4899 	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4900 	(void) printf(gettext(" state: %s\n"), health);
4901 
4902 	switch (reason) {
4903 	case ZPOOL_STATUS_MISSING_DEV_R:
4904 		(void) printf(gettext("status: One or more devices could not "
4905 		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
4906 		    "continue functioning in a degraded state.\n"));
4907 		(void) printf(gettext("action: Attach the missing device and "
4908 		    "online it using 'zpool online'.\n"));
4909 		break;
4910 
4911 	case ZPOOL_STATUS_MISSING_DEV_NR:
4912 		(void) printf(gettext("status: One or more devices could not "
4913 		    "be opened.  There are insufficient\n\treplicas for the "
4914 		    "pool to continue functioning.\n"));
4915 		(void) printf(gettext("action: Attach the missing device and "
4916 		    "online it using 'zpool online'.\n"));
4917 		break;
4918 
4919 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
4920 		(void) printf(gettext("status: One or more devices could not "
4921 		    "be used because the label is missing or\n\tinvalid.  "
4922 		    "Sufficient replicas exist for the pool to continue\n\t"
4923 		    "functioning in a degraded state.\n"));
4924 		(void) printf(gettext("action: Replace the device using "
4925 		    "'zpool replace'.\n"));
4926 		break;
4927 
4928 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4929 		(void) printf(gettext("status: One or more devices could not "
4930 		    "be used because the label is missing \n\tor invalid.  "
4931 		    "There are insufficient replicas for the pool to "
4932 		    "continue\n\tfunctioning.\n"));
4933 		zpool_explain_recover(zpool_get_handle(zhp),
4934 		    zpool_get_name(zhp), reason, config);
4935 		break;
4936 
4937 	case ZPOOL_STATUS_FAILING_DEV:
4938 		(void) printf(gettext("status: One or more devices has "
4939 		    "experienced an unrecoverable error.  An\n\tattempt was "
4940 		    "made to correct the error.  Applications are "
4941 		    "unaffected.\n"));
4942 		(void) printf(gettext("action: Determine if the device needs "
4943 		    "to be replaced, and clear the errors\n\tusing "
4944 		    "'zpool clear' or replace the device with 'zpool "
4945 		    "replace'.\n"));
4946 		break;
4947 
4948 	case ZPOOL_STATUS_OFFLINE_DEV:
4949 		(void) printf(gettext("status: One or more devices has "
4950 		    "been taken offline by the administrator.\n\tSufficient "
4951 		    "replicas exist for the pool to continue functioning in "
4952 		    "a\n\tdegraded state.\n"));
4953 		(void) printf(gettext("action: Online the device using "
4954 		    "'zpool online' or replace the device with\n\t'zpool "
4955 		    "replace'.\n"));
4956 		break;
4957 
4958 	case ZPOOL_STATUS_REMOVED_DEV:
4959 		(void) printf(gettext("status: One or more devices has "
4960 		    "been removed by the administrator.\n\tSufficient "
4961 		    "replicas exist for the pool to continue functioning in "
4962 		    "a\n\tdegraded state.\n"));
4963 		(void) printf(gettext("action: Online the device using "
4964 		    "'zpool online' or replace the device with\n\t'zpool "
4965 		    "replace'.\n"));
4966 		break;
4967 
4968 	case ZPOOL_STATUS_RESILVERING:
4969 		(void) printf(gettext("status: One or more devices is "
4970 		    "currently being resilvered.  The pool will\n\tcontinue "
4971 		    "to function, possibly in a degraded state.\n"));
4972 		(void) printf(gettext("action: Wait for the resilver to "
4973 		    "complete.\n"));
4974 		break;
4975 
4976 	case ZPOOL_STATUS_CORRUPT_DATA:
4977 		(void) printf(gettext("status: One or more devices has "
4978 		    "experienced an error resulting in data\n\tcorruption.  "
4979 		    "Applications may be affected.\n"));
4980 		(void) printf(gettext("action: Restore the file in question "
4981 		    "if possible.  Otherwise restore the\n\tentire pool from "
4982 		    "backup.\n"));
4983 		break;
4984 
4985 	case ZPOOL_STATUS_CORRUPT_POOL:
4986 		(void) printf(gettext("status: The pool metadata is corrupted "
4987 		    "and the pool cannot be opened.\n"));
4988 		zpool_explain_recover(zpool_get_handle(zhp),
4989 		    zpool_get_name(zhp), reason, config);
4990 		break;
4991 
4992 	case ZPOOL_STATUS_VERSION_OLDER:
4993 		(void) printf(gettext("status: The pool is formatted using a "
4994 		    "legacy on-disk format.  The pool can\n\tstill be used, "
4995 		    "but some features are unavailable.\n"));
4996 		(void) printf(gettext("action: Upgrade the pool using 'zpool "
4997 		    "upgrade'.  Once this is done, the\n\tpool will no longer "
4998 		    "be accessible on software that does not support feature\n"
4999 		    "\tflags.\n"));
5000 		break;
5001 
5002 	case ZPOOL_STATUS_VERSION_NEWER:
5003 		(void) printf(gettext("status: The pool has been upgraded to a "
5004 		    "newer, incompatible on-disk version.\n\tThe pool cannot "
5005 		    "be accessed on this system.\n"));
5006 		(void) printf(gettext("action: Access the pool from a system "
5007 		    "running more recent software, or\n\trestore the pool from "
5008 		    "backup.\n"));
5009 		break;
5010 
5011 	case ZPOOL_STATUS_FEAT_DISABLED:
5012 		(void) printf(gettext("status: Some supported features are not "
5013 		    "enabled on the pool. The pool can\n\tstill be used, but "
5014 		    "some features are unavailable.\n"));
5015 		(void) printf(gettext("action: Enable all features using "
5016 		    "'zpool upgrade'. Once this is done,\n\tthe pool may no "
5017 		    "longer be accessible by software that does not support\n\t"
5018 		    "the features. See zpool-features(7) for details.\n"));
5019 		break;
5020 
5021 	case ZPOOL_STATUS_UNSUP_FEAT_READ:
5022 		(void) printf(gettext("status: The pool cannot be accessed on "
5023 		    "this system because it uses the\n\tfollowing feature(s) "
5024 		    "not supported on this system:\n"));
5025 		zpool_print_unsup_feat(config);
5026 		(void) printf("\n");
5027 		(void) printf(gettext("action: Access the pool from a system "
5028 		    "that supports the required feature(s),\n\tor restore the "
5029 		    "pool from backup.\n"));
5030 		break;
5031 
5032 	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
5033 		(void) printf(gettext("status: The pool can only be accessed "
5034 		    "in read-only mode on this system. It\n\tcannot be "
5035 		    "accessed in read-write mode because it uses the "
5036 		    "following\n\tfeature(s) not supported on this system:\n"));
5037 		zpool_print_unsup_feat(config);
5038 		(void) printf("\n");
5039 		(void) printf(gettext("action: The pool cannot be accessed in "
5040 		    "read-write mode. Import the pool with\n"
5041 		    "\t\"-o readonly=on\", access the pool from a system that "
5042 		    "supports the\n\trequired feature(s), or restore the "
5043 		    "pool from backup.\n"));
5044 		break;
5045 
5046 	case ZPOOL_STATUS_FAULTED_DEV_R:
5047 		(void) printf(gettext("status: One or more devices are "
5048 		    "faulted in response to persistent errors.\n\tSufficient "
5049 		    "replicas exist for the pool to continue functioning "
5050 		    "in a\n\tdegraded state.\n"));
5051 		(void) printf(gettext("action: Replace the faulted device, "
5052 		    "or use 'zpool clear' to mark the device\n\trepaired.\n"));
5053 		break;
5054 
5055 	case ZPOOL_STATUS_FAULTED_DEV_NR:
5056 		(void) printf(gettext("status: One or more devices are "
5057 		    "faulted in response to persistent errors.  There are "
5058 		    "insufficient replicas for the pool to\n\tcontinue "
5059 		    "functioning.\n"));
5060 		(void) printf(gettext("action: Destroy and re-create the pool "
5061 		    "from a backup source.  Manually marking the device\n"
5062 		    "\trepaired using 'zpool clear' may allow some data "
5063 		    "to be recovered.\n"));
5064 		break;
5065 
5066 	case ZPOOL_STATUS_IO_FAILURE_WAIT:
5067 	case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
5068 		(void) printf(gettext("status: One or more devices are "
5069 		    "faulted in response to IO failures.\n"));
5070 		(void) printf(gettext("action: Make sure the affected devices "
5071 		    "are connected, then run 'zpool clear'.\n"));
5072 		break;
5073 
5074 	case ZPOOL_STATUS_BAD_LOG:
5075 		(void) printf(gettext("status: An intent log record "
5076 		    "could not be read.\n"
5077 		    "\tWaiting for adminstrator intervention to fix the "
5078 		    "faulted pool.\n"));
5079 		(void) printf(gettext("action: Either restore the affected "
5080 		    "device(s) and run 'zpool online',\n"
5081 		    "\tor ignore the intent log records by running "
5082 		    "'zpool clear'.\n"));
5083 		break;
5084 
5085 	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
5086 		(void) printf(gettext("status: One or more devices are "
5087 		    "configured to use a non-native block size.\n"
5088 		    "\tExpect reduced performance.\n"));
5089 		(void) printf(gettext("action: Replace affected devices with "
5090 		    "devices that support the\n\tconfigured block size, or "
5091 		    "migrate data to a properly configured\n\tpool.\n"));
5092 		break;
5093 
5094 	default:
5095 		/*
5096 		 * The remaining errors can't actually be generated, yet.
5097 		 */
5098 		assert(reason == ZPOOL_STATUS_OK);
5099 	}
5100 
5101 	if (msgid != NULL)
5102 		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
5103 		    msgid);
5104 
5105 	if (config != NULL) {
5106 		int namewidth;
5107 		uint64_t nerr;
5108 		nvlist_t **spares, **l2cache;
5109 		uint_t nspares, nl2cache;
5110 		pool_checkpoint_stat_t *pcs = NULL;
5111 		pool_scan_stat_t *ps = NULL;
5112 		pool_removal_stat_t *prs = NULL;
5113 
5114 		(void) nvlist_lookup_uint64_array(nvroot,
5115 		    ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
5116 		(void) nvlist_lookup_uint64_array(nvroot,
5117 		    ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
5118 		(void) nvlist_lookup_uint64_array(nvroot,
5119 		    ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
5120 
5121 		print_scan_status(ps);
5122 		print_checkpoint_scan_warning(ps, pcs);
5123 		print_removal_status(zhp, prs);
5124 		print_checkpoint_status(pcs);
5125 
5126 		namewidth = max_width(zhp, nvroot, 0, 0);
5127 		if (namewidth < 10)
5128 			namewidth = 10;
5129 
5130 		(void) printf(gettext("config:\n\n"));
5131 		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
5132 		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
5133 		print_status_config(zhp, zpool_get_name(zhp), nvroot,
5134 		    namewidth, 0, B_FALSE);
5135 
5136 		if (num_logs(nvroot) > 0)
5137 			print_logs(zhp, nvroot, namewidth, B_TRUE);
5138 		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5139 		    &l2cache, &nl2cache) == 0)
5140 			print_l2cache(zhp, l2cache, nl2cache, namewidth);
5141 
5142 		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5143 		    &spares, &nspares) == 0)
5144 			print_spares(zhp, spares, nspares, namewidth);
5145 
5146 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5147 		    &nerr) == 0) {
5148 			nvlist_t *nverrlist = NULL;
5149 
5150 			/*
5151 			 * If the approximate error count is small, get a
5152 			 * precise count by fetching the entire log and
5153 			 * uniquifying the results.
5154 			 */
5155 			if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
5156 			    zpool_get_errlog(zhp, &nverrlist) == 0) {
5157 				nvpair_t *elem;
5158 
5159 				elem = NULL;
5160 				nerr = 0;
5161 				while ((elem = nvlist_next_nvpair(nverrlist,
5162 				    elem)) != NULL) {
5163 					nerr++;
5164 				}
5165 			}
5166 			nvlist_free(nverrlist);
5167 
5168 			(void) printf("\n");
5169 
5170 			if (nerr == 0)
5171 				(void) printf(gettext("errors: No known data "
5172 				    "errors\n"));
5173 			else if (!cbp->cb_verbose)
5174 				(void) printf(gettext("errors: %llu data "
5175 				    "errors, use '-v' for a list\n"),
5176 				    (u_longlong_t)nerr);
5177 			else
5178 				print_error_log(zhp);
5179 		}
5180 
5181 		if (cbp->cb_dedup_stats)
5182 			print_dedup_stats(config);
5183 	} else {
5184 		(void) printf(gettext("config: The configuration cannot be "
5185 		    "determined.\n"));
5186 	}
5187 
5188 	return (0);
5189 }
5190 
5191 /*
5192  * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
5193  *
5194  *	-v	Display complete error logs
5195  *	-x	Display only pools with potential problems
5196  *	-D	Display dedup status (undocumented)
5197  *	-T	Display a timestamp in date(1) or Unix format
5198  *
5199  * Describes the health status of all pools or some subset.
5200  */
5201 int
zpool_do_status(int argc,char ** argv)5202 zpool_do_status(int argc, char **argv)
5203 {
5204 	int c;
5205 	int ret;
5206 	unsigned long interval = 0, count = 0;
5207 	status_cbdata_t cb = { 0 };
5208 
5209 	/* check options */
5210 	while ((c = getopt(argc, argv, "vxDT:")) != -1) {
5211 		switch (c) {
5212 		case 'v':
5213 			cb.cb_verbose = B_TRUE;
5214 			break;
5215 		case 'x':
5216 			cb.cb_explain = B_TRUE;
5217 			break;
5218 		case 'D':
5219 			cb.cb_dedup_stats = B_TRUE;
5220 			break;
5221 		case 'T':
5222 			get_timestamp_arg(*optarg);
5223 			break;
5224 		case '?':
5225 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5226 			    optopt);
5227 			usage(B_FALSE);
5228 		}
5229 	}
5230 
5231 	argc -= optind;
5232 	argv += optind;
5233 
5234 	get_interval_count(&argc, argv, &interval, &count);
5235 
5236 	if (argc == 0)
5237 		cb.cb_allpools = B_TRUE;
5238 
5239 	cb.cb_first = B_TRUE;
5240 
5241 	for (;;) {
5242 		if (timestamp_fmt != NODATE)
5243 			print_timestamp(timestamp_fmt);
5244 
5245 		ret = for_each_pool(argc, argv, B_TRUE, NULL,
5246 		    status_callback, &cb);
5247 
5248 		if (argc == 0 && cb.cb_count == 0)
5249 			(void) printf(gettext("no pools available\n"));
5250 		else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5251 			(void) printf(gettext("all pools are healthy\n"));
5252 
5253 		if (ret != 0)
5254 			return (ret);
5255 
5256 		if (interval == 0)
5257 			break;
5258 
5259 		if (count != 0 && --count == 0)
5260 			break;
5261 
5262 		(void) sleep(interval);
5263 	}
5264 
5265 	return (0);
5266 }
5267 
5268 typedef struct upgrade_cbdata {
5269 	boolean_t	cb_first;
5270 	boolean_t	cb_unavail;
5271 	char		cb_poolname[ZFS_MAX_DATASET_NAME_LEN];
5272 	int		cb_argc;
5273 	uint64_t	cb_version;
5274 	char		**cb_argv;
5275 } upgrade_cbdata_t;
5276 
5277 #ifdef __FreeBSD__
5278 static int
is_root_pool(zpool_handle_t * zhp)5279 is_root_pool(zpool_handle_t *zhp)
5280 {
5281 	static struct statfs sfs;
5282 	static char *poolname = NULL;
5283 	static boolean_t stated = B_FALSE;
5284 	char *slash;
5285 
5286 	if (!stated) {
5287 		stated = B_TRUE;
5288 		if (statfs("/", &sfs) == -1) {
5289 			(void) fprintf(stderr,
5290 			    "Unable to stat root file system: %s.\n",
5291 			    strerror(errno));
5292 			return (0);
5293 		}
5294 		if (strcmp(sfs.f_fstypename, "zfs") != 0)
5295 			return (0);
5296 		poolname = sfs.f_mntfromname;
5297 		if ((slash = strchr(poolname, '/')) != NULL)
5298 			*slash = '\0';
5299 	}
5300 	return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
5301 }
5302 
5303 static void
root_pool_upgrade_check(zpool_handle_t * zhp,char * poolname,int size)5304 root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
5305 {
5306 
5307 	if (poolname[0] == '\0' && is_root_pool(zhp))
5308 		(void) strlcpy(poolname, zpool_get_name(zhp), size);
5309 }
5310 #endif	/* FreeBSD */
5311 
5312 static int
upgrade_version(zpool_handle_t * zhp,uint64_t version)5313 upgrade_version(zpool_handle_t *zhp, uint64_t version)
5314 {
5315 	int ret;
5316 	nvlist_t *config;
5317 	uint64_t oldversion;
5318 
5319 	config = zpool_get_config(zhp, NULL);
5320 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5321 	    &oldversion) == 0);
5322 
5323 	assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5324 	assert(oldversion < version);
5325 
5326 	ret = zpool_upgrade(zhp, version);
5327 	if (ret != 0)
5328 		return (ret);
5329 
5330 	if (version >= SPA_VERSION_FEATURES) {
5331 		(void) printf(gettext("Successfully upgraded "
5332 		    "'%s' from version %llu to feature flags.\n"),
5333 		    zpool_get_name(zhp), oldversion);
5334 	} else {
5335 		(void) printf(gettext("Successfully upgraded "
5336 		    "'%s' from version %llu to version %llu.\n"),
5337 		    zpool_get_name(zhp), oldversion, version);
5338 	}
5339 
5340 	return (0);
5341 }
5342 
5343 static int
upgrade_enable_all(zpool_handle_t * zhp,int * countp)5344 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5345 {
5346 	int i, ret, count;
5347 	boolean_t firstff = B_TRUE;
5348 	nvlist_t *enabled = zpool_get_features(zhp);
5349 
5350 	count = 0;
5351 	for (i = 0; i < SPA_FEATURES; i++) {
5352 		const char *fname = spa_feature_table[i].fi_uname;
5353 		const char *fguid = spa_feature_table[i].fi_guid;
5354 		if (!nvlist_exists(enabled, fguid)) {
5355 			char *propname;
5356 			verify(-1 != asprintf(&propname, "feature@%s", fname));
5357 			ret = zpool_set_prop(zhp, propname,
5358 			    ZFS_FEATURE_ENABLED);
5359 			if (ret != 0) {
5360 				free(propname);
5361 				return (ret);
5362 			}
5363 			count++;
5364 
5365 			if (firstff) {
5366 				(void) printf(gettext("Enabled the "
5367 				    "following features on '%s':\n"),
5368 				    zpool_get_name(zhp));
5369 				firstff = B_FALSE;
5370 			}
5371 			(void) printf(gettext("  %s\n"), fname);
5372 			free(propname);
5373 		}
5374 	}
5375 
5376 	if (countp != NULL)
5377 		*countp = count;
5378 	return (0);
5379 }
5380 
5381 static int
upgrade_cb(zpool_handle_t * zhp,void * arg)5382 upgrade_cb(zpool_handle_t *zhp, void *arg)
5383 {
5384 	upgrade_cbdata_t *cbp = arg;
5385 	nvlist_t *config;
5386 	uint64_t version;
5387 	boolean_t printnl = B_FALSE;
5388 	int ret;
5389 
5390 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5391 		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5392 		    "currently unavailable.\n\n"), zpool_get_name(zhp));
5393 		cbp->cb_unavail = B_TRUE;
5394 		/* Allow iteration to continue. */
5395 		return (0);
5396 	}
5397 
5398 	config = zpool_get_config(zhp, NULL);
5399 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5400 	    &version) == 0);
5401 
5402 	assert(SPA_VERSION_IS_SUPPORTED(version));
5403 
5404 	if (version < cbp->cb_version) {
5405 		cbp->cb_first = B_FALSE;
5406 		ret = upgrade_version(zhp, cbp->cb_version);
5407 		if (ret != 0)
5408 			return (ret);
5409 #ifdef __FreeBSD__
5410 		root_pool_upgrade_check(zhp, cbp->cb_poolname,
5411 		    sizeof(cbp->cb_poolname));
5412 #endif	/* __FreeBSD__ */
5413 		printnl = B_TRUE;
5414 
5415 #ifdef illumos
5416 		/*
5417 		 * If they did "zpool upgrade -a", then we could
5418 		 * be doing ioctls to different pools.  We need
5419 		 * to log this history once to each pool, and bypass
5420 		 * the normal history logging that happens in main().
5421 		 */
5422 		(void) zpool_log_history(g_zfs, history_str);
5423 		log_history = B_FALSE;
5424 #endif
5425 	}
5426 
5427 	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5428 		int count;
5429 		ret = upgrade_enable_all(zhp, &count);
5430 		if (ret != 0)
5431 			return (ret);
5432 
5433 		if (count > 0) {
5434 			cbp->cb_first = B_FALSE;
5435 			printnl = B_TRUE;
5436 #ifdef __FreeBSD__
5437 			root_pool_upgrade_check(zhp, cbp->cb_poolname,
5438 			    sizeof(cbp->cb_poolname));
5439 #endif	/* __FreeBSD__ */
5440 			/*
5441 			 * If they did "zpool upgrade -a", then we could
5442 			 * be doing ioctls to different pools.  We need
5443 			 * to log this history once to each pool, and bypass
5444 			 * the normal history logging that happens in main().
5445 			 */
5446 			(void) zpool_log_history(g_zfs, history_str);
5447 			log_history = B_FALSE;
5448 		}
5449 	}
5450 
5451 	if (printnl) {
5452 		(void) printf(gettext("\n"));
5453 	}
5454 
5455 	return (0);
5456 }
5457 
5458 static int
upgrade_list_unavail(zpool_handle_t * zhp,void * arg)5459 upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
5460 {
5461 	upgrade_cbdata_t *cbp = arg;
5462 
5463 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5464 		if (cbp->cb_first) {
5465 			(void) fprintf(stderr, gettext("The following pools "
5466 			    "are unavailable and cannot be upgraded as this "
5467 			    "time.\n\n"));
5468 			(void) fprintf(stderr, gettext("POOL\n"));
5469 			(void) fprintf(stderr, gettext("------------\n"));
5470 			cbp->cb_first = B_FALSE;
5471 		}
5472 		(void) printf(gettext("%s\n"), zpool_get_name(zhp));
5473 		cbp->cb_unavail = B_TRUE;
5474 	}
5475 	return (0);
5476 }
5477 
5478 static int
upgrade_list_older_cb(zpool_handle_t * zhp,void * arg)5479 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5480 {
5481 	upgrade_cbdata_t *cbp = arg;
5482 	nvlist_t *config;
5483 	uint64_t version;
5484 
5485 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5486 		/*
5487 		 * This will have been reported by upgrade_list_unavail so
5488 		 * just allow iteration to continue.
5489 		 */
5490 		cbp->cb_unavail = B_TRUE;
5491 		return (0);
5492 	}
5493 
5494 	config = zpool_get_config(zhp, NULL);
5495 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5496 	    &version) == 0);
5497 
5498 	assert(SPA_VERSION_IS_SUPPORTED(version));
5499 
5500 	if (version < SPA_VERSION_FEATURES) {
5501 		if (cbp->cb_first) {
5502 			(void) printf(gettext("The following pools are "
5503 			    "formatted with legacy version numbers and can\n"
5504 			    "be upgraded to use feature flags.  After "
5505 			    "being upgraded, these pools\nwill no "
5506 			    "longer be accessible by software that does not "
5507 			    "support feature\nflags.\n\n"));
5508 			(void) printf(gettext("VER  POOL\n"));
5509 			(void) printf(gettext("---  ------------\n"));
5510 			cbp->cb_first = B_FALSE;
5511 		}
5512 
5513 		(void) printf("%2llu   %s\n", (u_longlong_t)version,
5514 		    zpool_get_name(zhp));
5515 	}
5516 
5517 	return (0);
5518 }
5519 
5520 static int
upgrade_list_disabled_cb(zpool_handle_t * zhp,void * arg)5521 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5522 {
5523 	upgrade_cbdata_t *cbp = arg;
5524 	nvlist_t *config;
5525 	uint64_t version;
5526 
5527 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5528 		/*
5529 		 * This will have been reported by upgrade_list_unavail so
5530 		 * just allow iteration to continue.
5531 		 */
5532 		cbp->cb_unavail = B_TRUE;
5533 		return (0);
5534 	}
5535 
5536 	config = zpool_get_config(zhp, NULL);
5537 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5538 	    &version) == 0);
5539 
5540 	if (version >= SPA_VERSION_FEATURES) {
5541 		int i;
5542 		boolean_t poolfirst = B_TRUE;
5543 		nvlist_t *enabled = zpool_get_features(zhp);
5544 
5545 		for (i = 0; i < SPA_FEATURES; i++) {
5546 			const char *fguid = spa_feature_table[i].fi_guid;
5547 			const char *fname = spa_feature_table[i].fi_uname;
5548 			if (!nvlist_exists(enabled, fguid)) {
5549 				if (cbp->cb_first) {
5550 					(void) printf(gettext("\nSome "
5551 					    "supported features are not "
5552 					    "enabled on the following pools. "
5553 					    "Once a\nfeature is enabled the "
5554 					    "pool may become incompatible with "
5555 					    "software\nthat does not support "
5556 					    "the feature. See "
5557 					    "zpool-features(7) for "
5558 					    "details.\n\n"));
5559 					(void) printf(gettext("POOL  "
5560 					    "FEATURE\n"));
5561 					(void) printf(gettext("------"
5562 					    "---------\n"));
5563 					cbp->cb_first = B_FALSE;
5564 				}
5565 
5566 				if (poolfirst) {
5567 					(void) printf(gettext("%s\n"),
5568 					    zpool_get_name(zhp));
5569 					poolfirst = B_FALSE;
5570 				}
5571 
5572 				(void) printf(gettext("      %s\n"), fname);
5573 			}
5574 		}
5575 	}
5576 
5577 	return (0);
5578 }
5579 
5580 /* ARGSUSED */
5581 static int
upgrade_one(zpool_handle_t * zhp,void * data)5582 upgrade_one(zpool_handle_t *zhp, void *data)
5583 {
5584 	boolean_t printnl = B_FALSE;
5585 	upgrade_cbdata_t *cbp = data;
5586 	uint64_t cur_version;
5587 	int ret;
5588 
5589 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5590 		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5591 		    "is currently unavailable.\n\n"), zpool_get_name(zhp));
5592 		cbp->cb_unavail = B_TRUE;
5593 		return (1);
5594 	}
5595 
5596 	if (strcmp("log", zpool_get_name(zhp)) == 0) {
5597 		(void) printf(gettext("'log' is now a reserved word\n"
5598 		    "Pool 'log' must be renamed using export and import"
5599 		    " to upgrade.\n\n"));
5600 		return (1);
5601 	}
5602 
5603 	cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5604 	if (cur_version > cbp->cb_version) {
5605 		(void) printf(gettext("Pool '%s' is already formatted "
5606 		    "using more current version '%llu'.\n\n"),
5607 		    zpool_get_name(zhp), cur_version);
5608 		return (0);
5609 	}
5610 
5611 	if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5612 		(void) printf(gettext("Pool '%s' is already formatted "
5613 		    "using version %llu.\n\n"), zpool_get_name(zhp),
5614 		    cbp->cb_version);
5615 		return (0);
5616 	}
5617 
5618 	if (cur_version != cbp->cb_version) {
5619 		printnl = B_TRUE;
5620 		ret = upgrade_version(zhp, cbp->cb_version);
5621 		if (ret != 0)
5622 			return (ret);
5623 #ifdef __FreeBSD__
5624 		root_pool_upgrade_check(zhp, cbp->cb_poolname,
5625 		    sizeof(cbp->cb_poolname));
5626 #endif	/* __FreeBSD__ */
5627 	}
5628 
5629 	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5630 		int count = 0;
5631 		ret = upgrade_enable_all(zhp, &count);
5632 		if (ret != 0)
5633 			return (ret);
5634 
5635 		if (count != 0) {
5636 			printnl = B_TRUE;
5637 #ifdef __FreeBSD__
5638 			root_pool_upgrade_check(zhp, cbp->cb_poolname,
5639 			    sizeof(cbp->cb_poolname));
5640 #endif	/* __FreeBSD __*/
5641 		} else if (cur_version == SPA_VERSION) {
5642 			(void) printf(gettext("Pool '%s' already has all "
5643 			    "supported features enabled.\n\n"),
5644 			    zpool_get_name(zhp));
5645 		}
5646 	}
5647 
5648 	if (printnl) {
5649 		(void) printf(gettext("\n"));
5650 	}
5651 
5652 	return (0);
5653 }
5654 
5655 /*
5656  * zpool upgrade
5657  * zpool upgrade -v
5658  * zpool upgrade [-V version] <-a | pool ...>
5659  *
5660  * With no arguments, display downrev'd ZFS pool available for upgrade.
5661  * Individual pools can be upgraded by specifying the pool, and '-a' will
5662  * upgrade all pools.
5663  */
5664 int
zpool_do_upgrade(int argc,char ** argv)5665 zpool_do_upgrade(int argc, char **argv)
5666 {
5667 	int c;
5668 	upgrade_cbdata_t cb = { 0 };
5669 	int ret = 0;
5670 	boolean_t showversions = B_FALSE;
5671 	boolean_t upgradeall = B_FALSE;
5672 	char *end;
5673 
5674 
5675 	/* check options */
5676 	while ((c = getopt(argc, argv, ":avV:")) != -1) {
5677 		switch (c) {
5678 		case 'a':
5679 			upgradeall = B_TRUE;
5680 			break;
5681 		case 'v':
5682 			showversions = B_TRUE;
5683 			break;
5684 		case 'V':
5685 			cb.cb_version = strtoll(optarg, &end, 10);
5686 			if (*end != '\0' ||
5687 			    !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5688 				(void) fprintf(stderr,
5689 				    gettext("invalid version '%s'\n"), optarg);
5690 				usage(B_FALSE);
5691 			}
5692 			break;
5693 		case ':':
5694 			(void) fprintf(stderr, gettext("missing argument for "
5695 			    "'%c' option\n"), optopt);
5696 			usage(B_FALSE);
5697 			break;
5698 		case '?':
5699 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5700 			    optopt);
5701 			usage(B_FALSE);
5702 		}
5703 	}
5704 
5705 	cb.cb_argc = argc;
5706 	cb.cb_argv = argv;
5707 	argc -= optind;
5708 	argv += optind;
5709 
5710 	if (cb.cb_version == 0) {
5711 		cb.cb_version = SPA_VERSION;
5712 	} else if (!upgradeall && argc == 0) {
5713 		(void) fprintf(stderr, gettext("-V option is "
5714 		    "incompatible with other arguments\n"));
5715 		usage(B_FALSE);
5716 	}
5717 
5718 	if (showversions) {
5719 		if (upgradeall || argc != 0) {
5720 			(void) fprintf(stderr, gettext("-v option is "
5721 			    "incompatible with other arguments\n"));
5722 			usage(B_FALSE);
5723 		}
5724 	} else if (upgradeall) {
5725 		if (argc != 0) {
5726 			(void) fprintf(stderr, gettext("-a option should not "
5727 			    "be used along with a pool name\n"));
5728 			usage(B_FALSE);
5729 		}
5730 	}
5731 
5732 	(void) printf(gettext("This system supports ZFS pool feature "
5733 	    "flags.\n\n"));
5734 	if (showversions) {
5735 		int i;
5736 
5737 		(void) printf(gettext("The following features are "
5738 		    "supported:\n\n"));
5739 		(void) printf(gettext("FEAT DESCRIPTION\n"));
5740 		(void) printf("----------------------------------------------"
5741 		    "---------------\n");
5742 		for (i = 0; i < SPA_FEATURES; i++) {
5743 			zfeature_info_t *fi = &spa_feature_table[i];
5744 			const char *ro =
5745 			    (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5746 			    " (read-only compatible)" : "";
5747 
5748 			(void) printf("%-37s%s\n", fi->fi_uname, ro);
5749 			(void) printf("     %s\n", fi->fi_desc);
5750 		}
5751 		(void) printf("\n");
5752 
5753 		(void) printf(gettext("The following legacy versions are also "
5754 		    "supported:\n\n"));
5755 		(void) printf(gettext("VER  DESCRIPTION\n"));
5756 		(void) printf("---  -----------------------------------------"
5757 		    "---------------\n");
5758 		(void) printf(gettext(" 1   Initial ZFS version\n"));
5759 		(void) printf(gettext(" 2   Ditto blocks "
5760 		    "(replicated metadata)\n"));
5761 		(void) printf(gettext(" 3   Hot spares and double parity "
5762 		    "RAID-Z\n"));
5763 		(void) printf(gettext(" 4   zpool history\n"));
5764 		(void) printf(gettext(" 5   Compression using the gzip "
5765 		    "algorithm\n"));
5766 		(void) printf(gettext(" 6   bootfs pool property\n"));
5767 		(void) printf(gettext(" 7   Separate intent log devices\n"));
5768 		(void) printf(gettext(" 8   Delegated administration\n"));
5769 		(void) printf(gettext(" 9   refquota and refreservation "
5770 		    "properties\n"));
5771 		(void) printf(gettext(" 10  Cache devices\n"));
5772 		(void) printf(gettext(" 11  Improved scrub performance\n"));
5773 		(void) printf(gettext(" 12  Snapshot properties\n"));
5774 		(void) printf(gettext(" 13  snapused property\n"));
5775 		(void) printf(gettext(" 14  passthrough-x aclinherit\n"));
5776 		(void) printf(gettext(" 15  user/group space accounting\n"));
5777 		(void) printf(gettext(" 16  stmf property support\n"));
5778 		(void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
5779 		(void) printf(gettext(" 18  Snapshot user holds\n"));
5780 		(void) printf(gettext(" 19  Log device removal\n"));
5781 		(void) printf(gettext(" 20  Compression using zle "
5782 		    "(zero-length encoding)\n"));
5783 		(void) printf(gettext(" 21  Deduplication\n"));
5784 		(void) printf(gettext(" 22  Received properties\n"));
5785 		(void) printf(gettext(" 23  Slim ZIL\n"));
5786 		(void) printf(gettext(" 24  System attributes\n"));
5787 		(void) printf(gettext(" 25  Improved scrub stats\n"));
5788 		(void) printf(gettext(" 26  Improved snapshot deletion "
5789 		    "performance\n"));
5790 		(void) printf(gettext(" 27  Improved snapshot creation "
5791 		    "performance\n"));
5792 		(void) printf(gettext(" 28  Multiple vdev replacements\n"));
5793 		(void) printf(gettext("\nFor more information on a particular "
5794 		    "version, including supported releases,\n"));
5795 		(void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5796 	} else if (argc == 0 && upgradeall) {
5797 		cb.cb_first = B_TRUE;
5798 		ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5799 		if (ret == 0 && cb.cb_first) {
5800 			if (cb.cb_version == SPA_VERSION) {
5801 				(void) printf(gettext("All %spools are already "
5802 				    "formatted using feature flags.\n\n"),
5803 				    cb.cb_unavail ? gettext("available ") : "");
5804 				(void) printf(gettext("Every %sfeature flags "
5805 				    "pool already has all supported features "
5806 				    "enabled.\n"),
5807 				    cb.cb_unavail ? gettext("available ") : "");
5808 			} else {
5809 				(void) printf(gettext("All pools are already "
5810 				    "formatted with version %llu or higher.\n"),
5811 				    cb.cb_version);
5812 			}
5813 		}
5814 	} else if (argc == 0) {
5815 		cb.cb_first = B_TRUE;
5816 		ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
5817 		assert(ret == 0);
5818 
5819 		if (!cb.cb_first) {
5820 			(void) fprintf(stderr, "\n");
5821 		}
5822 
5823 		cb.cb_first = B_TRUE;
5824 		ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5825 		assert(ret == 0);
5826 
5827 		if (cb.cb_first) {
5828 			(void) printf(gettext("All %spools are formatted using "
5829 			    "feature flags.\n\n"), cb.cb_unavail ?
5830 			    gettext("available ") : "");
5831 		} else {
5832 			(void) printf(gettext("\nUse 'zpool upgrade -v' "
5833 			    "for a list of available legacy versions.\n"));
5834 		}
5835 
5836 		cb.cb_first = B_TRUE;
5837 		ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5838 		assert(ret == 0);
5839 
5840 		if (cb.cb_first) {
5841 			(void) printf(gettext("Every %sfeature flags pool has "
5842 			    "all supported features enabled.\n"),
5843 			    cb.cb_unavail ? gettext("available ") : "");
5844 		} else {
5845 			(void) printf(gettext("\n"));
5846 		}
5847 	} else {
5848 		ret = for_each_pool(argc, argv, B_TRUE, NULL,
5849 		    upgrade_one, &cb);
5850 	}
5851 
5852 	if (cb.cb_poolname[0] != '\0') {
5853 		(void) printf(
5854 		    "If you boot from pool '%s', don't forget to update boot code.\n"
5855 		    "Assuming you use GPT partitioning and da0 is your boot disk\n"
5856 		    "the following command will do it:\n"
5857 		    "\n"
5858 		    "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
5859 		    cb.cb_poolname);
5860 	}
5861 
5862 	return (ret);
5863 }
5864 
5865 typedef struct hist_cbdata {
5866 	boolean_t first;
5867 	boolean_t longfmt;
5868 	boolean_t internal;
5869 } hist_cbdata_t;
5870 
5871 /*
5872  * Print out the command history for a specific pool.
5873  */
5874 static int
get_history_one(zpool_handle_t * zhp,void * data)5875 get_history_one(zpool_handle_t *zhp, void *data)
5876 {
5877 	nvlist_t *nvhis;
5878 	nvlist_t **records;
5879 	uint_t numrecords;
5880 	int ret, i;
5881 	hist_cbdata_t *cb = (hist_cbdata_t *)data;
5882 
5883 	cb->first = B_FALSE;
5884 
5885 	(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5886 
5887 	if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5888 		return (ret);
5889 
5890 	verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5891 	    &records, &numrecords) == 0);
5892 	for (i = 0; i < numrecords; i++) {
5893 		nvlist_t *rec = records[i];
5894 		char tbuf[30] = "";
5895 
5896 		if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5897 			time_t tsec;
5898 			struct tm t;
5899 
5900 			tsec = fnvlist_lookup_uint64(records[i],
5901 			    ZPOOL_HIST_TIME);
5902 			(void) localtime_r(&tsec, &t);
5903 			(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5904 		}
5905 
5906 		if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5907 			(void) printf("%s %s", tbuf,
5908 			    fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5909 		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5910 			int ievent =
5911 			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5912 			if (!cb->internal)
5913 				continue;
5914 			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5915 				(void) printf("%s unrecognized record:\n",
5916 				    tbuf);
5917 				dump_nvlist(rec, 4);
5918 				continue;
5919 			}
5920 			(void) printf("%s [internal %s txg:%lld] %s", tbuf,
5921 			    zfs_history_event_names[ievent],
5922 			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5923 			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5924 		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5925 			if (!cb->internal)
5926 				continue;
5927 			(void) printf("%s [txg:%lld] %s", tbuf,
5928 			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5929 			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5930 			if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5931 				(void) printf(" %s (%llu)",
5932 				    fnvlist_lookup_string(rec,
5933 				    ZPOOL_HIST_DSNAME),
5934 				    fnvlist_lookup_uint64(rec,
5935 				    ZPOOL_HIST_DSID));
5936 			}
5937 			(void) printf(" %s", fnvlist_lookup_string(rec,
5938 			    ZPOOL_HIST_INT_STR));
5939 		} else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5940 			if (!cb->internal)
5941 				continue;
5942 			(void) printf("%s ioctl %s\n", tbuf,
5943 			    fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5944 			if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5945 				(void) printf("    input:\n");
5946 				dump_nvlist(fnvlist_lookup_nvlist(rec,
5947 				    ZPOOL_HIST_INPUT_NVL), 8);
5948 			}
5949 			if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5950 				(void) printf("    output:\n");
5951 				dump_nvlist(fnvlist_lookup_nvlist(rec,
5952 				    ZPOOL_HIST_OUTPUT_NVL), 8);
5953 			}
5954 			if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5955 				(void) printf("    errno: %lld\n",
5956 				    fnvlist_lookup_int64(rec,
5957 				    ZPOOL_HIST_ERRNO));
5958 			}
5959 		} else {
5960 			if (!cb->internal)
5961 				continue;
5962 			(void) printf("%s unrecognized record:\n", tbuf);
5963 			dump_nvlist(rec, 4);
5964 		}
5965 
5966 		if (!cb->longfmt) {
5967 			(void) printf("\n");
5968 			continue;
5969 		}
5970 		(void) printf(" [");
5971 		if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5972 			uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5973 			struct passwd *pwd = getpwuid(who);
5974 			(void) printf("user %d ", (int)who);
5975 			if (pwd != NULL)
5976 				(void) printf("(%s) ", pwd->pw_name);
5977 		}
5978 		if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5979 			(void) printf("on %s",
5980 			    fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5981 		}
5982 		if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5983 			(void) printf(":%s",
5984 			    fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5985 		}
5986 		(void) printf("]");
5987 		(void) printf("\n");
5988 	}
5989 	(void) printf("\n");
5990 	nvlist_free(nvhis);
5991 
5992 	return (ret);
5993 }
5994 
5995 /*
5996  * zpool history <pool>
5997  *
5998  * Displays the history of commands that modified pools.
5999  */
6000 int
zpool_do_history(int argc,char ** argv)6001 zpool_do_history(int argc, char **argv)
6002 {
6003 	hist_cbdata_t cbdata = { 0 };
6004 	int ret;
6005 	int c;
6006 
6007 	cbdata.first = B_TRUE;
6008 	/* check options */
6009 	while ((c = getopt(argc, argv, "li")) != -1) {
6010 		switch (c) {
6011 		case 'l':
6012 			cbdata.longfmt = B_TRUE;
6013 			break;
6014 		case 'i':
6015 			cbdata.internal = B_TRUE;
6016 			break;
6017 		case '?':
6018 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
6019 			    optopt);
6020 			usage(B_FALSE);
6021 		}
6022 	}
6023 	argc -= optind;
6024 	argv += optind;
6025 
6026 	ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
6027 	    &cbdata);
6028 
6029 	if (argc == 0 && cbdata.first == B_TRUE) {
6030 		(void) printf(gettext("no pools available\n"));
6031 		return (0);
6032 	}
6033 
6034 	return (ret);
6035 }
6036 
6037 static int
get_callback(zpool_handle_t * zhp,void * data)6038 get_callback(zpool_handle_t *zhp, void *data)
6039 {
6040 	zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
6041 	char value[MAXNAMELEN];
6042 	zprop_source_t srctype;
6043 	zprop_list_t *pl;
6044 
6045 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
6046 
6047 		/*
6048 		 * Skip the special fake placeholder. This will also skip
6049 		 * over the name property when 'all' is specified.
6050 		 */
6051 		if (pl->pl_prop == ZPOOL_PROP_NAME &&
6052 		    pl == cbp->cb_proplist)
6053 			continue;
6054 
6055 		if (pl->pl_prop == ZPROP_INVAL &&
6056 		    (zpool_prop_feature(pl->pl_user_prop) ||
6057 		    zpool_prop_unsupported(pl->pl_user_prop))) {
6058 			srctype = ZPROP_SRC_LOCAL;
6059 
6060 			if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
6061 			    value, sizeof (value)) == 0) {
6062 				zprop_print_one_property(zpool_get_name(zhp),
6063 				    cbp, pl->pl_user_prop, value, srctype,
6064 				    NULL, NULL);
6065 			}
6066 		} else {
6067 			if (zpool_get_prop(zhp, pl->pl_prop, value,
6068 			    sizeof (value), &srctype, cbp->cb_literal) != 0)
6069 				continue;
6070 
6071 			zprop_print_one_property(zpool_get_name(zhp), cbp,
6072 			    zpool_prop_to_name(pl->pl_prop), value, srctype,
6073 			    NULL, NULL);
6074 		}
6075 	}
6076 	return (0);
6077 }
6078 
6079 /*
6080  * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
6081  *
6082  *	-H	Scripted mode.  Don't display headers, and separate properties
6083  *		by a single tab.
6084  *	-o	List of columns to display.  Defaults to
6085  *		"name,property,value,source".
6086  *	-p	Diplay values in parsable (exact) format.
6087  *
6088  * Get properties of pools in the system. Output space statistics
6089  * for each one as well as other attributes.
6090  */
6091 int
zpool_do_get(int argc,char ** argv)6092 zpool_do_get(int argc, char **argv)
6093 {
6094 	zprop_get_cbdata_t cb = { 0 };
6095 	zprop_list_t fake_name = { 0 };
6096 	int ret;
6097 	int c, i;
6098 	char *value;
6099 
6100 	cb.cb_first = B_TRUE;
6101 
6102 	/*
6103 	 * Set up default columns and sources.
6104 	 */
6105 	cb.cb_sources = ZPROP_SRC_ALL;
6106 	cb.cb_columns[0] = GET_COL_NAME;
6107 	cb.cb_columns[1] = GET_COL_PROPERTY;
6108 	cb.cb_columns[2] = GET_COL_VALUE;
6109 	cb.cb_columns[3] = GET_COL_SOURCE;
6110 	cb.cb_type = ZFS_TYPE_POOL;
6111 
6112 	/* check options */
6113 	while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
6114 		switch (c) {
6115 		case 'p':
6116 			cb.cb_literal = B_TRUE;
6117 			break;
6118 		case 'H':
6119 			cb.cb_scripted = B_TRUE;
6120 			break;
6121 		case 'o':
6122 			bzero(&cb.cb_columns, sizeof (cb.cb_columns));
6123 			i = 0;
6124 			while (*optarg != '\0') {
6125 				static char *col_subopts[] =
6126 				{ "name", "property", "value", "source",
6127 				"all", NULL };
6128 
6129 				if (i == ZFS_GET_NCOLS) {
6130 					(void) fprintf(stderr, gettext("too "
6131 					"many fields given to -o "
6132 					"option\n"));
6133 					usage(B_FALSE);
6134 				}
6135 
6136 				switch (getsubopt(&optarg, col_subopts,
6137 				    &value)) {
6138 				case 0:
6139 					cb.cb_columns[i++] = GET_COL_NAME;
6140 					break;
6141 				case 1:
6142 					cb.cb_columns[i++] = GET_COL_PROPERTY;
6143 					break;
6144 				case 2:
6145 					cb.cb_columns[i++] = GET_COL_VALUE;
6146 					break;
6147 				case 3:
6148 					cb.cb_columns[i++] = GET_COL_SOURCE;
6149 					break;
6150 				case 4:
6151 					if (i > 0) {
6152 						(void) fprintf(stderr,
6153 						    gettext("\"all\" conflicts "
6154 						    "with specific fields "
6155 						    "given to -o option\n"));
6156 						usage(B_FALSE);
6157 					}
6158 					cb.cb_columns[0] = GET_COL_NAME;
6159 					cb.cb_columns[1] = GET_COL_PROPERTY;
6160 					cb.cb_columns[2] = GET_COL_VALUE;
6161 					cb.cb_columns[3] = GET_COL_SOURCE;
6162 					i = ZFS_GET_NCOLS;
6163 					break;
6164 				default:
6165 					(void) fprintf(stderr,
6166 					    gettext("invalid column name "
6167 					    "'%s'\n"), suboptarg);
6168 					usage(B_FALSE);
6169 				}
6170 			}
6171 			break;
6172 		case '?':
6173 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
6174 			    optopt);
6175 			usage(B_FALSE);
6176 		}
6177 	}
6178 
6179 	argc -= optind;
6180 	argv += optind;
6181 
6182 	if (argc < 1) {
6183 		(void) fprintf(stderr, gettext("missing property "
6184 		    "argument\n"));
6185 		usage(B_FALSE);
6186 	}
6187 
6188 	if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
6189 	    ZFS_TYPE_POOL) != 0)
6190 		usage(B_FALSE);
6191 
6192 	argc--;
6193 	argv++;
6194 
6195 	if (cb.cb_proplist != NULL) {
6196 		fake_name.pl_prop = ZPOOL_PROP_NAME;
6197 		fake_name.pl_width = strlen(gettext("NAME"));
6198 		fake_name.pl_next = cb.cb_proplist;
6199 		cb.cb_proplist = &fake_name;
6200 	}
6201 
6202 	ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
6203 	    get_callback, &cb);
6204 
6205 	if (cb.cb_proplist == &fake_name)
6206 		zprop_free_list(fake_name.pl_next);
6207 	else
6208 		zprop_free_list(cb.cb_proplist);
6209 
6210 	return (ret);
6211 }
6212 
6213 typedef struct set_cbdata {
6214 	char *cb_propname;
6215 	char *cb_value;
6216 	boolean_t cb_any_successful;
6217 } set_cbdata_t;
6218 
6219 int
set_callback(zpool_handle_t * zhp,void * data)6220 set_callback(zpool_handle_t *zhp, void *data)
6221 {
6222 	int error;
6223 	set_cbdata_t *cb = (set_cbdata_t *)data;
6224 
6225 	error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
6226 
6227 	if (!error)
6228 		cb->cb_any_successful = B_TRUE;
6229 
6230 	return (error);
6231 }
6232 
6233 int
zpool_do_set(int argc,char ** argv)6234 zpool_do_set(int argc, char **argv)
6235 {
6236 	set_cbdata_t cb = { 0 };
6237 	int error;
6238 
6239 	if (argc > 1 && argv[1][0] == '-') {
6240 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
6241 		    argv[1][1]);
6242 		usage(B_FALSE);
6243 	}
6244 
6245 	if (argc < 2) {
6246 		(void) fprintf(stderr, gettext("missing property=value "
6247 		    "argument\n"));
6248 		usage(B_FALSE);
6249 	}
6250 
6251 	if (argc < 3) {
6252 		(void) fprintf(stderr, gettext("missing pool name\n"));
6253 		usage(B_FALSE);
6254 	}
6255 
6256 	if (argc > 3) {
6257 		(void) fprintf(stderr, gettext("too many pool names\n"));
6258 		usage(B_FALSE);
6259 	}
6260 
6261 	cb.cb_propname = argv[1];
6262 	cb.cb_value = strchr(cb.cb_propname, '=');
6263 	if (cb.cb_value == NULL) {
6264 		(void) fprintf(stderr, gettext("missing value in "
6265 		    "property=value argument\n"));
6266 		usage(B_FALSE);
6267 	}
6268 
6269 	*(cb.cb_value) = '\0';
6270 	cb.cb_value++;
6271 
6272 	error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6273 	    set_callback, &cb);
6274 
6275 	return (error);
6276 }
6277 
6278 static int
find_command_idx(char * command,int * idx)6279 find_command_idx(char *command, int *idx)
6280 {
6281 	int i;
6282 
6283 	for (i = 0; i < NCOMMAND; i++) {
6284 		if (command_table[i].name == NULL)
6285 			continue;
6286 
6287 		if (strcmp(command, command_table[i].name) == 0) {
6288 			*idx = i;
6289 			return (0);
6290 		}
6291 	}
6292 	return (1);
6293 }
6294 
6295 int
main(int argc,char ** argv)6296 main(int argc, char **argv)
6297 {
6298 	int ret = 0;
6299 	int i;
6300 	char *cmdname;
6301 
6302 	(void) setlocale(LC_ALL, "");
6303 	(void) textdomain(TEXT_DOMAIN);
6304 
6305 	if ((g_zfs = libzfs_init()) == NULL) {
6306 		(void) fprintf(stderr, gettext("internal error: failed to "
6307 		    "initialize ZFS library\n"));
6308 		return (1);
6309 	}
6310 
6311 	libzfs_print_on_error(g_zfs, B_TRUE);
6312 
6313 	opterr = 0;
6314 
6315 	/*
6316 	 * Make sure the user has specified some command.
6317 	 */
6318 	if (argc < 2) {
6319 		(void) fprintf(stderr, gettext("missing command\n"));
6320 		usage(B_FALSE);
6321 	}
6322 
6323 	cmdname = argv[1];
6324 
6325 	/*
6326 	 * Special case '-?'
6327 	 */
6328 	if (strcmp(cmdname, "-?") == 0)
6329 		usage(B_TRUE);
6330 
6331 	zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6332 
6333 	/*
6334 	 * Run the appropriate command.
6335 	 */
6336 	if (find_command_idx(cmdname, &i) == 0) {
6337 		current_command = &command_table[i];
6338 		ret = command_table[i].func(argc - 1, argv + 1);
6339 	} else if (strchr(cmdname, '=')) {
6340 		verify(find_command_idx("set", &i) == 0);
6341 		current_command = &command_table[i];
6342 		ret = command_table[i].func(argc, argv);
6343 	} else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6344 		/*
6345 		 * 'freeze' is a vile debugging abomination, so we treat
6346 		 * it as such.
6347 		 */
6348 		zfs_cmd_t zc = { 0 };
6349 		(void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
6350 		return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
6351 	} else {
6352 		(void) fprintf(stderr, gettext("unrecognized "
6353 		    "command '%s'\n"), cmdname);
6354 		usage(B_FALSE);
6355 	}
6356 
6357 	if (ret == 0 && log_history)
6358 		(void) zpool_log_history(g_zfs, history_str);
6359 
6360 	libzfs_fini(g_zfs);
6361 
6362 	/*
6363 	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
6364 	 * for the purposes of running ::findleaks.
6365 	 */
6366 	if (getenv("ZFS_ABORT") != NULL) {
6367 		(void) printf("dumping core by request\n");
6368 		abort();
6369 	}
6370 
6371 	return (ret);
6372 }
6373