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