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