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