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