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