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