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