]> git.proxmox.com Git - mirror_zfs.git/blame - cmd/zpool/zpool_main.c
Linux 4.7 compat: use iterate_shared for concurrent readdir
[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 4270print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
bc2d8093 4271 boolean_t valid, enum zfs_nicenum_format format)
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
bc2d8093
CE
4282 zfs_nicenum_format(value, propval, sizeof (propval),
4283 format);
a05dfd00
GW
4284 break;
4285 case ZPOOL_PROP_FRAGMENTATION:
4286 if (value == ZFS_FRAG_INVALID) {
4287 (void) strlcpy(propval, "-", sizeof (propval));
bc2d8093
CE
4288 } else if (format == ZFS_NICENUM_RAW) {
4289 (void) snprintf(propval, sizeof (propval), "%llu",
4290 (unsigned long long)value);
a05dfd00
GW
4291 } else {
4292 (void) snprintf(propval, sizeof (propval), "%llu%%",
4293 (unsigned long long)value);
4294 }
4295 break;
4296 case ZPOOL_PROP_CAPACITY:
bc2d8093
CE
4297 if (format == ZFS_NICENUM_RAW)
4298 (void) snprintf(propval, sizeof (propval), "%llu",
4299 (unsigned long long)value);
4300 else
4301 (void) snprintf(propval, sizeof (propval), "%llu%%",
4302 (unsigned long long)value);
a05dfd00
GW
4303 break;
4304 default:
bc2d8093 4305 zfs_nicenum_format(value, propval, sizeof (propval), format);
a05dfd00
GW
4306 }
4307
4308 if (!valid)
4309 (void) strlcpy(propval, "-", sizeof (propval));
1bd201e7
CS
4310
4311 if (scripted)
4312 (void) printf("\t%s", propval);
4313 else
4314 (void) printf(" %*s", (int)width, propval);
4315}
4316
4317void
4318print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
4319 list_cbdata_t *cb, int depth)
4320{
4321 nvlist_t **child;
4322 vdev_stat_t *vs;
4323 uint_t c, children;
4324 char *vname;
4325 boolean_t scripted = cb->cb_scripted;
8e4c5c9a
JWK
4326 uint64_t islog = B_FALSE;
4327 boolean_t haslog = B_FALSE;
4328 char *dashes = "%-*s - - - - - -\n";
1bd201e7
CS
4329
4330 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
4331 (uint64_t **)&vs, &c) == 0);
4332
4333 if (name != NULL) {
a05dfd00
GW
4334 boolean_t toplevel = (vs->vs_space != 0);
4335 uint64_t cap;
bc2d8093
CE
4336 enum zfs_nicenum_format format;
4337
4338 if (cb->cb_literal)
4339 format = ZFS_NICENUM_RAW;
4340 else
4341 format = ZFS_NICENUM_1024;
a05dfd00 4342
1bd201e7
CS
4343 if (scripted)
4344 (void) printf("\t%s", name);
4345 else if (strlen(name) + depth > cb->cb_namewidth)
4346 (void) printf("%*s%s", depth, "", name);
4347 else
4348 (void) printf("%*s%s%*s", depth, "", name,
4349 (int)(cb->cb_namewidth - strlen(name) - depth), "");
4350
a05dfd00
GW
4351 /*
4352 * Print the properties for the individual vdevs. Some
4353 * properties are only applicable to toplevel vdevs. The
4354 * 'toplevel' boolean value is passed to the print_one_column()
4355 * to indicate that the value is valid.
4356 */
4357 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
bc2d8093 4358 toplevel, format);
a05dfd00 4359 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
bc2d8093 4360 toplevel, format);
a05dfd00 4361 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
bc2d8093 4362 scripted, toplevel, format);
a05dfd00 4363 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
bc2d8093 4364 B_TRUE, format);
a05dfd00
GW
4365 print_one_column(ZPOOL_PROP_FRAGMENTATION,
4366 vs->vs_fragmentation, scripted,
bc2d8093
CE
4367 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel),
4368 format);
a05dfd00
GW
4369 cap = (vs->vs_space == 0) ? 0 :
4370 (vs->vs_alloc * 100 / vs->vs_space);
bc2d8093
CE
4371 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel,
4372 format);
1bd201e7
CS
4373 (void) printf("\n");
4374 }
4375
4376 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
4377 &child, &children) != 0)
4378 return;
4379
4380 for (c = 0; c < children; c++) {
4381 uint64_t ishole = B_FALSE;
4382
4383 if (nvlist_lookup_uint64(child[c],
4384 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
4385 continue;
4386
8e4c5c9a
JWK
4387 if (nvlist_lookup_uint64(child[c],
4388 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
4389 haslog = B_TRUE;
4390 continue;
4391 }
4392
d2f3e292
RY
4393 vname = zpool_vdev_name(g_zfs, zhp, child[c],
4394 cb->cb_name_flags);
1bd201e7
CS
4395 print_list_stats(zhp, vname, child[c], cb, depth + 2);
4396 free(vname);
4397 }
4398
8e4c5c9a
JWK
4399 if (haslog == B_TRUE) {
4400 /* LINTED E_SEC_PRINTF_VAR_FMT */
4401 (void) printf(dashes, cb->cb_namewidth, "log");
4402 for (c = 0; c < children; c++) {
4403 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
4404 &islog) != 0 || !islog)
4405 continue;
d2f3e292
RY
4406 vname = zpool_vdev_name(g_zfs, zhp, child[c],
4407 cb->cb_name_flags);
8e4c5c9a
JWK
4408 print_list_stats(zhp, vname, child[c], cb, depth + 2);
4409 free(vname);
4410 }
4411 }
4412
1bd201e7 4413 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
8e4c5c9a
JWK
4414 &child, &children) == 0 && children > 0) {
4415 /* LINTED E_SEC_PRINTF_VAR_FMT */
4416 (void) printf(dashes, cb->cb_namewidth, "cache");
4417 for (c = 0; c < children; c++) {
d2f3e292
RY
4418 vname = zpool_vdev_name(g_zfs, zhp, child[c],
4419 cb->cb_name_flags);
8e4c5c9a
JWK
4420 print_list_stats(zhp, vname, child[c], cb, depth + 2);
4421 free(vname);
4422 }
4423 }
1bd201e7 4424
8e4c5c9a
JWK
4425 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
4426 &children) == 0 && children > 0) {
4427 /* LINTED E_SEC_PRINTF_VAR_FMT */
4428 (void) printf(dashes, cb->cb_namewidth, "spare");
1bd201e7 4429 for (c = 0; c < children; c++) {
d2f3e292
RY
4430 vname = zpool_vdev_name(g_zfs, zhp, child[c],
4431 cb->cb_name_flags);
1bd201e7
CS
4432 print_list_stats(zhp, vname, child[c], cb, depth + 2);
4433 free(vname);
4434 }
4435 }
4436}
4437
4438
34dc7c2f
BB
4439/*
4440 * Generic callback function to list a pool.
4441 */
4442int
4443list_callback(zpool_handle_t *zhp, void *data)
4444{
4445 list_cbdata_t *cbp = data;
1bd201e7
CS
4446 nvlist_t *config;
4447 nvlist_t *nvroot;
34dc7c2f 4448
1bd201e7 4449 config = zpool_get_config(zhp, NULL);
34dc7c2f 4450
1bd201e7
CS
4451 print_pool(zhp, cbp);
4452 if (!cbp->cb_verbose)
4453 return (0);
4454
4455 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4456 &nvroot) == 0);
4457 print_list_stats(zhp, NULL, nvroot, cbp, 0);
34dc7c2f
BB
4458
4459 return (0);
4460}
4461
4462/*
2a8b84b7 4463 * zpool list [-gHLpP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
34dc7c2f 4464 *
d2f3e292 4465 * -g Display guid for individual vdev name.
34dc7c2f
BB
4466 * -H Scripted mode. Don't display headers, and separate properties
4467 * by a single tab.
d2f3e292 4468 * -L Follow links when resolving vdev path name.
34dc7c2f 4469 * -o List of properties to display. Defaults to
a05dfd00
GW
4470 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
4471 * "dedupratio,health,altroot"
2a8b84b7 4472 * -p Display values in parsable (exact) format.
a77f29f9 4473 * -P Display full path for vdev name.
428870ff 4474 * -T Display a timestamp in date(1) or Unix format
34dc7c2f
BB
4475 *
4476 * List all pools in the system, whether or not they're healthy. Output space
4477 * statistics for each one, as well as health status summary.
4478 */
4479int
4480zpool_do_list(int argc, char **argv)
4481{
4482 int c;
cd72af9c 4483 int ret = 0;
34dc7c2f
BB
4484 list_cbdata_t cb = { 0 };
4485 static char default_props[] =
a05dfd00 4486 "name,size,allocated,free,expandsize,fragmentation,capacity,"
f3a7f661 4487 "dedupratio,health,altroot";
34dc7c2f 4488 char *props = default_props;
193a37cb
TH
4489 float interval = 0;
4490 unsigned long count = 0;
1bd201e7
CS
4491 zpool_list_t *list;
4492 boolean_t first = B_TRUE;
34dc7c2f
BB
4493
4494 /* check options */
2a8b84b7 4495 while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
34dc7c2f 4496 switch (c) {
d2f3e292
RY
4497 case 'g':
4498 cb.cb_name_flags |= VDEV_NAME_GUID;
4499 break;
34dc7c2f
BB
4500 case 'H':
4501 cb.cb_scripted = B_TRUE;
4502 break;
d2f3e292
RY
4503 case 'L':
4504 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
4505 break;
34dc7c2f
BB
4506 case 'o':
4507 props = optarg;
4508 break;
a77f29f9 4509 case 'P':
d2f3e292
RY
4510 cb.cb_name_flags |= VDEV_NAME_PATH;
4511 break;
2a8b84b7
AS
4512 case 'p':
4513 cb.cb_literal = B_TRUE;
4514 break;
428870ff
BB
4515 case 'T':
4516 get_timestamp_arg(*optarg);
4517 break;
1bd201e7
CS
4518 case 'v':
4519 cb.cb_verbose = B_TRUE;
4520 break;
34dc7c2f
BB
4521 case ':':
4522 (void) fprintf(stderr, gettext("missing argument for "
4523 "'%c' option\n"), optopt);
4524 usage(B_FALSE);
4525 break;
4526 case '?':
4527 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4528 optopt);
4529 usage(B_FALSE);
4530 }
4531 }
4532
4533 argc -= optind;
4534 argv += optind;
4535
428870ff
BB
4536 get_interval_count(&argc, argv, &interval, &count);
4537
34dc7c2f
BB
4538 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
4539 usage(B_FALSE);
4540
428870ff 4541 for (;;) {
3e43edd2
GW
4542 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
4543 &ret)) == NULL)
4544 return (1);
1bd201e7
CS
4545
4546 if (pool_list_count(list) == 0)
4547 break;
34dc7c2f 4548
428870ff
BB
4549 if (timestamp_fmt != NODATE)
4550 print_timestamp(timestamp_fmt);
34dc7c2f 4551
1bd201e7
CS
4552 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
4553 print_header(&cb);
4554 first = B_FALSE;
428870ff 4555 }
1bd201e7 4556 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
428870ff
BB
4557
4558 if (interval == 0)
4559 break;
4560
4561 if (count != 0 && --count == 0)
4562 break;
4563
3e43edd2 4564 pool_list_free(list);
193a37cb 4565 (void) fsleep(interval);
34dc7c2f
BB
4566 }
4567
3e43edd2
GW
4568 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
4569 (void) printf(gettext("no pools available\n"));
4570 ret = 0;
4571 }
4572
4573 pool_list_free(list);
428870ff 4574 zprop_free_list(cb.cb_proplist);
34dc7c2f
BB
4575 return (ret);
4576}
4577
34dc7c2f
BB
4578static int
4579zpool_do_attach_or_replace(int argc, char **argv, int replacing)
4580{
4581 boolean_t force = B_FALSE;
4582 int c;
4583 nvlist_t *nvroot;
4584 char *poolname, *old_disk, *new_disk;
4585 zpool_handle_t *zhp;
df831108
CP
4586 nvlist_t *props = NULL;
4587 char *propval;
34dc7c2f
BB
4588 int ret;
4589
4590 /* check options */
4588bf57 4591 while ((c = getopt(argc, argv, "fo:")) != -1) {
34dc7c2f
BB
4592 switch (c) {
4593 case 'f':
4594 force = B_TRUE;
4595 break;
df831108
CP
4596 case 'o':
4597 if ((propval = strchr(optarg, '=')) == NULL) {
4598 (void) fprintf(stderr, gettext("missing "
4599 "'=' for -o option\n"));
4600 usage(B_FALSE);
4601 }
4602 *propval = '\0';
4603 propval++;
4604
4605 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
4606 (add_prop_list(optarg, propval, &props, B_TRUE)))
4607 usage(B_FALSE);
4608 break;
34dc7c2f
BB
4609 case '?':
4610 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4611 optopt);
4612 usage(B_FALSE);
4613 }
4614 }
4615
4616 argc -= optind;
4617 argv += optind;
4618
4619 /* get pool name and check number of arguments */
4620 if (argc < 1) {
4621 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4622 usage(B_FALSE);
4623 }
4624
4625 poolname = argv[0];
4626
4627 if (argc < 2) {
4628 (void) fprintf(stderr,
4629 gettext("missing <device> specification\n"));
4630 usage(B_FALSE);
4631 }
4632
4633 old_disk = argv[1];
4634
4635 if (argc < 3) {
4636 if (!replacing) {
4637 (void) fprintf(stderr,
4638 gettext("missing <new_device> specification\n"));
4639 usage(B_FALSE);
4640 }
4641 new_disk = old_disk;
4642 argc -= 1;
4643 argv += 1;
4644 } else {
4645 new_disk = argv[2];
4646 argc -= 2;
4647 argv += 2;
4648 }
4649
4650 if (argc > 1) {
4651 (void) fprintf(stderr, gettext("too many arguments\n"));
4652 usage(B_FALSE);
4653 }
4654
4655 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4656 return (1);
4657
4658 if (zpool_get_config(zhp, NULL) == NULL) {
4659 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
4660 poolname);
4661 zpool_close(zhp);
4662 return (1);
4663 }
4664
df831108 4665 nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
b128c09f 4666 argc, argv);
34dc7c2f
BB
4667 if (nvroot == NULL) {
4668 zpool_close(zhp);
4669 return (1);
4670 }
4671
4672 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
4673
4674 nvlist_free(nvroot);
4675 zpool_close(zhp);
4676
4677 return (ret);
4678}
4679
4680/*
4681 * zpool replace [-f] <pool> <device> <new_device>
4682 *
4683 * -f Force attach, even if <new_device> appears to be in use.
4684 *
4685 * Replace <device> with <new_device>.
4686 */
4687/* ARGSUSED */
4688int
4689zpool_do_replace(int argc, char **argv)
4690{
4691 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
4692}
4693
4694/*
df831108 4695 * zpool attach [-f] [-o property=value] <pool> <device> <new_device>
34dc7c2f
BB
4696 *
4697 * -f Force attach, even if <new_device> appears to be in use.
df831108 4698 * -o Set property=value.
34dc7c2f
BB
4699 *
4700 * Attach <new_device> to the mirror containing <device>. If <device> is not
4701 * part of a mirror, then <device> will be transformed into a mirror of
4702 * <device> and <new_device>. In either case, <new_device> will begin life
4703 * with a DTL of [0, now], and will immediately begin to resilver itself.
4704 */
4705int
4706zpool_do_attach(int argc, char **argv)
4707{
4708 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
4709}
4710
4711/*
4712 * zpool detach [-f] <pool> <device>
4713 *
4714 * -f Force detach of <device>, even if DTLs argue against it
4715 * (not supported yet)
4716 *
4717 * Detach a device from a mirror. The operation will be refused if <device>
4718 * is the last device in the mirror, or if the DTLs indicate that this device
4719 * has the only valid copy of some data.
4720 */
4721/* ARGSUSED */
4722int
4723zpool_do_detach(int argc, char **argv)
4724{
4725 int c;
4726 char *poolname, *path;
4727 zpool_handle_t *zhp;
4728 int ret;
4729
4730 /* check options */
4731 while ((c = getopt(argc, argv, "f")) != -1) {
4732 switch (c) {
4733 case 'f':
4734 case '?':
4735 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4736 optopt);
4737 usage(B_FALSE);
4738 }
4739 }
4740
4741 argc -= optind;
4742 argv += optind;
4743
4744 /* get pool name and check number of arguments */
4745 if (argc < 1) {
4746 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4747 usage(B_FALSE);
4748 }
4749
4750 if (argc < 2) {
4751 (void) fprintf(stderr,
4752 gettext("missing <device> specification\n"));
4753 usage(B_FALSE);
4754 }
4755
4756 poolname = argv[0];
4757 path = argv[1];
4758
4759 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4760 return (1);
4761
4762 ret = zpool_vdev_detach(zhp, path);
4763
4764 zpool_close(zhp);
4765
4766 return (ret);
4767}
4768
428870ff 4769/*
a77f29f9 4770 * zpool split [-gLnP] [-o prop=val] ...
428870ff
BB
4771 * [-o mntopt] ...
4772 * [-R altroot] <pool> <newpool> [<device> ...]
4773 *
d2f3e292
RY
4774 * -g Display guid for individual vdev name.
4775 * -L Follow links when resolving vdev path name.
428870ff
BB
4776 * -n Do not split the pool, but display the resulting layout if
4777 * it were to be split.
4778 * -o Set property=value, or set mount options.
a77f29f9 4779 * -P Display full path for vdev name.
428870ff
BB
4780 * -R Mount the split-off pool under an alternate root.
4781 *
4782 * Splits the named pool and gives it the new pool name. Devices to be split
4783 * off may be listed, provided that no more than one device is specified
4784 * per top-level vdev mirror. The newly split pool is left in an exported
4785 * state unless -R is specified.
4786 *
4787 * Restrictions: the top-level of the pool pool must only be made up of
4788 * mirrors; all devices in the pool must be healthy; no device may be
4789 * undergoing a resilvering operation.
4790 */
4791int
4792zpool_do_split(int argc, char **argv)
4793{
4794 char *srcpool, *newpool, *propval;
4795 char *mntopts = NULL;
4796 splitflags_t flags;
4797 int c, ret = 0;
4798 zpool_handle_t *zhp;
4799 nvlist_t *config, *props = NULL;
4800
4801 flags.dryrun = B_FALSE;
4802 flags.import = B_FALSE;
d2f3e292 4803 flags.name_flags = 0;
428870ff
BB
4804
4805 /* check options */
a77f29f9 4806 while ((c = getopt(argc, argv, ":gLR:no:P")) != -1) {
428870ff 4807 switch (c) {
d2f3e292
RY
4808 case 'g':
4809 flags.name_flags |= VDEV_NAME_GUID;
4810 break;
4811 case 'L':
4812 flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
4813 break;
428870ff
BB
4814 case 'R':
4815 flags.import = B_TRUE;
4816 if (add_prop_list(
4817 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
4818 &props, B_TRUE) != 0) {
8a5fc748 4819 nvlist_free(props);
428870ff
BB
4820 usage(B_FALSE);
4821 }
4822 break;
4823 case 'n':
4824 flags.dryrun = B_TRUE;
4825 break;
4826 case 'o':
4827 if ((propval = strchr(optarg, '=')) != NULL) {
4828 *propval = '\0';
4829 propval++;
4830 if (add_prop_list(optarg, propval,
4831 &props, B_TRUE) != 0) {
8a5fc748 4832 nvlist_free(props);
428870ff
BB
4833 usage(B_FALSE);
4834 }
4835 } else {
4836 mntopts = optarg;
4837 }
4838 break;
a77f29f9 4839 case 'P':
d2f3e292
RY
4840 flags.name_flags |= VDEV_NAME_PATH;
4841 break;
428870ff
BB
4842 case ':':
4843 (void) fprintf(stderr, gettext("missing argument for "
4844 "'%c' option\n"), optopt);
4845 usage(B_FALSE);
4846 break;
4847 case '?':
4848 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4849 optopt);
4850 usage(B_FALSE);
4851 break;
4852 }
4853 }
4854
4855 if (!flags.import && mntopts != NULL) {
4856 (void) fprintf(stderr, gettext("setting mntopts is only "
4857 "valid when importing the pool\n"));
4858 usage(B_FALSE);
4859 }
4860
4861 argc -= optind;
4862 argv += optind;
4863
4864 if (argc < 1) {
4865 (void) fprintf(stderr, gettext("Missing pool name\n"));
4866 usage(B_FALSE);
4867 }
4868 if (argc < 2) {
4869 (void) fprintf(stderr, gettext("Missing new pool name\n"));
4870 usage(B_FALSE);
4871 }
4872
4873 srcpool = argv[0];
4874 newpool = argv[1];
4875
4876 argc -= 2;
4877 argv += 2;
4878
4879 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
4880 return (1);
4881
4882 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
4883 if (config == NULL) {
4884 ret = 1;
4885 } else {
4886 if (flags.dryrun) {
4887 (void) printf(gettext("would create '%s' with the "
4888 "following layout:\n\n"), newpool);
d2f3e292
RY
4889 print_vdev_tree(NULL, newpool, config, 0, B_FALSE,
4890 flags.name_flags);
428870ff
BB
4891 }
4892 nvlist_free(config);
4893 }
4894
4895 zpool_close(zhp);
4896
4897 if (ret != 0 || flags.dryrun || !flags.import)
4898 return (ret);
4899
4900 /*
4901 * The split was successful. Now we need to open the new
4902 * pool and import it.
4903 */
4904 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
4905 return (1);
4906 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
4907 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
4908 ret = 1;
af909a10 4909 (void) fprintf(stderr, gettext("Split was successful, but "
428870ff
BB
4910 "the datasets could not all be mounted\n"));
4911 (void) fprintf(stderr, gettext("Try doing '%s' with a "
4912 "different altroot\n"), "zpool import");
4913 }
4914 zpool_close(zhp);
4915
4916 return (ret);
4917}
4918
4919
4920
34dc7c2f
BB
4921/*
4922 * zpool online <pool> <device> ...
4923 */
4924int
4925zpool_do_online(int argc, char **argv)
4926{
4927 int c, i;
4928 char *poolname;
4929 zpool_handle_t *zhp;
4930 int ret = 0;
4931 vdev_state_t newstate;
9babb374 4932 int flags = 0;
34dc7c2f
BB
4933
4934 /* check options */
9babb374 4935 while ((c = getopt(argc, argv, "et")) != -1) {
34dc7c2f 4936 switch (c) {
9babb374
BB
4937 case 'e':
4938 flags |= ZFS_ONLINE_EXPAND;
4939 break;
34dc7c2f
BB
4940 case 't':
4941 case '?':
4942 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4943 optopt);
4944 usage(B_FALSE);
4945 }
4946 }
4947
4948 argc -= optind;
4949 argv += optind;
4950
4951 /* get pool name and check number of arguments */
4952 if (argc < 1) {
4953 (void) fprintf(stderr, gettext("missing pool name\n"));
4954 usage(B_FALSE);
4955 }
4956 if (argc < 2) {
4957 (void) fprintf(stderr, gettext("missing device name\n"));
4958 usage(B_FALSE);
4959 }
4960
4961 poolname = argv[0];
4962
4963 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4964 return (1);
4965
4966 for (i = 1; i < argc; i++) {
9babb374 4967 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
34dc7c2f
BB
4968 if (newstate != VDEV_STATE_HEALTHY) {
4969 (void) printf(gettext("warning: device '%s' "
4970 "onlined, but remains in faulted state\n"),
4971 argv[i]);
4972 if (newstate == VDEV_STATE_FAULTED)
4973 (void) printf(gettext("use 'zpool "
4974 "clear' to restore a faulted "
4975 "device\n"));
4976 else
4977 (void) printf(gettext("use 'zpool "
4978 "replace' to replace devices "
4979 "that are no longer present\n"));
4980 }
4981 } else {
4982 ret = 1;
4983 }
4984 }
4985
4986 zpool_close(zhp);
4987
4988 return (ret);
4989}
4990
4991/*
4992 * zpool offline [-ft] <pool> <device> ...
4993 *
4994 * -f Force the device into the offline state, even if doing
4995 * so would appear to compromise pool availability.
4996 * (not supported yet)
4997 *
4998 * -t Only take the device off-line temporarily. The offline
4999 * state will not be persistent across reboots.
5000 */
5001/* ARGSUSED */
5002int
5003zpool_do_offline(int argc, char **argv)
5004{
5005 int c, i;
5006 char *poolname;
5007 zpool_handle_t *zhp;
5008 int ret = 0;
5009 boolean_t istmp = B_FALSE;
5010
5011 /* check options */
5012 while ((c = getopt(argc, argv, "ft")) != -1) {
5013 switch (c) {
5014 case 't':
5015 istmp = B_TRUE;
5016 break;
5017 case 'f':
5018 case '?':
5019 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5020 optopt);
5021 usage(B_FALSE);
5022 }
5023 }
5024
5025 argc -= optind;
5026 argv += optind;
5027
5028 /* get pool name and check number of arguments */
5029 if (argc < 1) {
5030 (void) fprintf(stderr, gettext("missing pool name\n"));
5031 usage(B_FALSE);
5032 }
5033 if (argc < 2) {
5034 (void) fprintf(stderr, gettext("missing device name\n"));
5035 usage(B_FALSE);
5036 }
5037
5038 poolname = argv[0];
5039
5040 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5041 return (1);
5042
5043 for (i = 1; i < argc; i++) {
5044 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
5045 ret = 1;
5046 }
5047
5048 zpool_close(zhp);
5049
5050 return (ret);
5051}
5052
5053/*
5054 * zpool clear <pool> [device]
5055 *
5056 * Clear all errors associated with a pool or a particular device.
5057 */
5058int
5059zpool_do_clear(int argc, char **argv)
5060{
428870ff 5061 int c;
34dc7c2f 5062 int ret = 0;
428870ff
BB
5063 boolean_t dryrun = B_FALSE;
5064 boolean_t do_rewind = B_FALSE;
5065 boolean_t xtreme_rewind = B_FALSE;
5066 uint32_t rewind_policy = ZPOOL_NO_REWIND;
5067 nvlist_t *policy = NULL;
34dc7c2f
BB
5068 zpool_handle_t *zhp;
5069 char *pool, *device;
5070
428870ff
BB
5071 /* check options */
5072 while ((c = getopt(argc, argv, "FnX")) != -1) {
5073 switch (c) {
5074 case 'F':
5075 do_rewind = B_TRUE;
5076 break;
5077 case 'n':
5078 dryrun = B_TRUE;
5079 break;
5080 case 'X':
5081 xtreme_rewind = B_TRUE;
5082 break;
5083 case '?':
5084 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5085 optopt);
5086 usage(B_FALSE);
5087 }
5088 }
5089
5090 argc -= optind;
5091 argv += optind;
5092
5093 if (argc < 1) {
34dc7c2f
BB
5094 (void) fprintf(stderr, gettext("missing pool name\n"));
5095 usage(B_FALSE);
5096 }
5097
428870ff 5098 if (argc > 2) {
34dc7c2f
BB
5099 (void) fprintf(stderr, gettext("too many arguments\n"));
5100 usage(B_FALSE);
5101 }
5102
428870ff
BB
5103 if ((dryrun || xtreme_rewind) && !do_rewind) {
5104 (void) fprintf(stderr,
5105 gettext("-n or -X only meaningful with -F\n"));
5106 usage(B_FALSE);
5107 }
5108 if (dryrun)
5109 rewind_policy = ZPOOL_TRY_REWIND;
5110 else if (do_rewind)
5111 rewind_policy = ZPOOL_DO_REWIND;
5112 if (xtreme_rewind)
5113 rewind_policy |= ZPOOL_EXTREME_REWIND;
5114
5115 /* In future, further rewind policy choices can be passed along here */
5116 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
5117 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
5118 return (1);
5119
5120 pool = argv[0];
5121 device = argc == 2 ? argv[1] : NULL;
34dc7c2f 5122
428870ff
BB
5123 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
5124 nvlist_free(policy);
34dc7c2f 5125 return (1);
428870ff 5126 }
34dc7c2f 5127
428870ff 5128 if (zpool_clear(zhp, device, policy) != 0)
34dc7c2f
BB
5129 ret = 1;
5130
5131 zpool_close(zhp);
5132
428870ff
BB
5133 nvlist_free(policy);
5134
34dc7c2f
BB
5135 return (ret);
5136}
5137
3541dc6d
GA
5138/*
5139 * zpool reguid <pool>
5140 */
5141int
5142zpool_do_reguid(int argc, char **argv)
5143{
5144 int c;
5145 char *poolname;
5146 zpool_handle_t *zhp;
5147 int ret = 0;
5148
5149 /* check options */
5150 while ((c = getopt(argc, argv, "")) != -1) {
5151 switch (c) {
5152 case '?':
5153 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5154 optopt);
5155 usage(B_FALSE);
5156 }
5157 }
5158
5159 argc -= optind;
5160 argv += optind;
5161
5162 /* get pool name and check number of arguments */
5163 if (argc < 1) {
5164 (void) fprintf(stderr, gettext("missing pool name\n"));
5165 usage(B_FALSE);
5166 }
5167
5168 if (argc > 1) {
5169 (void) fprintf(stderr, gettext("too many arguments\n"));
5170 usage(B_FALSE);
5171 }
5172
5173 poolname = argv[0];
5174 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5175 return (1);
5176
5177 ret = zpool_reguid(zhp);
5178
5179 zpool_close(zhp);
5180 return (ret);
5181}
5182
5183
1bd201e7
CS
5184/*
5185 * zpool reopen <pool>
5186 *
5187 * Reopen the pool so that the kernel can update the sizes of all vdevs.
1bd201e7
CS
5188 */
5189int
5190zpool_do_reopen(int argc, char **argv)
5191{
5853fe79 5192 int c;
1bd201e7
CS
5193 int ret = 0;
5194 zpool_handle_t *zhp;
5195 char *pool;
5196
5853fe79
GW
5197 /* check options */
5198 while ((c = getopt(argc, argv, "")) != -1) {
5199 switch (c) {
5200 case '?':
5201 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5202 optopt);
5203 usage(B_FALSE);
5204 }
5205 }
5206
1bd201e7
CS
5207 argc--;
5208 argv++;
5209
5853fe79
GW
5210 if (argc < 1) {
5211 (void) fprintf(stderr, gettext("missing pool name\n"));
5212 usage(B_FALSE);
5213 }
5214
5215 if (argc > 1) {
5216 (void) fprintf(stderr, gettext("too many arguments\n"));
5217 usage(B_FALSE);
5218 }
1bd201e7
CS
5219
5220 pool = argv[0];
5221 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
5222 return (1);
5223
5224 ret = zpool_reopen(zhp);
5225 zpool_close(zhp);
5226 return (ret);
5227}
5228
34dc7c2f
BB
5229typedef struct scrub_cbdata {
5230 int cb_type;
5231 int cb_argc;
5232 char **cb_argv;
5233} scrub_cbdata_t;
5234
5235int
5236scrub_callback(zpool_handle_t *zhp, void *data)
5237{
5238 scrub_cbdata_t *cb = data;
5239 int err;
5240
5241 /*
5242 * Ignore faulted pools.
5243 */
5244 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5245 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
5246 "currently unavailable\n"), zpool_get_name(zhp));
5247 return (1);
5248 }
5249
428870ff 5250 err = zpool_scan(zhp, cb->cb_type);
34dc7c2f
BB
5251
5252 return (err != 0);
5253}
5254
5255/*
5256 * zpool scrub [-s] <pool> ...
5257 *
5258 * -s Stop. Stops any in-progress scrub.
5259 */
5260int
5261zpool_do_scrub(int argc, char **argv)
5262{
5263 int c;
5264 scrub_cbdata_t cb;
5265
428870ff 5266 cb.cb_type = POOL_SCAN_SCRUB;
34dc7c2f
BB
5267
5268 /* check options */
5269 while ((c = getopt(argc, argv, "s")) != -1) {
5270 switch (c) {
5271 case 's':
428870ff 5272 cb.cb_type = POOL_SCAN_NONE;
34dc7c2f
BB
5273 break;
5274 case '?':
5275 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5276 optopt);
5277 usage(B_FALSE);
5278 }
5279 }
5280
5281 cb.cb_argc = argc;
5282 cb.cb_argv = argv;
5283 argc -= optind;
5284 argv += optind;
5285
5286 if (argc < 1) {
5287 (void) fprintf(stderr, gettext("missing pool name argument\n"));
5288 usage(B_FALSE);
5289 }
5290
5291 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
5292}
5293
5294typedef struct status_cbdata {
5295 int cb_count;
d2f3e292 5296 int cb_name_flags;
34dc7c2f
BB
5297 boolean_t cb_allpools;
5298 boolean_t cb_verbose;
5299 boolean_t cb_explain;
5300 boolean_t cb_first;
428870ff 5301 boolean_t cb_dedup_stats;
34dc7c2f
BB
5302} status_cbdata_t;
5303
5304/*
5305 * Print out detailed scrub status.
5306 */
5307void
428870ff 5308print_scan_status(pool_scan_stat_t *ps)
34dc7c2f 5309{
428870ff 5310 time_t start, end;
572e2857 5311 uint64_t elapsed, mins_left, hours_left;
428870ff
BB
5312 uint64_t pass_exam, examined, total;
5313 uint_t rate;
34dc7c2f 5314 double fraction_done;
428870ff 5315 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
34dc7c2f 5316
24024589 5317 (void) printf(gettext(" scan: "));
34dc7c2f 5318
428870ff
BB
5319 /* If there's never been a scan, there's not much to say. */
5320 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
5321 ps->pss_func >= POOL_SCAN_FUNCS) {
34dc7c2f
BB
5322 (void) printf(gettext("none requested\n"));
5323 return;
5324 }
5325
428870ff
BB
5326 start = ps->pss_start_time;
5327 end = ps->pss_end_time;
5328 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
34dc7c2f 5329
428870ff
BB
5330 assert(ps->pss_func == POOL_SCAN_SCRUB ||
5331 ps->pss_func == POOL_SCAN_RESILVER);
5332 /*
5333 * Scan is finished or canceled.
5334 */
5335 if (ps->pss_state == DSS_FINISHED) {
5336 uint64_t minutes_taken = (end - start) / 60;
d4ed6673 5337 char *fmt = NULL;
428870ff
BB
5338
5339 if (ps->pss_func == POOL_SCAN_SCRUB) {
5340 fmt = gettext("scrub repaired %s in %lluh%um with "
5341 "%llu errors on %s");
5342 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
5343 fmt = gettext("resilvered %s in %lluh%um with "
5344 "%llu errors on %s");
5345 }
5346 /* LINTED */
5347 (void) printf(fmt, processed_buf,
34dc7c2f
BB
5348 (u_longlong_t)(minutes_taken / 60),
5349 (uint_t)(minutes_taken % 60),
428870ff
BB
5350 (u_longlong_t)ps->pss_errors,
5351 ctime((time_t *)&end));
5352 return;
5353 } else if (ps->pss_state == DSS_CANCELED) {
5354 if (ps->pss_func == POOL_SCAN_SCRUB) {
5355 (void) printf(gettext("scrub canceled on %s"),
5356 ctime(&end));
5357 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
5358 (void) printf(gettext("resilver canceled on %s"),
5359 ctime(&end));
5360 }
34dc7c2f
BB
5361 return;
5362 }
5363
428870ff
BB
5364 assert(ps->pss_state == DSS_SCANNING);
5365
5366 /*
5367 * Scan is in progress.
5368 */
5369 if (ps->pss_func == POOL_SCAN_SCRUB) {
5370 (void) printf(gettext("scrub in progress since %s"),
5371 ctime(&start));
5372 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
5373 (void) printf(gettext("resilver in progress since %s"),
5374 ctime(&start));
5375 }
34dc7c2f 5376
428870ff
BB
5377 examined = ps->pss_examined ? ps->pss_examined : 1;
5378 total = ps->pss_to_examine;
34dc7c2f 5379 fraction_done = (double)examined / total;
428870ff
BB
5380
5381 /* elapsed time for this pass */
5382 elapsed = time(NULL) - ps->pss_pass_start;
5383 elapsed = elapsed ? elapsed : 1;
5384 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
5385 rate = pass_exam / elapsed;
5386 rate = rate ? rate : 1;
5387 mins_left = ((total - examined) / rate) / 60;
572e2857 5388 hours_left = mins_left / 60;
428870ff
BB
5389
5390 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
5391 zfs_nicenum(total, total_buf, sizeof (total_buf));
5392 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
5393
572e2857
BB
5394 /*
5395 * do not print estimated time if hours_left is more than 30 days
5396 */
e7a05183 5397 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
572e2857
BB
5398 examined_buf, total_buf, rate_buf);
5399 if (hours_left < (30 * 24)) {
5400 (void) printf(gettext(", %lluh%um to go\n"),
5401 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
5402 } else {
5403 (void) printf(gettext(
5404 ", (scan is slow, no estimated time)\n"));
5405 }
428870ff
BB
5406
5407 if (ps->pss_func == POOL_SCAN_RESILVER) {
e7a05183 5408 (void) printf(gettext("\t%s resilvered, %.2f%% done\n"),
428870ff
BB
5409 processed_buf, 100 * fraction_done);
5410 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
e7a05183 5411 (void) printf(gettext("\t%s repaired, %.2f%% done\n"),
428870ff
BB
5412 processed_buf, 100 * fraction_done);
5413 }
34dc7c2f
BB
5414}
5415
34dc7c2f
BB
5416static void
5417print_error_log(zpool_handle_t *zhp)
5418{
5419 nvlist_t *nverrlist = NULL;
5420 nvpair_t *elem;
5421 char *pathname;
5422 size_t len = MAXPATHLEN * 2;
5423
5424 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
5425 (void) printf("errors: List of errors unavailable "
5426 "(insufficient privileges)\n");
5427 return;
5428 }
5429
5430 (void) printf("errors: Permanent errors have been "
5431 "detected in the following files:\n\n");
5432
5433 pathname = safe_malloc(len);
5434 elem = NULL;
5435 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
5436 nvlist_t *nv;
5437 uint64_t dsobj, obj;
5438
5439 verify(nvpair_value_nvlist(elem, &nv) == 0);
5440 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
5441 &dsobj) == 0);
5442 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
5443 &obj) == 0);
5444 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
5445 (void) printf("%7s %s\n", "", pathname);
5446 }
5447 free(pathname);
5448 nvlist_free(nverrlist);
5449}
5450
5451static void
5452print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
d2f3e292 5453 int namewidth, int name_flags)
34dc7c2f
BB
5454{
5455 uint_t i;
5456 char *name;
5457
5458 if (nspares == 0)
5459 return;
5460
5461 (void) printf(gettext("\tspares\n"));
5462
5463 for (i = 0; i < nspares; i++) {
d2f3e292 5464 name = zpool_vdev_name(g_zfs, zhp, spares[i], name_flags);
34dc7c2f 5465 print_status_config(zhp, name, spares[i],
d2f3e292 5466 namewidth, 2, B_TRUE, name_flags);
34dc7c2f
BB
5467 free(name);
5468 }
5469}
5470
5471static void
5472print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
d2f3e292 5473 int namewidth, int name_flags)
34dc7c2f
BB
5474{
5475 uint_t i;
5476 char *name;
5477
5478 if (nl2cache == 0)
5479 return;
5480
5481 (void) printf(gettext("\tcache\n"));
5482
5483 for (i = 0; i < nl2cache; i++) {
d2f3e292 5484 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], name_flags);
34dc7c2f 5485 print_status_config(zhp, name, l2cache[i],
d2f3e292 5486 namewidth, 2, B_FALSE, name_flags);
34dc7c2f
BB
5487 free(name);
5488 }
5489}
5490
428870ff
BB
5491static void
5492print_dedup_stats(nvlist_t *config)
5493{
5494 ddt_histogram_t *ddh;
5495 ddt_stat_t *dds;
5496 ddt_object_t *ddo;
5497 uint_t c;
5498
5499 /*
5500 * If the pool was faulted then we may not have been able to
32a9872b 5501 * obtain the config. Otherwise, if we have anything in the dedup
428870ff
BB
5502 * table continue processing the stats.
5503 */
5504 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
24024589 5505 (uint64_t **)&ddo, &c) != 0)
428870ff
BB
5506 return;
5507
5508 (void) printf("\n");
24024589
YP
5509 (void) printf(gettext(" dedup: "));
5510 if (ddo->ddo_count == 0) {
5511 (void) printf(gettext("no DDT entries\n"));
5512 return;
5513 }
5514
428870ff
BB
5515 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
5516 (u_longlong_t)ddo->ddo_count,
5517 (u_longlong_t)ddo->ddo_dspace,
5518 (u_longlong_t)ddo->ddo_mspace);
5519
5520 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
5521 (uint64_t **)&dds, &c) == 0);
5522 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
5523 (uint64_t **)&ddh, &c) == 0);
5524 zpool_dump_ddt(dds, ddh);
5525}
5526
34dc7c2f
BB
5527/*
5528 * Display a summary of pool status. Displays a summary such as:
5529 *
5530 * pool: tank
5531 * status: DEGRADED
5532 * reason: One or more devices ...
3cee2262 5533 * see: http://zfsonlinux.org/msg/ZFS-xxxx-01
34dc7c2f
BB
5534 * config:
5535 * mirror DEGRADED
5536 * c1t0d0 OK
5537 * c2t0d0 UNAVAIL
5538 *
5539 * When given the '-v' option, we print out the complete config. If the '-e'
5540 * option is specified, then we print out error rate information as well.
5541 */
5542int
5543status_callback(zpool_handle_t *zhp, void *data)
5544{
5545 status_cbdata_t *cbp = data;
5546 nvlist_t *config, *nvroot;
5547 char *msgid;
731782ec 5548 zpool_status_t reason;
ffe9d382 5549 zpool_errata_t errata;
34dc7c2f
BB
5550 const char *health;
5551 uint_t c;
5552 vdev_stat_t *vs;
5553
5554 config = zpool_get_config(zhp, NULL);
ffe9d382 5555 reason = zpool_get_status(zhp, &msgid, &errata);
34dc7c2f
BB
5556
5557 cbp->cb_count++;
5558
5559 /*
5560 * If we were given 'zpool status -x', only report those pools with
5561 * problems.
5562 */
c5b247f3
TC
5563 if (cbp->cb_explain &&
5564 (reason == ZPOOL_STATUS_OK ||
5565 reason == ZPOOL_STATUS_VERSION_OLDER ||
5566 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
34dc7c2f
BB
5567 if (!cbp->cb_allpools) {
5568 (void) printf(gettext("pool '%s' is healthy\n"),
5569 zpool_get_name(zhp));
5570 if (cbp->cb_first)
5571 cbp->cb_first = B_FALSE;
5572 }
5573 return (0);
5574 }
5575
5576 if (cbp->cb_first)
5577 cbp->cb_first = B_FALSE;
5578 else
5579 (void) printf("\n");
5580
5581 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5582 &nvroot) == 0);
428870ff 5583 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
5584 (uint64_t **)&vs, &c) == 0);
5585 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
5586
5587 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
5588 (void) printf(gettext(" state: %s\n"), health);
5589
5590 switch (reason) {
5591 case ZPOOL_STATUS_MISSING_DEV_R:
5592 (void) printf(gettext("status: One or more devices could not "
5593 "be opened. Sufficient replicas exist for\n\tthe pool to "
5594 "continue functioning in a degraded state.\n"));
5595 (void) printf(gettext("action: Attach the missing device and "
5596 "online it using 'zpool online'.\n"));
5597 break;
5598
5599 case ZPOOL_STATUS_MISSING_DEV_NR:
5600 (void) printf(gettext("status: One or more devices could not "
5601 "be opened. There are insufficient\n\treplicas for the "
5602 "pool to continue functioning.\n"));
5603 (void) printf(gettext("action: Attach the missing device and "
5604 "online it using 'zpool online'.\n"));
5605 break;
5606
5607 case ZPOOL_STATUS_CORRUPT_LABEL_R:
5608 (void) printf(gettext("status: One or more devices could not "
5609 "be used because the label is missing or\n\tinvalid. "
5610 "Sufficient replicas exist for the pool to continue\n\t"
5611 "functioning in a degraded state.\n"));
5612 (void) printf(gettext("action: Replace the device using "
5613 "'zpool replace'.\n"));
5614 break;
5615
5616 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
5617 (void) printf(gettext("status: One or more devices could not "
5618 "be used because the label is missing \n\tor invalid. "
5619 "There are insufficient replicas for the pool to "
5620 "continue\n\tfunctioning.\n"));
428870ff
BB
5621 zpool_explain_recover(zpool_get_handle(zhp),
5622 zpool_get_name(zhp), reason, config);
34dc7c2f
BB
5623 break;
5624
5625 case ZPOOL_STATUS_FAILING_DEV:
5626 (void) printf(gettext("status: One or more devices has "
5627 "experienced an unrecoverable error. An\n\tattempt was "
5628 "made to correct the error. Applications are "
5629 "unaffected.\n"));
5630 (void) printf(gettext("action: Determine if the device needs "
5631 "to be replaced, and clear the errors\n\tusing "
5632 "'zpool clear' or replace the device with 'zpool "
5633 "replace'.\n"));
5634 break;
5635
5636 case ZPOOL_STATUS_OFFLINE_DEV:
5637 (void) printf(gettext("status: One or more devices has "
5638 "been taken offline by the administrator.\n\tSufficient "
5639 "replicas exist for the pool to continue functioning in "
5640 "a\n\tdegraded state.\n"));
5641 (void) printf(gettext("action: Online the device using "
5642 "'zpool online' or replace the device with\n\t'zpool "
5643 "replace'.\n"));
5644 break;
5645
45d1cae3
BB
5646 case ZPOOL_STATUS_REMOVED_DEV:
5647 (void) printf(gettext("status: One or more devices has "
5648 "been removed by the administrator.\n\tSufficient "
5649 "replicas exist for the pool to continue functioning in "
5650 "a\n\tdegraded state.\n"));
5651 (void) printf(gettext("action: Online the device using "
5652 "'zpool online' or replace the device with\n\t'zpool "
5653 "replace'.\n"));
5654 break;
5655
34dc7c2f
BB
5656 case ZPOOL_STATUS_RESILVERING:
5657 (void) printf(gettext("status: One or more devices is "
5658 "currently being resilvered. The pool will\n\tcontinue "
5659 "to function, possibly in a degraded state.\n"));
5660 (void) printf(gettext("action: Wait for the resilver to "
5661 "complete.\n"));
5662 break;
5663
5664 case ZPOOL_STATUS_CORRUPT_DATA:
5665 (void) printf(gettext("status: One or more devices has "
5666 "experienced an error resulting in data\n\tcorruption. "
5667 "Applications may be affected.\n"));
5668 (void) printf(gettext("action: Restore the file in question "
5669 "if possible. Otherwise restore the\n\tentire pool from "
5670 "backup.\n"));
5671 break;
5672
5673 case ZPOOL_STATUS_CORRUPT_POOL:
5674 (void) printf(gettext("status: The pool metadata is corrupted "
5675 "and the pool cannot be opened.\n"));
428870ff
BB
5676 zpool_explain_recover(zpool_get_handle(zhp),
5677 zpool_get_name(zhp), reason, config);
34dc7c2f
BB
5678 break;
5679
5680 case ZPOOL_STATUS_VERSION_OLDER:
b9b24bb4
CS
5681 (void) printf(gettext("status: The pool is formatted using a "
5682 "legacy on-disk format. The pool can\n\tstill be used, "
5683 "but some features are unavailable.\n"));
34dc7c2f
BB
5684 (void) printf(gettext("action: Upgrade the pool using 'zpool "
5685 "upgrade'. Once this is done, the\n\tpool will no longer "
f52b31ea
BB
5686 "be accessible on software that does not support\n\t"
5687 "feature flags.\n"));
34dc7c2f
BB
5688 break;
5689
5690 case ZPOOL_STATUS_VERSION_NEWER:
5691 (void) printf(gettext("status: The pool has been upgraded to a "
5692 "newer, incompatible on-disk version.\n\tThe pool cannot "
5693 "be accessed on this system.\n"));
5694 (void) printf(gettext("action: Access the pool from a system "
5695 "running more recent software, or\n\trestore the pool from "
5696 "backup.\n"));
5697 break;
5698
b9b24bb4
CS
5699 case ZPOOL_STATUS_FEAT_DISABLED:
5700 (void) printf(gettext("status: Some supported features are not "
5701 "enabled on the pool. The pool can\n\tstill be used, but "
5702 "some features are unavailable.\n"));
5703 (void) printf(gettext("action: Enable all features using "
5704 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
5705 "longer be accessible by software that does not support\n\t"
5706 "the features. See zpool-features(5) for details.\n"));
5707 break;
5708
9ae529ec
CS
5709 case ZPOOL_STATUS_UNSUP_FEAT_READ:
5710 (void) printf(gettext("status: The pool cannot be accessed on "
5711 "this system because it uses the\n\tfollowing feature(s) "
5712 "not supported on this system:\n"));
5713 zpool_print_unsup_feat(config);
5714 (void) printf("\n");
5715 (void) printf(gettext("action: Access the pool from a system "
5716 "that supports the required feature(s),\n\tor restore the "
5717 "pool from backup.\n"));
5718 break;
5719
5720 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
5721 (void) printf(gettext("status: The pool can only be accessed "
5722 "in read-only mode on this system. It\n\tcannot be "
5723 "accessed in read-write mode because it uses the "
5724 "following\n\tfeature(s) not supported on this system:\n"));
5725 zpool_print_unsup_feat(config);
5726 (void) printf("\n");
5727 (void) printf(gettext("action: The pool cannot be accessed in "
5728 "read-write mode. Import the pool with\n"
5729 "\t\"-o readonly=on\", access the pool from a system that "
5730 "supports the\n\trequired feature(s), or restore the "
5731 "pool from backup.\n"));
5732 break;
5733
34dc7c2f
BB
5734 case ZPOOL_STATUS_FAULTED_DEV_R:
5735 (void) printf(gettext("status: One or more devices are "
5736 "faulted in response to persistent errors.\n\tSufficient "
5737 "replicas exist for the pool to continue functioning "
5738 "in a\n\tdegraded state.\n"));
5739 (void) printf(gettext("action: Replace the faulted device, "
5740 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
5741 break;
5742
5743 case ZPOOL_STATUS_FAULTED_DEV_NR:
5744 (void) printf(gettext("status: One or more devices are "
5745 "faulted in response to persistent errors. There are "
5746 "insufficient replicas for the pool to\n\tcontinue "
5747 "functioning.\n"));
5748 (void) printf(gettext("action: Destroy and re-create the pool "
5749 "from a backup source. Manually marking the device\n"
5750 "\trepaired using 'zpool clear' may allow some data "
5751 "to be recovered.\n"));
5752 break;
5753
b128c09f
BB
5754 case ZPOOL_STATUS_IO_FAILURE_WAIT:
5755 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
5756 (void) printf(gettext("status: One or more devices are "
5757 "faulted in response to IO failures.\n"));
5758 (void) printf(gettext("action: Make sure the affected devices "
5759 "are connected, then run 'zpool clear'.\n"));
5760 break;
5761
5762 case ZPOOL_STATUS_BAD_LOG:
5763 (void) printf(gettext("status: An intent log record "
5764 "could not be read.\n"
5765 "\tWaiting for adminstrator intervention to fix the "
5766 "faulted pool.\n"));
5767 (void) printf(gettext("action: Either restore the affected "
5768 "device(s) and run 'zpool online',\n"
5769 "\tor ignore the intent log records by running "
5770 "'zpool clear'.\n"));
5771 break;
5772
1cbae971
RY
5773 case ZPOOL_STATUS_HOSTID_MISMATCH:
5774 (void) printf(gettext("status: Mismatch between pool hostid "
5775 "and system hostid on imported pool.\n\tThis pool was "
5776 "previously imported into a system with a different "
5777 "hostid,\n\tand then was verbatim imported into this "
5778 "system.\n"));
5779 (void) printf(gettext("action: Export this pool on all systems "
5780 "on which it is imported.\n"
5781 "\tThen import it to correct the mismatch.\n"));
5782 break;
5783
ffe9d382
BB
5784 case ZPOOL_STATUS_ERRATA:
5785 (void) printf(gettext("status: Errata #%d detected.\n"),
5786 errata);
5787
5788 switch (errata) {
5789 case ZPOOL_ERRATA_NONE:
5790 break;
5791
4f2dcb3e
RY
5792 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
5793 (void) printf(gettext("action: To correct the issue "
5794 "run 'zpool scrub'.\n"));
5795 break;
5796
ffe9d382
BB
5797 default:
5798 /*
5799 * All errata which allow the pool to be imported
5800 * must contain an action message.
5801 */
5802 assert(0);
5803 }
5804 break;
5805
34dc7c2f
BB
5806 default:
5807 /*
5808 * The remaining errors can't actually be generated, yet.
5809 */
5810 assert(reason == ZPOOL_STATUS_OK);
5811 }
5812
5813 if (msgid != NULL)
3cee2262 5814 (void) printf(gettext(" see: http://zfsonlinux.org/msg/%s\n"),
34dc7c2f
BB
5815 msgid);
5816
5817 if (config != NULL) {
5818 int namewidth;
5819 uint64_t nerr;
5820 nvlist_t **spares, **l2cache;
5821 uint_t nspares, nl2cache;
428870ff 5822 pool_scan_stat_t *ps = NULL;
34dc7c2f 5823
428870ff
BB
5824 (void) nvlist_lookup_uint64_array(nvroot,
5825 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
5826 print_scan_status(ps);
34dc7c2f 5827
d2f3e292 5828 namewidth = max_width(zhp, nvroot, 0, 0, cbp->cb_name_flags);
34dc7c2f
BB
5829 if (namewidth < 10)
5830 namewidth = 10;
5831
5832 (void) printf(gettext("config:\n\n"));
5833 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
5834 "NAME", "STATE", "READ", "WRITE", "CKSUM");
5835 print_status_config(zhp, zpool_get_name(zhp), nvroot,
d2f3e292 5836 namewidth, 0, B_FALSE, cbp->cb_name_flags);
34dc7c2f 5837
9babb374 5838 if (num_logs(nvroot) > 0)
d2f3e292
RY
5839 print_logs(zhp, nvroot, namewidth, B_TRUE,
5840 cbp->cb_name_flags);
34dc7c2f
BB
5841 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5842 &l2cache, &nl2cache) == 0)
d2f3e292
RY
5843 print_l2cache(zhp, l2cache, nl2cache, namewidth,
5844 cbp->cb_name_flags);
34dc7c2f
BB
5845
5846 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5847 &spares, &nspares) == 0)
d2f3e292
RY
5848 print_spares(zhp, spares, nspares, namewidth,
5849 cbp->cb_name_flags);
34dc7c2f
BB
5850
5851 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5852 &nerr) == 0) {
5853 nvlist_t *nverrlist = NULL;
5854
5855 /*
5856 * If the approximate error count is small, get a
5857 * precise count by fetching the entire log and
5858 * uniquifying the results.
5859 */
5860 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
5861 zpool_get_errlog(zhp, &nverrlist) == 0) {
5862 nvpair_t *elem;
5863
5864 elem = NULL;
5865 nerr = 0;
5866 while ((elem = nvlist_next_nvpair(nverrlist,
5867 elem)) != NULL) {
5868 nerr++;
5869 }
5870 }
5871 nvlist_free(nverrlist);
5872
5873 (void) printf("\n");
5874
5875 if (nerr == 0)
5876 (void) printf(gettext("errors: No known data "
5877 "errors\n"));
5878 else if (!cbp->cb_verbose)
5879 (void) printf(gettext("errors: %llu data "
5880 "errors, use '-v' for a list\n"),
5881 (u_longlong_t)nerr);
5882 else
5883 print_error_log(zhp);
5884 }
428870ff
BB
5885
5886 if (cbp->cb_dedup_stats)
5887 print_dedup_stats(config);
34dc7c2f
BB
5888 } else {
5889 (void) printf(gettext("config: The configuration cannot be "
5890 "determined.\n"));
5891 }
5892
5893 return (0);
5894}
5895
5896/*
a77f29f9 5897 * zpool status [-gLPvx] [-T d|u] [pool] ... [interval [count]]
34dc7c2f 5898 *
d2f3e292
RY
5899 * -g Display guid for individual vdev name.
5900 * -L Follow links when resolving vdev path name.
a77f29f9 5901 * -P Display full path for vdev name.
34dc7c2f
BB
5902 * -v Display complete error logs
5903 * -x Display only pools with potential problems
428870ff
BB
5904 * -D Display dedup status (undocumented)
5905 * -T Display a timestamp in date(1) or Unix format
34dc7c2f
BB
5906 *
5907 * Describes the health status of all pools or some subset.
5908 */
5909int
5910zpool_do_status(int argc, char **argv)
5911{
5912 int c;
5913 int ret;
193a37cb
TH
5914 float interval = 0;
5915 unsigned long count = 0;
34dc7c2f
BB
5916 status_cbdata_t cb = { 0 };
5917
5918 /* check options */
a77f29f9 5919 while ((c = getopt(argc, argv, "gLPvxDT:")) != -1) {
34dc7c2f 5920 switch (c) {
d2f3e292
RY
5921 case 'g':
5922 cb.cb_name_flags |= VDEV_NAME_GUID;
5923 break;
5924 case 'L':
5925 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
5926 break;
a77f29f9 5927 case 'P':
d2f3e292
RY
5928 cb.cb_name_flags |= VDEV_NAME_PATH;
5929 break;
34dc7c2f
BB
5930 case 'v':
5931 cb.cb_verbose = B_TRUE;
5932 break;
5933 case 'x':
5934 cb.cb_explain = B_TRUE;
5935 break;
428870ff
BB
5936 case 'D':
5937 cb.cb_dedup_stats = B_TRUE;
5938 break;
5939 case 'T':
5940 get_timestamp_arg(*optarg);
5941 break;
34dc7c2f
BB
5942 case '?':
5943 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5944 optopt);
5945 usage(B_FALSE);
5946 }
5947 }
5948
5949 argc -= optind;
5950 argv += optind;
5951
428870ff 5952 get_interval_count(&argc, argv, &interval, &count);
34dc7c2f
BB
5953
5954 if (argc == 0)
5955 cb.cb_allpools = B_TRUE;
5956
428870ff 5957 cb.cb_first = B_TRUE;
34dc7c2f 5958
428870ff
BB
5959 for (;;) {
5960 if (timestamp_fmt != NODATE)
5961 print_timestamp(timestamp_fmt);
34dc7c2f 5962
428870ff
BB
5963 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5964 status_callback, &cb);
5965
5966 if (argc == 0 && cb.cb_count == 0)
42cb3819 5967 (void) fprintf(stderr, gettext("no pools available\n"));
428870ff
BB
5968 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5969 (void) printf(gettext("all pools are healthy\n"));
5970
5971 if (ret != 0)
5972 return (ret);
5973
5974 if (interval == 0)
5975 break;
5976
5977 if (count != 0 && --count == 0)
5978 break;
5979
193a37cb 5980 (void) fsleep(interval);
428870ff
BB
5981 }
5982
5983 return (0);
34dc7c2f
BB
5984}
5985
5986typedef struct upgrade_cbdata {
34dc7c2f 5987 int cb_first;
34dc7c2f
BB
5988 int cb_argc;
5989 uint64_t cb_version;
5990 char **cb_argv;
5991} upgrade_cbdata_t;
5992
287be44f
DS
5993static int
5994check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs)
5995{
5996 int zfs_version = (int) zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
5997 int *count = (int *)unsupp_fs;
5998
5999 if (zfs_version > ZPL_VERSION) {
6000 (void) printf(gettext("%s (v%d) is not supported by this "
6001 "implementation of ZFS.\n"),
6002 zfs_get_name(zhp), zfs_version);
6003 (*count)++;
6004 }
6005
6006 zfs_iter_filesystems(zhp, check_unsupp_fs, unsupp_fs);
6007
6008 zfs_close(zhp);
6009
6010 return (0);
6011}
6012
b9b24bb4
CS
6013static int
6014upgrade_version(zpool_handle_t *zhp, uint64_t version)
6015{
6016 int ret;
6017 nvlist_t *config;
6018 uint64_t oldversion;
287be44f 6019 int unsupp_fs = 0;
b9b24bb4
CS
6020
6021 config = zpool_get_config(zhp, NULL);
6022 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6023 &oldversion) == 0);
6024
6025 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
6026 assert(oldversion < version);
6027
287be44f
DS
6028 ret = zfs_iter_root(zpool_get_handle(zhp), check_unsupp_fs, &unsupp_fs);
6029 if (ret != 0)
6030 return (ret);
6031
6032 if (unsupp_fs) {
5c7afad4
BB
6033 (void) fprintf(stderr, gettext("Upgrade not performed due "
6034 "to %d unsupported filesystems (max v%d).\n"),
287be44f
DS
6035 unsupp_fs, (int) ZPL_VERSION);
6036 return (1);
6037 }
6038
b9b24bb4
CS
6039 ret = zpool_upgrade(zhp, version);
6040 if (ret != 0)
6041 return (ret);
6042
6043 if (version >= SPA_VERSION_FEATURES) {
6044 (void) printf(gettext("Successfully upgraded "
6045 "'%s' from version %llu to feature flags.\n"),
6046 zpool_get_name(zhp), (u_longlong_t) oldversion);
6047 } else {
6048 (void) printf(gettext("Successfully upgraded "
6049 "'%s' from version %llu to version %llu.\n"),
6050 zpool_get_name(zhp), (u_longlong_t) oldversion,
6051 (u_longlong_t) version);
6052 }
6053
6054 return (0);
6055}
6056
6057static int
6058upgrade_enable_all(zpool_handle_t *zhp, int *countp)
6059{
6060 int i, ret, count;
6061 boolean_t firstff = B_TRUE;
6062 nvlist_t *enabled = zpool_get_features(zhp);
6063
6064 count = 0;
6065 for (i = 0; i < SPA_FEATURES; i++) {
6066 const char *fname = spa_feature_table[i].fi_uname;
6067 const char *fguid = spa_feature_table[i].fi_guid;
6068 if (!nvlist_exists(enabled, fguid)) {
6069 char *propname;
6070 verify(-1 != asprintf(&propname, "feature@%s", fname));
6071 ret = zpool_set_prop(zhp, propname,
6072 ZFS_FEATURE_ENABLED);
6073 if (ret != 0) {
6074 free(propname);
6075 return (ret);
6076 }
6077 count++;
6078
6079 if (firstff) {
6080 (void) printf(gettext("Enabled the "
6081 "following features on '%s':\n"),
6082 zpool_get_name(zhp));
6083 firstff = B_FALSE;
6084 }
6085 (void) printf(gettext(" %s\n"), fname);
6086 free(propname);
6087 }
6088 }
6089
6090 if (countp != NULL)
6091 *countp = count;
6092 return (0);
6093}
6094
34dc7c2f
BB
6095static int
6096upgrade_cb(zpool_handle_t *zhp, void *arg)
6097{
6098 upgrade_cbdata_t *cbp = arg;
6099 nvlist_t *config;
6100 uint64_t version;
b9b24bb4
CS
6101 boolean_t printnl = B_FALSE;
6102 int ret;
34dc7c2f
BB
6103
6104 config = zpool_get_config(zhp, NULL);
6105 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6106 &version) == 0);
6107
b9b24bb4 6108 assert(SPA_VERSION_IS_SUPPORTED(version));
34dc7c2f 6109
b9b24bb4
CS
6110 if (version < cbp->cb_version) {
6111 cbp->cb_first = B_FALSE;
6112 ret = upgrade_version(zhp, cbp->cb_version);
6113 if (ret != 0)
6114 return (ret);
6115 printnl = B_TRUE;
6116
b9b24bb4
CS
6117 /*
6118 * If they did "zpool upgrade -a", then we could
6119 * be doing ioctls to different pools. We need
6120 * to log this history once to each pool, and bypass
6121 * the normal history logging that happens in main().
6122 */
6123 (void) zpool_log_history(g_zfs, history_str);
6124 log_history = B_FALSE;
b9b24bb4
CS
6125 }
6126
6127 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
6128 int count;
6129 ret = upgrade_enable_all(zhp, &count);
6130 if (ret != 0)
6131 return (ret);
6132
6133 if (count > 0) {
34dc7c2f 6134 cbp->cb_first = B_FALSE;
b9b24bb4 6135 printnl = B_TRUE;
34dc7c2f 6136 }
b9b24bb4 6137 }
34dc7c2f 6138
b9b24bb4
CS
6139 if (printnl) {
6140 (void) printf(gettext("\n"));
6141 }
6142
6143 return (0);
6144}
6145
6146static int
6147upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
6148{
6149 upgrade_cbdata_t *cbp = arg;
6150 nvlist_t *config;
6151 uint64_t version;
6152
6153 config = zpool_get_config(zhp, NULL);
6154 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6155 &version) == 0);
6156
6157 assert(SPA_VERSION_IS_SUPPORTED(version));
6158
6159 if (version < SPA_VERSION_FEATURES) {
34dc7c2f
BB
6160 if (cbp->cb_first) {
6161 (void) printf(gettext("The following pools are "
b9b24bb4
CS
6162 "formatted with legacy version numbers and can\n"
6163 "be upgraded to use feature flags. After "
6164 "being upgraded, these pools\nwill no "
6165 "longer be accessible by software that does not "
6166 "support feature\nflags.\n\n"));
34dc7c2f
BB
6167 (void) printf(gettext("VER POOL\n"));
6168 (void) printf(gettext("--- ------------\n"));
6169 cbp->cb_first = B_FALSE;
6170 }
6171
6172 (void) printf("%2llu %s\n", (u_longlong_t)version,
6173 zpool_get_name(zhp));
6174 }
6175
b9b24bb4
CS
6176 return (0);
6177}
6178
6179static int
6180upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
6181{
6182 upgrade_cbdata_t *cbp = arg;
6183 nvlist_t *config;
6184 uint64_t version;
6185
6186 config = zpool_get_config(zhp, NULL);
6187 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6188 &version) == 0);
6189
6190 if (version >= SPA_VERSION_FEATURES) {
6191 int i;
6192 boolean_t poolfirst = B_TRUE;
6193 nvlist_t *enabled = zpool_get_features(zhp);
6194
6195 for (i = 0; i < SPA_FEATURES; i++) {
6196 const char *fguid = spa_feature_table[i].fi_guid;
6197 const char *fname = spa_feature_table[i].fi_uname;
6198 if (!nvlist_exists(enabled, fguid)) {
6199 if (cbp->cb_first) {
6200 (void) printf(gettext("\nSome "
6201 "supported features are not "
6202 "enabled on the following pools. "
6203 "Once a\nfeature is enabled the "
6204 "pool may become incompatible with "
6205 "software\nthat does not support "
6206 "the feature. See "
6207 "zpool-features(5) for "
6208 "details.\n\n"));
6209 (void) printf(gettext("POOL "
6210 "FEATURE\n"));
6211 (void) printf(gettext("------"
6212 "---------\n"));
6213 cbp->cb_first = B_FALSE;
6214 }
6215
6216 if (poolfirst) {
6217 (void) printf(gettext("%s\n"),
6218 zpool_get_name(zhp));
6219 poolfirst = B_FALSE;
6220 }
6221
6222 (void) printf(gettext(" %s\n"), fname);
6223 }
6f1ffb06
MA
6224 /*
6225 * If they did "zpool upgrade -a", then we could
6226 * be doing ioctls to different pools. We need
6227 * to log this history once to each pool, and bypass
6228 * the normal history logging that happens in main().
6229 */
6230 (void) zpool_log_history(g_zfs, history_str);
6231 log_history = B_FALSE;
b9b24bb4
CS
6232 }
6233 }
6234
6235 return (0);
34dc7c2f
BB
6236}
6237
6238/* ARGSUSED */
6239static int
6240upgrade_one(zpool_handle_t *zhp, void *data)
6241{
b9b24bb4 6242 boolean_t printnl = B_FALSE;
34dc7c2f
BB
6243 upgrade_cbdata_t *cbp = data;
6244 uint64_t cur_version;
6245 int ret;
6246
6247 if (strcmp("log", zpool_get_name(zhp)) == 0) {
c66989ba 6248 (void) fprintf(stderr, gettext("'log' is now a reserved word\n"
34dc7c2f
BB
6249 "Pool 'log' must be renamed using export and import"
6250 " to upgrade.\n"));
6251 return (1);
6252 }
6253
6254 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
6255 if (cur_version > cbp->cb_version) {
6256 (void) printf(gettext("Pool '%s' is already formatted "
b9b24bb4 6257 "using more current version '%llu'.\n\n"),
b8864a23 6258 zpool_get_name(zhp), (u_longlong_t) cur_version);
34dc7c2f
BB
6259 return (0);
6260 }
b9b24bb4
CS
6261
6262 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
34dc7c2f 6263 (void) printf(gettext("Pool '%s' is already formatted "
b9b24bb4
CS
6264 "using version %llu.\n\n"), zpool_get_name(zhp),
6265 (u_longlong_t) cbp->cb_version);
34dc7c2f
BB
6266 return (0);
6267 }
6268
b9b24bb4
CS
6269 if (cur_version != cbp->cb_version) {
6270 printnl = B_TRUE;
6271 ret = upgrade_version(zhp, cbp->cb_version);
6272 if (ret != 0)
6273 return (ret);
6274 }
34dc7c2f 6275
b9b24bb4
CS
6276 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
6277 int count = 0;
6278 ret = upgrade_enable_all(zhp, &count);
6279 if (ret != 0)
6280 return (ret);
6281
6282 if (count != 0) {
6283 printnl = B_TRUE;
6284 } else if (cur_version == SPA_VERSION) {
6285 (void) printf(gettext("Pool '%s' already has all "
6286 "supported features enabled.\n"),
6287 zpool_get_name(zhp));
6288 }
6289 }
6290
6291 if (printnl) {
6292 (void) printf(gettext("\n"));
34dc7c2f
BB
6293 }
6294
b9b24bb4 6295 return (0);
34dc7c2f
BB
6296}
6297
6298/*
6299 * zpool upgrade
6300 * zpool upgrade -v
6301 * zpool upgrade [-V version] <-a | pool ...>
6302 *
6303 * With no arguments, display downrev'd ZFS pool available for upgrade.
6304 * Individual pools can be upgraded by specifying the pool, and '-a' will
6305 * upgrade all pools.
6306 */
6307int
6308zpool_do_upgrade(int argc, char **argv)
6309{
6310 int c;
6311 upgrade_cbdata_t cb = { 0 };
6312 int ret = 0;
6313 boolean_t showversions = B_FALSE;
b9b24bb4 6314 boolean_t upgradeall = B_FALSE;
34dc7c2f
BB
6315 char *end;
6316
6317
6318 /* check options */
9babb374 6319 while ((c = getopt(argc, argv, ":avV:")) != -1) {
34dc7c2f
BB
6320 switch (c) {
6321 case 'a':
b9b24bb4 6322 upgradeall = B_TRUE;
34dc7c2f
BB
6323 break;
6324 case 'v':
6325 showversions = B_TRUE;
6326 break;
6327 case 'V':
6328 cb.cb_version = strtoll(optarg, &end, 10);
9ae529ec
CS
6329 if (*end != '\0' ||
6330 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
34dc7c2f
BB
6331 (void) fprintf(stderr,
6332 gettext("invalid version '%s'\n"), optarg);
6333 usage(B_FALSE);
6334 }
6335 break;
9babb374
BB
6336 case ':':
6337 (void) fprintf(stderr, gettext("missing argument for "
6338 "'%c' option\n"), optopt);
6339 usage(B_FALSE);
6340 break;
34dc7c2f
BB
6341 case '?':
6342 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6343 optopt);
6344 usage(B_FALSE);
6345 }
6346 }
6347
6348 cb.cb_argc = argc;
6349 cb.cb_argv = argv;
6350 argc -= optind;
6351 argv += optind;
6352
6353 if (cb.cb_version == 0) {
6354 cb.cb_version = SPA_VERSION;
b9b24bb4 6355 } else if (!upgradeall && argc == 0) {
34dc7c2f
BB
6356 (void) fprintf(stderr, gettext("-V option is "
6357 "incompatible with other arguments\n"));
6358 usage(B_FALSE);
6359 }
6360
6361 if (showversions) {
b9b24bb4 6362 if (upgradeall || argc != 0) {
34dc7c2f
BB
6363 (void) fprintf(stderr, gettext("-v option is "
6364 "incompatible with other arguments\n"));
6365 usage(B_FALSE);
6366 }
b9b24bb4 6367 } else if (upgradeall) {
34dc7c2f
BB
6368 if (argc != 0) {
6369 (void) fprintf(stderr, gettext("-a option should not "
6370 "be used along with a pool name\n"));
6371 usage(B_FALSE);
6372 }
6373 }
6374
9ae529ec
CS
6375 (void) printf(gettext("This system supports ZFS pool feature "
6376 "flags.\n\n"));
34dc7c2f 6377 if (showversions) {
b9b24bb4
CS
6378 int i;
6379
6380 (void) printf(gettext("The following features are "
6381 "supported:\n\n"));
6382 (void) printf(gettext("FEAT DESCRIPTION\n"));
6383 (void) printf("----------------------------------------------"
6384 "---------------\n");
6385 for (i = 0; i < SPA_FEATURES; i++) {
6386 zfeature_info_t *fi = &spa_feature_table[i];
241b5415
MA
6387 const char *ro =
6388 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
b9b24bb4
CS
6389 " (read-only compatible)" : "";
6390
6391 (void) printf("%-37s%s\n", fi->fi_uname, ro);
6392 (void) printf(" %s\n", fi->fi_desc);
6393 }
6394 (void) printf("\n");
6395
6396 (void) printf(gettext("The following legacy versions are also "
34dc7c2f
BB
6397 "supported:\n\n"));
6398 (void) printf(gettext("VER DESCRIPTION\n"));
6399 (void) printf("--- -----------------------------------------"
6400 "---------------\n");
6401 (void) printf(gettext(" 1 Initial ZFS version\n"));
6402 (void) printf(gettext(" 2 Ditto blocks "
6403 "(replicated metadata)\n"));
6404 (void) printf(gettext(" 3 Hot spares and double parity "
6405 "RAID-Z\n"));
6406 (void) printf(gettext(" 4 zpool history\n"));
6407 (void) printf(gettext(" 5 Compression using the gzip "
6408 "algorithm\n"));
6409 (void) printf(gettext(" 6 bootfs pool property\n"));
6410 (void) printf(gettext(" 7 Separate intent log devices\n"));
6411 (void) printf(gettext(" 8 Delegated administration\n"));
6412 (void) printf(gettext(" 9 refquota and refreservation "
6413 "properties\n"));
6414 (void) printf(gettext(" 10 Cache devices\n"));
b128c09f
BB
6415 (void) printf(gettext(" 11 Improved scrub performance\n"));
6416 (void) printf(gettext(" 12 Snapshot properties\n"));
6417 (void) printf(gettext(" 13 snapused property\n"));
9babb374
BB
6418 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
6419 (void) printf(gettext(" 15 user/group space accounting\n"));
6420 (void) printf(gettext(" 16 stmf property support\n"));
45d1cae3 6421 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
428870ff
BB
6422 (void) printf(gettext(" 18 Snapshot user holds\n"));
6423 (void) printf(gettext(" 19 Log device removal\n"));
6424 (void) printf(gettext(" 20 Compression using zle "
6425 "(zero-length encoding)\n"));
6426 (void) printf(gettext(" 21 Deduplication\n"));
6427 (void) printf(gettext(" 22 Received properties\n"));
6428 (void) printf(gettext(" 23 Slim ZIL\n"));
6429 (void) printf(gettext(" 24 System attributes\n"));
6430 (void) printf(gettext(" 25 Improved scrub stats\n"));
6431 (void) printf(gettext(" 26 Improved snapshot deletion "
6432 "performance\n"));
572e2857
BB
6433 (void) printf(gettext(" 27 Improved snapshot creation "
6434 "performance\n"));
6435 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
428870ff
BB
6436 (void) printf(gettext("\nFor more information on a particular "
6437 "version, including supported releases,\n"));
6438 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
b9b24bb4
CS
6439 } else if (argc == 0 && upgradeall) {
6440 cb.cb_first = B_TRUE;
34dc7c2f 6441 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
b9b24bb4
CS
6442 if (ret == 0 && cb.cb_first) {
6443 if (cb.cb_version == SPA_VERSION) {
6444 (void) printf(gettext("All pools are already "
6445 "formatted using feature flags.\n\n"));
6446 (void) printf(gettext("Every feature flags "
6447 "pool already has all supported features "
6448 "enabled.\n"));
6449 } else {
6450 (void) printf(gettext("All pools are already "
6451 "formatted with version %llu or higher.\n"),
6452 (u_longlong_t) cb.cb_version);
34dc7c2f
BB
6453 }
6454 }
b9b24bb4
CS
6455 } else if (argc == 0) {
6456 cb.cb_first = B_TRUE;
6457 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
6458 assert(ret == 0);
34dc7c2f 6459
b9b24bb4
CS
6460 if (cb.cb_first) {
6461 (void) printf(gettext("All pools are formatted "
6462 "using feature flags.\n\n"));
6463 } else {
6464 (void) printf(gettext("\nUse 'zpool upgrade -v' "
6465 "for a list of available legacy versions.\n"));
6466 }
6467
6468 cb.cb_first = B_TRUE;
6469 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
6470 assert(ret == 0);
6471
6472 if (cb.cb_first) {
6473 (void) printf(gettext("Every feature flags pool has "
6474 "all supported features enabled.\n"));
6475 } else {
6476 (void) printf(gettext("\n"));
34dc7c2f
BB
6477 }
6478 } else {
6479 ret = for_each_pool(argc, argv, B_FALSE, NULL,
6480 upgrade_one, &cb);
6481 }
6482
6483 return (ret);
6484}
6485
6486typedef struct hist_cbdata {
6487 boolean_t first;
6f1ffb06
MA
6488 boolean_t longfmt;
6489 boolean_t internal;
34dc7c2f
BB
6490} hist_cbdata_t;
6491
34dc7c2f
BB
6492/*
6493 * Print out the command history for a specific pool.
6494 */
6495static int
6496get_history_one(zpool_handle_t *zhp, void *data)
6497{
6498 nvlist_t *nvhis;
6499 nvlist_t **records;
6500 uint_t numrecords;
34dc7c2f 6501 int ret, i;
34dc7c2f 6502 hist_cbdata_t *cb = (hist_cbdata_t *)data;
34dc7c2f
BB
6503
6504 cb->first = B_FALSE;
6505
6506 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
6507
6508 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
6509 return (ret);
6510
6511 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
6512 &records, &numrecords) == 0);
6513 for (i = 0; i < numrecords; i++) {
6f1ffb06
MA
6514 nvlist_t *rec = records[i];
6515 char tbuf[30] = "";
34dc7c2f 6516
6f1ffb06
MA
6517 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
6518 time_t tsec;
6519 struct tm t;
34dc7c2f 6520
6f1ffb06
MA
6521 tsec = fnvlist_lookup_uint64(records[i],
6522 ZPOOL_HIST_TIME);
6523 (void) localtime_r(&tsec, &t);
6524 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
6525 }
6526
6527 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
6528 (void) printf("%s %s", tbuf,
6529 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
6530 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
6531 int ievent =
6532 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
6533 if (!cb->internal)
34dc7c2f 6534 continue;
6f1ffb06
MA
6535 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
6536 (void) printf("%s unrecognized record:\n",
6537 tbuf);
6538 dump_nvlist(rec, 4);
34dc7c2f 6539 continue;
6f1ffb06
MA
6540 }
6541 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
6542 zfs_history_event_names[ievent],
d1d7e268
MK
6543 (longlong_t) fnvlist_lookup_uint64(
6544 rec, ZPOOL_HIST_TXG),
6f1ffb06
MA
6545 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
6546 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
6547 if (!cb->internal)
6548 continue;
6549 (void) printf("%s [txg:%lld] %s", tbuf,
d1d7e268
MK
6550 (longlong_t) fnvlist_lookup_uint64(
6551 rec, ZPOOL_HIST_TXG),
6f1ffb06
MA
6552 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
6553 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
6554 (void) printf(" %s (%llu)",
6555 fnvlist_lookup_string(rec,
6556 ZPOOL_HIST_DSNAME),
d1d7e268 6557 (u_longlong_t)fnvlist_lookup_uint64(rec,
6f1ffb06
MA
6558 ZPOOL_HIST_DSID));
6559 }
6560 (void) printf(" %s", fnvlist_lookup_string(rec,
6561 ZPOOL_HIST_INT_STR));
6562 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
6563 if (!cb->internal)
6564 continue;
6565 (void) printf("%s ioctl %s\n", tbuf,
6566 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
6567 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
6568 (void) printf(" input:\n");
6569 dump_nvlist(fnvlist_lookup_nvlist(rec,
6570 ZPOOL_HIST_INPUT_NVL), 8);
6571 }
6572 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
6573 (void) printf(" output:\n");
6574 dump_nvlist(fnvlist_lookup_nvlist(rec,
6575 ZPOOL_HIST_OUTPUT_NVL), 8);
6576 }
6577 } else {
6578 if (!cb->internal)
6579 continue;
6580 (void) printf("%s unrecognized record:\n", tbuf);
6581 dump_nvlist(rec, 4);
34dc7c2f 6582 }
34dc7c2f
BB
6583
6584 if (!cb->longfmt) {
6585 (void) printf("\n");
6586 continue;
6587 }
6588 (void) printf(" [");
6f1ffb06
MA
6589 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
6590 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
6591 struct passwd *pwd = getpwuid(who);
6592 (void) printf("user %d ", (int)who);
6593 if (pwd != NULL)
6594 (void) printf("(%s) ", pwd->pw_name);
34dc7c2f 6595 }
6f1ffb06
MA
6596 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
6597 (void) printf("on %s",
6598 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
34dc7c2f 6599 }
6f1ffb06
MA
6600 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
6601 (void) printf(":%s",
6602 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
34dc7c2f
BB
6603 }
6604
6605 (void) printf("]");
6606 (void) printf("\n");
6607 }
6608 (void) printf("\n");
6609 nvlist_free(nvhis);
6610
6611 return (ret);
6612}
6613
6614/*
6615 * zpool history <pool>
6616 *
6617 * Displays the history of commands that modified pools.
6618 */
34dc7c2f
BB
6619int
6620zpool_do_history(int argc, char **argv)
6621{
6622 hist_cbdata_t cbdata = { 0 };
6623 int ret;
6624 int c;
6625
6626 cbdata.first = B_TRUE;
6627 /* check options */
6628 while ((c = getopt(argc, argv, "li")) != -1) {
6629 switch (c) {
6630 case 'l':
6f1ffb06 6631 cbdata.longfmt = B_TRUE;
34dc7c2f
BB
6632 break;
6633 case 'i':
6f1ffb06 6634 cbdata.internal = B_TRUE;
34dc7c2f
BB
6635 break;
6636 case '?':
6637 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6638 optopt);
6639 usage(B_FALSE);
6640 }
6641 }
6642 argc -= optind;
6643 argv += optind;
6644
6645 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
6646 &cbdata);
6647
6648 if (argc == 0 && cbdata.first == B_TRUE) {
42cb3819 6649 (void) fprintf(stderr, gettext("no pools available\n"));
34dc7c2f
BB
6650 return (0);
6651 }
6652
6653 return (ret);
6654}
6655
26685276
BB
6656typedef struct ev_opts {
6657 int verbose;
c5343ba7 6658 int scripted;
26685276
BB
6659 int follow;
6660 int clear;
6661} ev_opts_t;
6662
6663static void
6664zpool_do_events_short(nvlist_t *nvl)
6665{
6666 char ctime_str[26], str[32], *ptr;
6667 int64_t *tv;
6668 uint_t n;
6669
6670 verify(nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0);
6671 memset(str, ' ', 32);
6672 (void) ctime_r((const time_t *)&tv[0], ctime_str);
d1d7e268
MK
6673 (void) strncpy(str, ctime_str+4, 6); /* 'Jun 30' */
6674 (void) strncpy(str+7, ctime_str+20, 4); /* '1993' */
6675 (void) strncpy(str+12, ctime_str+11, 8); /* '21:49:08' */
6676 (void) sprintf(str+20, ".%09lld", (longlong_t)tv[1]); /* '.123456789' */
26685276
BB
6677 (void) printf(gettext("%s "), str);
6678
6679 verify(nvlist_lookup_string(nvl, FM_CLASS, &ptr) == 0);
6680 (void) printf(gettext("%s\n"), ptr);
6681}
6682
6683static void
6684zpool_do_events_nvprint(nvlist_t *nvl, int depth)
6685{
6686 nvpair_t *nvp;
6687
6688 for (nvp = nvlist_next_nvpair(nvl, NULL);
6689 nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) {
6690
6691 data_type_t type = nvpair_type(nvp);
6692 const char *name = nvpair_name(nvp);
6693
6694 boolean_t b;
6695 uint8_t i8;
6696 uint16_t i16;
6697 uint32_t i32;
6698 uint64_t i64;
6699 char *str;
6700 nvlist_t *cnv;
6701
6702 printf(gettext("%*s%s = "), depth, "", name);
6703
6704 switch (type) {
6705 case DATA_TYPE_BOOLEAN:
6706 printf(gettext("%s"), "1");
6707 break;
6708
6709 case DATA_TYPE_BOOLEAN_VALUE:
6710 (void) nvpair_value_boolean_value(nvp, &b);
6711 printf(gettext("%s"), b ? "1" : "0");
6712 break;
6713
6714 case DATA_TYPE_BYTE:
6715 (void) nvpair_value_byte(nvp, &i8);
6716 printf(gettext("0x%x"), i8);
6717 break;
6718
6719 case DATA_TYPE_INT8:
6720 (void) nvpair_value_int8(nvp, (void *)&i8);
6721 printf(gettext("0x%x"), i8);
6722 break;
6723
6724 case DATA_TYPE_UINT8:
6725 (void) nvpair_value_uint8(nvp, &i8);
6726 printf(gettext("0x%x"), i8);
6727 break;
6728
6729 case DATA_TYPE_INT16:
6730 (void) nvpair_value_int16(nvp, (void *)&i16);
6731 printf(gettext("0x%x"), i16);
6732 break;
6733
6734 case DATA_TYPE_UINT16:
6735 (void) nvpair_value_uint16(nvp, &i16);
6736 printf(gettext("0x%x"), i16);
6737 break;
6738
6739 case DATA_TYPE_INT32:
6740 (void) nvpair_value_int32(nvp, (void *)&i32);
6741 printf(gettext("0x%x"), i32);
6742 break;
6743
6744 case DATA_TYPE_UINT32:
6745 (void) nvpair_value_uint32(nvp, &i32);
6746 printf(gettext("0x%x"), i32);
6747 break;
6748
6749 case DATA_TYPE_INT64:
6750 (void) nvpair_value_int64(nvp, (void *)&i64);
6751 printf(gettext("0x%llx"), (u_longlong_t)i64);
6752 break;
6753
6754 case DATA_TYPE_UINT64:
6755 (void) nvpair_value_uint64(nvp, &i64);
6756 printf(gettext("0x%llx"), (u_longlong_t)i64);
6757 break;
6758
6759 case DATA_TYPE_HRTIME:
6760 (void) nvpair_value_hrtime(nvp, (void *)&i64);
6761 printf(gettext("0x%llx"), (u_longlong_t)i64);
6762 break;
6763
6764 case DATA_TYPE_STRING:
6765 (void) nvpair_value_string(nvp, &str);
6766 printf(gettext("\"%s\""), str ? str : "<NULL>");
6767 break;
6768
6769 case DATA_TYPE_NVLIST:
6770 printf(gettext("(embedded nvlist)\n"));
6771 (void) nvpair_value_nvlist(nvp, &cnv);
6772 zpool_do_events_nvprint(cnv, depth + 8);
c5343ba7 6773 printf(gettext("%*s(end %s)"), depth, "", name);
26685276
BB
6774 break;
6775
6776 case DATA_TYPE_NVLIST_ARRAY: {
6777 nvlist_t **val;
6778 uint_t i, nelem;
6779
6780 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
6781 printf(gettext("(%d embedded nvlists)\n"), nelem);
6782 for (i = 0; i < nelem; i++) {
6783 printf(gettext("%*s%s[%d] = %s\n"),
d1d7e268 6784 depth, "", name, i, "(embedded nvlist)");
26685276
BB
6785 zpool_do_events_nvprint(val[i], depth + 8);
6786 printf(gettext("%*s(end %s[%i])\n"),
d1d7e268 6787 depth, "", name, i);
26685276
BB
6788 }
6789 printf(gettext("%*s(end %s)\n"), depth, "", name);
6790 }
6791 break;
6792
6793 case DATA_TYPE_INT8_ARRAY: {
6794 int8_t *val;
6795 uint_t i, nelem;
6796
6797 (void) nvpair_value_int8_array(nvp, &val, &nelem);
6798 for (i = 0; i < nelem; i++)
6799 printf(gettext("0x%x "), val[i]);
6800
6801 break;
6802 }
6803
6804 case DATA_TYPE_UINT8_ARRAY: {
6805 uint8_t *val;
6806 uint_t i, nelem;
6807
6808 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
6809 for (i = 0; i < nelem; i++)
6810 printf(gettext("0x%x "), val[i]);
6811
6812 break;
6813 }
6814
6815 case DATA_TYPE_INT16_ARRAY: {
6816 int16_t *val;
6817 uint_t i, nelem;
6818
6819 (void) nvpair_value_int16_array(nvp, &val, &nelem);
6820 for (i = 0; i < nelem; i++)
6821 printf(gettext("0x%x "), val[i]);
6822
6823 break;
6824 }
6825
6826 case DATA_TYPE_UINT16_ARRAY: {
6827 uint16_t *val;
6828 uint_t i, nelem;
6829
6830 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
6831 for (i = 0; i < nelem; i++)
6832 printf(gettext("0x%x "), val[i]);
6833
6834 break;
6835 }
6836
6837 case DATA_TYPE_INT32_ARRAY: {
6838 int32_t *val;
6839 uint_t i, nelem;
6840
6841 (void) nvpair_value_int32_array(nvp, &val, &nelem);
6842 for (i = 0; i < nelem; i++)
6843 printf(gettext("0x%x "), val[i]);
6844
6845 break;
6846 }
6847
6848 case DATA_TYPE_UINT32_ARRAY: {
6849 uint32_t *val;
6850 uint_t i, nelem;
6851
6852 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
6853 for (i = 0; i < nelem; i++)
6854 printf(gettext("0x%x "), val[i]);
6855
6856 break;
6857 }
6858
6859 case DATA_TYPE_INT64_ARRAY: {
6860 int64_t *val;
6861 uint_t i, nelem;
6862
6863 (void) nvpair_value_int64_array(nvp, &val, &nelem);
6864 for (i = 0; i < nelem; i++)
d1d7e268
MK
6865 printf(gettext("0x%llx "),
6866 (u_longlong_t)val[i]);
26685276
BB
6867
6868 break;
6869 }
6870
6871 case DATA_TYPE_UINT64_ARRAY: {
6872 uint64_t *val;
6873 uint_t i, nelem;
6874
6875 (void) nvpair_value_uint64_array(nvp, &val, &nelem);
6876 for (i = 0; i < nelem; i++)
d1d7e268
MK
6877 printf(gettext("0x%llx "),
6878 (u_longlong_t)val[i]);
26685276
BB
6879
6880 break;
6881 }
6882
d21705ea
BB
6883 case DATA_TYPE_STRING_ARRAY: {
6884 char **str;
6885 uint_t i, nelem;
6886
6887 (void) nvpair_value_string_array(nvp, &str, &nelem);
6888 for (i = 0; i < nelem; i++)
6889 printf(gettext("\"%s\" "),
6890 str[i] ? str[i] : "<NULL>");
6891
6892 break;
6893 }
6894
26685276
BB
6895 case DATA_TYPE_BOOLEAN_ARRAY:
6896 case DATA_TYPE_BYTE_ARRAY:
6897 case DATA_TYPE_DOUBLE:
6898 case DATA_TYPE_UNKNOWN:
6899 printf(gettext("<unknown>"));
6900 break;
6901 }
6902
6903 printf(gettext("\n"));
6904 }
6905}
6906
6907static int
6908zpool_do_events_next(ev_opts_t *opts)
6909{
6910 nvlist_t *nvl;
9b101a73 6911 int zevent_fd, ret, dropped;
26685276 6912
9b101a73
BB
6913 zevent_fd = open(ZFS_DEV, O_RDWR);
6914 VERIFY(zevent_fd >= 0);
26685276 6915
c5343ba7
BB
6916 if (!opts->scripted)
6917 (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS");
26685276
BB
6918
6919 while (1) {
6920 ret = zpool_events_next(g_zfs, &nvl, &dropped,
8c7aa0cf 6921 (opts->follow ? ZEVENT_NONE : ZEVENT_NONBLOCK), zevent_fd);
26685276
BB
6922 if (ret || nvl == NULL)
6923 break;
6924
6925 if (dropped > 0)
6926 (void) printf(gettext("dropped %d events\n"), dropped);
6927
6928 zpool_do_events_short(nvl);
6929
6930 if (opts->verbose) {
6931 zpool_do_events_nvprint(nvl, 8);
6932 printf(gettext("\n"));
6933 }
50fe577d 6934 (void) fflush(stdout);
26685276
BB
6935
6936 nvlist_free(nvl);
6937 }
6938
9b101a73 6939 VERIFY(0 == close(zevent_fd));
26685276
BB
6940
6941 return (ret);
6942}
6943
6944static int
6945zpool_do_events_clear(ev_opts_t *opts)
6946{
6947 int count, ret;
6948
6949 ret = zpool_events_clear(g_zfs, &count);
6950 if (!ret)
6951 (void) printf(gettext("cleared %d events\n"), count);
6952
6953 return (ret);
6954}
6955
6956/*
6957 * zpool events [-vfc]
6958 *
6959 * Displays events logs by ZFS.
6960 */
6961int
6962zpool_do_events(int argc, char **argv)
6963{
6964 ev_opts_t opts = { 0 };
6965 int ret;
6966 int c;
6967
6968 /* check options */
c5343ba7 6969 while ((c = getopt(argc, argv, "vHfc")) != -1) {
26685276
BB
6970 switch (c) {
6971 case 'v':
6972 opts.verbose = 1;
c5343ba7
BB
6973 break;
6974 case 'H':
6975 opts.scripted = 1;
26685276
BB
6976 break;
6977 case 'f':
6978 opts.follow = 1;
6979 break;
6980 case 'c':
6981 opts.clear = 1;
6982 break;
6983 case '?':
6984 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6985 optopt);
6986 usage(B_FALSE);
6987 }
6988 }
6989 argc -= optind;
6990 argv += optind;
6991
6992 if (opts.clear)
6993 ret = zpool_do_events_clear(&opts);
6994 else
6995 ret = zpool_do_events_next(&opts);
6996
d1d7e268 6997 return (ret);
26685276
BB
6998}
6999
34dc7c2f
BB
7000static int
7001get_callback(zpool_handle_t *zhp, void *data)
7002{
7003 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
7004 char value[MAXNAMELEN];
7005 zprop_source_t srctype;
7006 zprop_list_t *pl;
7007
7008 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
7009
7010 /*
7011 * Skip the special fake placeholder. This will also skip
7012 * over the name property when 'all' is specified.
7013 */
7014 if (pl->pl_prop == ZPOOL_PROP_NAME &&
7015 pl == cbp->cb_proplist)
7016 continue;
7017
9ae529ec
CS
7018 if (pl->pl_prop == ZPROP_INVAL &&
7019 (zpool_prop_feature(pl->pl_user_prop) ||
7020 zpool_prop_unsupported(pl->pl_user_prop))) {
7021 srctype = ZPROP_SRC_LOCAL;
34dc7c2f 7022
9ae529ec
CS
7023 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
7024 value, sizeof (value)) == 0) {
7025 zprop_print_one_property(zpool_get_name(zhp),
7026 cbp, pl->pl_user_prop, value, srctype,
7027 NULL, NULL);
7028 }
7029 } else {
2a8b84b7 7030 if (zpool_get_prop(zhp, pl->pl_prop, value,
d65e7381 7031 sizeof (value), &srctype, cbp->cb_literal) != 0)
9ae529ec
CS
7032 continue;
7033
7034 zprop_print_one_property(zpool_get_name(zhp), cbp,
7035 zpool_prop_to_name(pl->pl_prop), value, srctype,
7036 NULL, NULL);
7037 }
34dc7c2f
BB
7038 }
7039 return (0);
7040}
7041
2a8b84b7
AS
7042/*
7043 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
7044 *
7045 * -H Scripted mode. Don't display headers, and separate properties
7046 * by a single tab.
7047 * -o List of columns to display. Defaults to
7048 * "name,property,value,source".
7049 * -p Diplay values in parsable (exact) format.
7050 *
7051 * Get properties of pools in the system. Output space statistics
7052 * for each one as well as other attributes.
7053 */
34dc7c2f
BB
7054int
7055zpool_do_get(int argc, char **argv)
7056{
7057 zprop_get_cbdata_t cb = { 0 };
7058 zprop_list_t fake_name = { 0 };
2a8b84b7
AS
7059 int ret;
7060 int c, i;
7061 char *value;
7062
7063 cb.cb_first = B_TRUE;
7064
7065 /*
7066 * Set up default columns and sources.
7067 */
7068 cb.cb_sources = ZPROP_SRC_ALL;
7069 cb.cb_columns[0] = GET_COL_NAME;
7070 cb.cb_columns[1] = GET_COL_PROPERTY;
7071 cb.cb_columns[2] = GET_COL_VALUE;
7072 cb.cb_columns[3] = GET_COL_SOURCE;
7073 cb.cb_type = ZFS_TYPE_POOL;
34dc7c2f 7074
d65e7381 7075 /* check options */
2a8b84b7 7076 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
d65e7381
RE
7077 switch (c) {
7078 case 'p':
7079 cb.cb_literal = B_TRUE;
7080 break;
79eb71dc
TF
7081 case 'H':
7082 cb.cb_scripted = B_TRUE;
7083 break;
2a8b84b7
AS
7084 case 'o':
7085 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
7086 i = 0;
7087 while (*optarg != '\0') {
7088 static char *col_subopts[] =
7089 { "name", "property", "value", "source",
7090 "all", NULL };
7091
7092 if (i == ZFS_GET_NCOLS) {
7093 (void) fprintf(stderr, gettext("too "
7094 "many fields given to -o "
7095 "option\n"));
7096 usage(B_FALSE);
7097 }
79eb71dc 7098
2a8b84b7
AS
7099 switch (getsubopt(&optarg, col_subopts,
7100 &value)) {
7101 case 0:
7102 cb.cb_columns[i++] = GET_COL_NAME;
7103 break;
7104 case 1:
7105 cb.cb_columns[i++] = GET_COL_PROPERTY;
7106 break;
7107 case 2:
7108 cb.cb_columns[i++] = GET_COL_VALUE;
7109 break;
7110 case 3:
7111 cb.cb_columns[i++] = GET_COL_SOURCE;
7112 break;
7113 case 4:
7114 if (i > 0) {
7115 (void) fprintf(stderr,
7116 gettext("\"all\" conflicts "
7117 "with specific fields "
7118 "given to -o option\n"));
7119 usage(B_FALSE);
7120 }
7121 cb.cb_columns[0] = GET_COL_NAME;
7122 cb.cb_columns[1] = GET_COL_PROPERTY;
7123 cb.cb_columns[2] = GET_COL_VALUE;
7124 cb.cb_columns[3] = GET_COL_SOURCE;
7125 i = ZFS_GET_NCOLS;
7126 break;
7127 default:
7128 (void) fprintf(stderr,
7129 gettext("invalid column name "
7130 "'%s'\n"), value);
7131 usage(B_FALSE);
7132 }
7133 }
7134 break;
d65e7381
RE
7135 case '?':
7136 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7137 optopt);
7138 usage(B_FALSE);
7139 }
7140 }
7141
7142 argc -= optind;
7143 argv += optind;
7144
7145 if (argc < 1) {
9ae529ec
CS
7146 (void) fprintf(stderr, gettext("missing property "
7147 "argument\n"));
34dc7c2f 7148 usage(B_FALSE);
9ae529ec 7149 }
34dc7c2f 7150
2a8b84b7
AS
7151 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
7152 ZFS_TYPE_POOL) != 0)
34dc7c2f
BB
7153 usage(B_FALSE);
7154
d65e7381
RE
7155 argc--;
7156 argv++;
7157
34dc7c2f
BB
7158 if (cb.cb_proplist != NULL) {
7159 fake_name.pl_prop = ZPOOL_PROP_NAME;
7160 fake_name.pl_width = strlen(gettext("NAME"));
7161 fake_name.pl_next = cb.cb_proplist;
7162 cb.cb_proplist = &fake_name;
7163 }
7164
d65e7381 7165 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
34dc7c2f
BB
7166 get_callback, &cb);
7167
7168 if (cb.cb_proplist == &fake_name)
7169 zprop_free_list(fake_name.pl_next);
7170 else
7171 zprop_free_list(cb.cb_proplist);
7172
7173 return (ret);
7174}
7175
7176typedef struct set_cbdata {
7177 char *cb_propname;
7178 char *cb_value;
7179 boolean_t cb_any_successful;
7180} set_cbdata_t;
7181
7182int
7183set_callback(zpool_handle_t *zhp, void *data)
7184{
7185 int error;
7186 set_cbdata_t *cb = (set_cbdata_t *)data;
7187
7188 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
7189
7190 if (!error)
7191 cb->cb_any_successful = B_TRUE;
7192
7193 return (error);
7194}
7195
7196int
7197zpool_do_set(int argc, char **argv)
7198{
7199 set_cbdata_t cb = { 0 };
7200 int error;
7201
7202 if (argc > 1 && argv[1][0] == '-') {
7203 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7204 argv[1][1]);
7205 usage(B_FALSE);
7206 }
7207
7208 if (argc < 2) {
7209 (void) fprintf(stderr, gettext("missing property=value "
7210 "argument\n"));
7211 usage(B_FALSE);
7212 }
7213
7214 if (argc < 3) {
7215 (void) fprintf(stderr, gettext("missing pool name\n"));
7216 usage(B_FALSE);
7217 }
7218
7219 if (argc > 3) {
7220 (void) fprintf(stderr, gettext("too many pool names\n"));
7221 usage(B_FALSE);
7222 }
7223
7224 cb.cb_propname = argv[1];
7225 cb.cb_value = strchr(cb.cb_propname, '=');
7226 if (cb.cb_value == NULL) {
7227 (void) fprintf(stderr, gettext("missing value in "
7228 "property=value argument\n"));
7229 usage(B_FALSE);
7230 }
7231
7232 *(cb.cb_value) = '\0';
7233 cb.cb_value++;
7234
7235 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
7236 set_callback, &cb);
7237
7238 return (error);
7239}
7240
7241static int
7242find_command_idx(char *command, int *idx)
7243{
7244 int i;
7245
7246 for (i = 0; i < NCOMMAND; i++) {
7247 if (command_table[i].name == NULL)
7248 continue;
7249
7250 if (strcmp(command, command_table[i].name) == 0) {
7251 *idx = i;
7252 return (0);
7253 }
7254 }
7255 return (1);
7256}
7257
7258int
7259main(int argc, char **argv)
7260{
7261 int ret;
d4ed6673 7262 int i = 0;
34dc7c2f
BB
7263 char *cmdname;
7264
7265 (void) setlocale(LC_ALL, "");
7266 (void) textdomain(TEXT_DOMAIN);
5b4136bd 7267 srand(time(NULL));
34dc7c2f 7268
308a451f
MA
7269 dprintf_setup(&argc, argv);
7270
34dc7c2f
BB
7271 opterr = 0;
7272
7273 /*
7274 * Make sure the user has specified some command.
7275 */
7276 if (argc < 2) {
7277 (void) fprintf(stderr, gettext("missing command\n"));
7278 usage(B_FALSE);
7279 }
7280
7281 cmdname = argv[1];
7282
7283 /*
7284 * Special case '-?'
7285 */
d1d7e268 7286 if ((strcmp(cmdname, "-?") == 0) || strcmp(cmdname, "--help") == 0)
34dc7c2f
BB
7287 usage(B_TRUE);
7288
65037d9b
BB
7289 if ((g_zfs = libzfs_init()) == NULL) {
7290 (void) fprintf(stderr, "%s", libzfs_error_init(errno));
9b020fd9 7291 return (1);
65037d9b 7292 }
9b020fd9
BB
7293
7294 libzfs_print_on_error(g_zfs, B_TRUE);
7295
6f1ffb06 7296 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
34dc7c2f
BB
7297
7298 /*
7299 * Run the appropriate command.
7300 */
7301 if (find_command_idx(cmdname, &i) == 0) {
7302 current_command = &command_table[i];
7303 ret = command_table[i].func(argc - 1, argv + 1);
7304 } else if (strchr(cmdname, '=')) {
7305 verify(find_command_idx("set", &i) == 0);
7306 current_command = &command_table[i];
7307 ret = command_table[i].func(argc, argv);
7308 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
7309 /*
7310 * 'freeze' is a vile debugging abomination, so we treat
7311 * it as such.
7312 */
7313 char buf[16384];
7314 int fd = open(ZFS_DEV, O_RDWR);
7315 (void) strcpy((void *)buf, argv[2]);
7316 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
7317 } else {
7318 (void) fprintf(stderr, gettext("unrecognized "
7319 "command '%s'\n"), cmdname);
7320 usage(B_FALSE);
d4ed6673 7321 ret = 1;
34dc7c2f
BB
7322 }
7323
6f1ffb06
MA
7324 if (ret == 0 && log_history)
7325 (void) zpool_log_history(g_zfs, history_str);
7326
34dc7c2f
BB
7327 libzfs_fini(g_zfs);
7328
7329 /*
7330 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
7331 * for the purposes of running ::findleaks.
7332 */
7333 if (getenv("ZFS_ABORT") != NULL) {
7334 (void) printf("dumping core by request\n");
7335 abort();
7336 }
7337
7338 return (ret);
7339}