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