]> git.proxmox.com Git - mirror_zfs.git/blame - cmd/zpool/zpool_main.c
Fix `zpool status` overflow on fast scrubs
[mirror_zfs.git] / cmd / zpool / zpool_main.c
CommitLineData
34dc7c2f
BB
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
428870ff 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
95bcd51e 24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
241b5415 25 * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
95bcd51e 26 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
df831108 27 * Copyright (c) 2012 by Cyril Plisko. All rights reserved.
eaa52d32 28 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
8e896579 29 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
bec1067d 30 * Copyright (c) 2017 Datto Inc.
d3f2cd7e 31 * Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
34dc7c2f
BB
32 */
33
34dc7c2f
BB
34#include <assert.h>
35#include <ctype.h>
36#include <dirent.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <libgen.h>
40#include <libintl.h>
41#include <libuutil.h>
42#include <locale.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <strings.h>
47#include <unistd.h>
34dc7c2f
BB
48#include <pwd.h>
49#include <zone.h>
d6418de0 50#include <sys/wait.h>
1bd201e7 51#include <zfs_prop.h>
34dc7c2f 52#include <sys/fs/zfs.h>
34dc7c2f 53#include <sys/stat.h>
46364cb2 54#include <sys/systeminfo.h>
d02ca379 55#include <sys/fm/fs/zfs.h>
26685276
BB
56#include <sys/fm/util.h>
57#include <sys/fm/protocol.h>
8c7aa0cf 58#include <sys/zfs_ioctl.h>
b5256303 59#include <sys/mount.h>
d4a72f23
TC
60#include <sys/sysmacros.h>
61
193a37cb 62#include <math.h>
34dc7c2f
BB
63
64#include <libzfs.h>
65
66#include "zpool_util.h"
67#include "zfs_comutil.h"
9ae529ec 68#include "zfeature_common.h"
34dc7c2f 69
428870ff
BB
70#include "statcommon.h"
71
34dc7c2f
BB
72static int zpool_do_create(int, char **);
73static int zpool_do_destroy(int, char **);
74
75static int zpool_do_add(int, char **);
76static int zpool_do_remove(int, char **);
131cc95c 77static int zpool_do_labelclear(int, char **);
34dc7c2f
BB
78
79static int zpool_do_list(int, char **);
80static int zpool_do_iostat(int, char **);
81static int zpool_do_status(int, char **);
82
83static int zpool_do_online(int, char **);
84static int zpool_do_offline(int, char **);
85static int zpool_do_clear(int, char **);
1bd201e7 86static int zpool_do_reopen(int, char **);
34dc7c2f 87
3541dc6d
GA
88static int zpool_do_reguid(int, char **);
89
34dc7c2f
BB
90static int zpool_do_attach(int, char **);
91static int zpool_do_detach(int, char **);
92static int zpool_do_replace(int, char **);
428870ff 93static int zpool_do_split(int, char **);
34dc7c2f
BB
94
95static int zpool_do_scrub(int, char **);
96
97static int zpool_do_import(int, char **);
98static int zpool_do_export(int, char **);
99
100static int zpool_do_upgrade(int, char **);
101
102static int zpool_do_history(int, char **);
26685276 103static int zpool_do_events(int, char **);
34dc7c2f
BB
104
105static int zpool_do_get(int, char **);
106static int zpool_do_set(int, char **);
107
bec1067d
AP
108static int zpool_do_sync(int, char **);
109
34dc7c2f
BB
110/*
111 * These libumem hooks provide a reasonable set of defaults for the allocator's
112 * debugging facilities.
113 */
b128c09f
BB
114
115#ifdef DEBUG
34dc7c2f
BB
116const char *
117_umem_debug_init(void)
118{
119 return ("default,verbose"); /* $UMEM_DEBUG setting */
120}
121
122const char *
123_umem_logging_init(void)
124{
125 return ("fail,contents"); /* $UMEM_LOGGING setting */
126}
b128c09f 127#endif
34dc7c2f
BB
128
129typedef enum {
130 HELP_ADD,
131 HELP_ATTACH,
132 HELP_CLEAR,
133 HELP_CREATE,
134 HELP_DESTROY,
135 HELP_DETACH,
136 HELP_EXPORT,
137 HELP_HISTORY,
138 HELP_IMPORT,
139 HELP_IOSTAT,
131cc95c 140 HELP_LABELCLEAR,
34dc7c2f
BB
141 HELP_LIST,
142 HELP_OFFLINE,
143 HELP_ONLINE,
144 HELP_REPLACE,
145 HELP_REMOVE,
146 HELP_SCRUB,
147 HELP_STATUS,
148 HELP_UPGRADE,
26685276 149 HELP_EVENTS,
34dc7c2f 150 HELP_GET,
428870ff 151 HELP_SET,
3541dc6d 152 HELP_SPLIT,
bec1067d 153 HELP_SYNC,
1bd201e7
CS
154 HELP_REGUID,
155 HELP_REOPEN
34dc7c2f
BB
156} zpool_help_t;
157
158
193a37cb
TH
159/*
160 * Flags for stats to display with "zpool iostats"
161 */
162enum iostat_type {
163 IOS_DEFAULT = 0,
164 IOS_LATENCY = 1,
165 IOS_QUEUES = 2,
166 IOS_L_HISTO = 3,
7e945072 167 IOS_RQ_HISTO = 4,
193a37cb
TH
168 IOS_COUNT, /* always last element */
169};
170
171/* iostat_type entries as bitmasks */
172#define IOS_DEFAULT_M (1ULL << IOS_DEFAULT)
173#define IOS_LATENCY_M (1ULL << IOS_LATENCY)
174#define IOS_QUEUES_M (1ULL << IOS_QUEUES)
175#define IOS_L_HISTO_M (1ULL << IOS_L_HISTO)
7e945072
TH
176#define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO)
177
178/* Mask of all the histo bits */
179#define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
180
181/*
182 * Lookup table for iostat flags to nvlist names. Basically a list
183 * of all the nvlists a flag requires. Also specifies the order in
184 * which data gets printed in zpool iostat.
185 */
186static const char *vsx_type_to_nvlist[IOS_COUNT][11] = {
187 [IOS_L_HISTO] = {
188 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
189 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
190 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
191 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
192 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
193 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
194 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
195 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
196 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
197 NULL},
198 [IOS_LATENCY] = {
199 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
200 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
201 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
202 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
203 NULL},
204 [IOS_QUEUES] = {
205 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
206 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
207 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
208 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
209 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
210 NULL},
211 [IOS_RQ_HISTO] = {
212 ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
213 ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
214 ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
215 ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
216 ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
217 ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
218 ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
219 ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
220 ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
221 ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
222 NULL},
223};
224
225
226/*
227 * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
228 * Right now, only one histo bit is ever set at one time, so we can
229 * just do a highbit64(a)
230 */
231#define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1)
193a37cb 232
34dc7c2f
BB
233typedef struct zpool_command {
234 const char *name;
235 int (*func)(int, char **);
236 zpool_help_t usage;
237} zpool_command_t;
238
239/*
240 * Master command table. Each ZFS command has a name, associated function, and
241 * usage message. The usage messages need to be internationalized, so we have
242 * to have a function to return the usage message based on a command index.
243 *
244 * These commands are organized according to how they are displayed in the usage
245 * message. An empty command (one with a NULL name) indicates an empty line in
246 * the generic usage message.
247 */
248static zpool_command_t command_table[] = {
249 { "create", zpool_do_create, HELP_CREATE },
250 { "destroy", zpool_do_destroy, HELP_DESTROY },
251 { NULL },
252 { "add", zpool_do_add, HELP_ADD },
253 { "remove", zpool_do_remove, HELP_REMOVE },
254 { NULL },
131cc95c
DK
255 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
256 { NULL },
34dc7c2f
BB
257 { "list", zpool_do_list, HELP_LIST },
258 { "iostat", zpool_do_iostat, HELP_IOSTAT },
259 { "status", zpool_do_status, HELP_STATUS },
260 { NULL },
261 { "online", zpool_do_online, HELP_ONLINE },
262 { "offline", zpool_do_offline, HELP_OFFLINE },
263 { "clear", zpool_do_clear, HELP_CLEAR },
1bd201e7 264 { "reopen", zpool_do_reopen, HELP_REOPEN },
34dc7c2f
BB
265 { NULL },
266 { "attach", zpool_do_attach, HELP_ATTACH },
267 { "detach", zpool_do_detach, HELP_DETACH },
268 { "replace", zpool_do_replace, HELP_REPLACE },
428870ff 269 { "split", zpool_do_split, HELP_SPLIT },
34dc7c2f
BB
270 { NULL },
271 { "scrub", zpool_do_scrub, HELP_SCRUB },
272 { NULL },
273 { "import", zpool_do_import, HELP_IMPORT },
274 { "export", zpool_do_export, HELP_EXPORT },
275 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
3541dc6d 276 { "reguid", zpool_do_reguid, HELP_REGUID },
34dc7c2f
BB
277 { NULL },
278 { "history", zpool_do_history, HELP_HISTORY },
26685276
BB
279 { "events", zpool_do_events, HELP_EVENTS },
280 { NULL },
34dc7c2f
BB
281 { "get", zpool_do_get, HELP_GET },
282 { "set", zpool_do_set, HELP_SET },
bec1067d 283 { "sync", zpool_do_sync, HELP_SYNC },
34dc7c2f
BB
284};
285
193a37cb 286#define NCOMMAND (ARRAY_SIZE(command_table))
34dc7c2f 287
6f1ffb06 288static zpool_command_t *current_command;
34dc7c2f 289static char history_str[HIS_MAX_RECORD_LEN];
6f1ffb06 290static boolean_t log_history = B_TRUE;
428870ff
BB
291static uint_t timestamp_fmt = NODATE;
292
34dc7c2f 293static const char *
e9aa730c
GM
294get_usage(zpool_help_t idx)
295{
34dc7c2f
BB
296 switch (idx) {
297 case HELP_ADD:
a77f29f9 298 return (gettext("\tadd [-fgLnP] [-o property=value] "
df831108 299 "<pool> <vdev> ...\n"));
34dc7c2f 300 case HELP_ATTACH:
df831108
CP
301 return (gettext("\tattach [-f] [-o property=value] "
302 "<pool> <device> <new-device>\n"));
34dc7c2f 303 case HELP_CLEAR:
428870ff 304 return (gettext("\tclear [-nF] <pool> [device]\n"));
34dc7c2f 305 case HELP_CREATE:
9ae529ec 306 return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
b128c09f 307 "\t [-O file-system-property=value] ... \n"
34dc7c2f
BB
308 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
309 case HELP_DESTROY:
310 return (gettext("\tdestroy [-f] <pool>\n"));
311 case HELP_DETACH:
312 return (gettext("\tdetach <pool> <device>\n"));
313 case HELP_EXPORT:
859735c0 314 return (gettext("\texport [-af] <pool> ...\n"));
34dc7c2f
BB
315 case HELP_HISTORY:
316 return (gettext("\thistory [-il] [<pool>] ...\n"));
317 case HELP_IMPORT:
318 return (gettext("\timport [-d dir] [-D]\n"
b5256303
TC
319 "\timport [-d dir | -c cachefile] [-F [-n]] [-l] "
320 "<pool | id>\n"
34dc7c2f 321 "\timport [-o mntopts] [-o property=value] ... \n"
b5256303 322 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
572e2857 323 "[-R root] [-F [-n]] -a\n"
34dc7c2f 324 "\timport [-o mntopts] [-o property=value] ... \n"
b5256303 325 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
572e2857
BB
326 "[-R root] [-F [-n]]\n"
327 "\t <pool | id> [newpool]\n"));
34dc7c2f 328 case HELP_IOSTAT:
d6418de0
TH
329 return (gettext("\tiostat [[[-c [script1,script2,...]"
330 "[-lq]]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
331 "\t [[pool ...]|[pool vdev ...]|[vdev ...]]"
332 " [interval [count]]\n"));
131cc95c
DK
333 case HELP_LABELCLEAR:
334 return (gettext("\tlabelclear [-f] <vdev>\n"));
34dc7c2f 335 case HELP_LIST:
2a8b84b7 336 return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
63f88c12 337 "[-T d|u] [pool] ... \n"
338 "\t [interval [count]]\n"));
34dc7c2f 339 case HELP_OFFLINE:
4a283c7f 340 return (gettext("\toffline [-f] [-t] <pool> <device> ...\n"));
34dc7c2f
BB
341 case HELP_ONLINE:
342 return (gettext("\tonline <pool> <device> ...\n"));
343 case HELP_REPLACE:
628668a3
TF
344 return (gettext("\treplace [-f] [-o property=value] "
345 "<pool> <device> [new-device]\n"));
34dc7c2f
BB
346 case HELP_REMOVE:
347 return (gettext("\tremove <pool> <device> ...\n"));
1bd201e7 348 case HELP_REOPEN:
d3f2cd7e 349 return (gettext("\treopen [-n] <pool>\n"));
34dc7c2f 350 case HELP_SCRUB:
0ea05c64 351 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
34dc7c2f 352 case HELP_STATUS:
d6418de0 353 return (gettext("\tstatus [-c [script1,script2,...]] [-gLPvxD]"
63f88c12 354 "[-T d|u] [pool] ... \n"
355 "\t [interval [count]]\n"));
34dc7c2f
BB
356 case HELP_UPGRADE:
357 return (gettext("\tupgrade\n"
358 "\tupgrade -v\n"
359 "\tupgrade [-V version] <-a | pool ...>\n"));
26685276 360 case HELP_EVENTS:
88f9c939 361 return (gettext("\tevents [-vHf [pool] | -c]\n"));
34dc7c2f 362 case HELP_GET:
2a8b84b7
AS
363 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
364 "<\"all\" | property[,...]> <pool> ...\n"));
34dc7c2f
BB
365 case HELP_SET:
366 return (gettext("\tset <property=value> <pool> \n"));
428870ff 367 case HELP_SPLIT:
b5256303 368 return (gettext("\tsplit [-gLnPl] [-R altroot] [-o mntopts]\n"
428870ff
BB
369 "\t [-o property=value] <pool> <newpool> "
370 "[<device> ...]\n"));
3541dc6d
GA
371 case HELP_REGUID:
372 return (gettext("\treguid <pool>\n"));
bec1067d
AP
373 case HELP_SYNC:
374 return (gettext("\tsync [pool] ...\n"));
34dc7c2f
BB
375 }
376
377 abort();
378 /* NOTREACHED */
379}
380
381
382/*
383 * Callback routine that will print out a pool property value.
384 */
385static int
386print_prop_cb(int prop, void *cb)
387{
388 FILE *fp = cb;
389
428870ff 390 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
34dc7c2f
BB
391
392 if (zpool_prop_readonly(prop))
393 (void) fprintf(fp, " NO ");
394 else
428870ff 395 (void) fprintf(fp, " YES ");
34dc7c2f
BB
396
397 if (zpool_prop_values(prop) == NULL)
398 (void) fprintf(fp, "-\n");
399 else
400 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
401
402 return (ZPROP_CONT);
403}
404
405/*
406 * Display usage message. If we're inside a command, display only the usage for
407 * that command. Otherwise, iterate over the entire command table and display
408 * a complete usage message.
409 */
410void
411usage(boolean_t requested)
412{
413 FILE *fp = requested ? stdout : stderr;
414
415 if (current_command == NULL) {
416 int i;
417
418 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
419 (void) fprintf(fp,
420 gettext("where 'command' is one of the following:\n\n"));
421
422 for (i = 0; i < NCOMMAND; i++) {
423 if (command_table[i].name == NULL)
424 (void) fprintf(fp, "\n");
425 else
426 (void) fprintf(fp, "%s",
427 get_usage(command_table[i].usage));
428 }
429 } else {
430 (void) fprintf(fp, gettext("usage:\n"));
431 (void) fprintf(fp, "%s", get_usage(current_command->usage));
432 }
433
434 if (current_command != NULL &&
435 ((strcmp(current_command->name, "set") == 0) ||
436 (strcmp(current_command->name, "get") == 0) ||
437 (strcmp(current_command->name, "list") == 0))) {
438
439 (void) fprintf(fp,
440 gettext("\nthe following properties are supported:\n"));
441
428870ff 442 (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
34dc7c2f
BB
443 "PROPERTY", "EDIT", "VALUES");
444
445 /* Iterate over all properties */
446 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
447 ZFS_TYPE_POOL);
9ae529ec
CS
448
449 (void) fprintf(fp, "\t%-15s ", "feature@...");
450 (void) fprintf(fp, "YES disabled | enabled | active\n");
451
452 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
453 "appended with a feature name.\nSee zpool-features(5).\n"));
34dc7c2f
BB
454 }
455
456 /*
457 * See comments at end of main().
458 */
459 if (getenv("ZFS_ABORT") != NULL) {
460 (void) printf("dumping core by request\n");
461 abort();
462 }
463
464 exit(requested ? 0 : 2);
465}
466
467void
468print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
d2f3e292 469 boolean_t print_logs, int name_flags)
34dc7c2f
BB
470{
471 nvlist_t **child;
472 uint_t c, children;
473 char *vname;
474
475 if (name != NULL)
476 (void) printf("\t%*s%s\n", indent, "", name);
477
478 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
479 &child, &children) != 0)
480 return;
481
482 for (c = 0; c < children; c++) {
483 uint64_t is_log = B_FALSE;
484
485 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
486 &is_log);
487 if ((is_log && !print_logs) || (!is_log && print_logs))
488 continue;
489
d2f3e292 490 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
34dc7c2f 491 print_vdev_tree(zhp, vname, child[c], indent + 2,
d2f3e292 492 B_FALSE, name_flags);
34dc7c2f
BB
493 free(vname);
494 }
495}
496
b9b24bb4
CS
497static boolean_t
498prop_list_contains_feature(nvlist_t *proplist)
499{
500 nvpair_t *nvp;
501 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
502 nvp = nvlist_next_nvpair(proplist, nvp)) {
503 if (zpool_prop_feature(nvpair_name(nvp)))
504 return (B_TRUE);
505 }
506 return (B_FALSE);
507}
508
34dc7c2f
BB
509/*
510 * Add a property pair (name, string-value) into a property nvlist.
511 */
512static int
b128c09f
BB
513add_prop_list(const char *propname, char *propval, nvlist_t **props,
514 boolean_t poolprop)
34dc7c2f 515{
31864e3d 516 zpool_prop_t prop = ZPOOL_PROP_INVAL;
b128c09f 517 zfs_prop_t fprop;
34dc7c2f 518 nvlist_t *proplist;
b128c09f
BB
519 const char *normnm;
520 char *strval;
34dc7c2f
BB
521
522 if (*props == NULL &&
523 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
524 (void) fprintf(stderr,
525 gettext("internal error: out of memory\n"));
526 return (1);
527 }
528
529 proplist = *props;
530
b128c09f 531 if (poolprop) {
b9b24bb4
CS
532 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
533
31864e3d 534 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
9ae529ec 535 !zpool_prop_feature(propname)) {
b128c09f
BB
536 (void) fprintf(stderr, gettext("property '%s' is "
537 "not a valid pool property\n"), propname);
538 return (2);
539 }
b9b24bb4
CS
540
541 /*
542 * feature@ properties and version should not be specified
543 * at the same time.
544 */
31864e3d 545 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
b9b24bb4
CS
546 nvlist_exists(proplist, vname)) ||
547 (prop == ZPOOL_PROP_VERSION &&
548 prop_list_contains_feature(proplist))) {
549 (void) fprintf(stderr, gettext("'feature@' and "
550 "'version' properties cannot be specified "
551 "together\n"));
552 return (2);
553 }
554
555
9ae529ec
CS
556 if (zpool_prop_feature(propname))
557 normnm = propname;
558 else
559 normnm = zpool_prop_to_name(prop);
b128c09f 560 } else {
9babb374
BB
561 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
562 normnm = zfs_prop_to_name(fprop);
563 } else {
564 normnm = propname;
b128c09f 565 }
34dc7c2f
BB
566 }
567
b128c09f
BB
568 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
569 prop != ZPOOL_PROP_CACHEFILE) {
34dc7c2f
BB
570 (void) fprintf(stderr, gettext("property '%s' "
571 "specified multiple times\n"), propname);
572 return (2);
573 }
574
b128c09f 575 if (nvlist_add_string(proplist, normnm, propval) != 0) {
34dc7c2f
BB
576 (void) fprintf(stderr, gettext("internal "
577 "error: out of memory\n"));
578 return (1);
579 }
580
581 return (0);
582}
583
2f3ec900
RY
584/*
585 * Set a default property pair (name, string-value) in a property nvlist
586 */
587static int
588add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
589 boolean_t poolprop)
590{
591 char *pval;
592
593 if (nvlist_lookup_string(*props, propname, &pval) == 0)
594 return (0);
595
596 return (add_prop_list(propname, propval, props, B_TRUE));
597}
598
34dc7c2f 599/*
a77f29f9 600 * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
34dc7c2f
BB
601 *
602 * -f Force addition of devices, even if they appear in use
d2f3e292
RY
603 * -g Display guid for individual vdev name.
604 * -L Follow links when resolving vdev path name.
34dc7c2f
BB
605 * -n Do not add the devices, but display the resulting layout if
606 * they were to be added.
df831108 607 * -o Set property=value.
a77f29f9 608 * -P Display full path for vdev name.
34dc7c2f
BB
609 *
610 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
611 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
612 * libzfs.
613 */
614int
615zpool_do_add(int argc, char **argv)
616{
617 boolean_t force = B_FALSE;
618 boolean_t dryrun = B_FALSE;
d2f3e292 619 int name_flags = 0;
34dc7c2f
BB
620 int c;
621 nvlist_t *nvroot;
622 char *poolname;
623 int ret;
624 zpool_handle_t *zhp;
625 nvlist_t *config;
df831108
CP
626 nvlist_t *props = NULL;
627 char *propval;
34dc7c2f
BB
628
629 /* check options */
a77f29f9 630 while ((c = getopt(argc, argv, "fgLno:P")) != -1) {
34dc7c2f
BB
631 switch (c) {
632 case 'f':
633 force = B_TRUE;
634 break;
d2f3e292
RY
635 case 'g':
636 name_flags |= VDEV_NAME_GUID;
637 break;
638 case 'L':
639 name_flags |= VDEV_NAME_FOLLOW_LINKS;
640 break;
34dc7c2f
BB
641 case 'n':
642 dryrun = B_TRUE;
643 break;
df831108
CP
644 case 'o':
645 if ((propval = strchr(optarg, '=')) == NULL) {
646 (void) fprintf(stderr, gettext("missing "
647 "'=' for -o option\n"));
648 usage(B_FALSE);
649 }
650 *propval = '\0';
651 propval++;
652
653 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
654 (add_prop_list(optarg, propval, &props, B_TRUE)))
655 usage(B_FALSE);
656 break;
a77f29f9 657 case 'P':
d2f3e292
RY
658 name_flags |= VDEV_NAME_PATH;
659 break;
34dc7c2f
BB
660 case '?':
661 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
662 optopt);
663 usage(B_FALSE);
664 }
665 }
666
667 argc -= optind;
668 argv += optind;
669
670 /* get pool name and check number of arguments */
671 if (argc < 1) {
672 (void) fprintf(stderr, gettext("missing pool name argument\n"));
673 usage(B_FALSE);
674 }
675 if (argc < 2) {
676 (void) fprintf(stderr, gettext("missing vdev specification\n"));
677 usage(B_FALSE);
678 }
679
680 poolname = argv[0];
681
682 argc--;
683 argv++;
684
685 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
686 return (1);
687
688 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
689 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
690 poolname);
691 zpool_close(zhp);
692 return (1);
693 }
694
dddef7d6 695 /* unless manually specified use "ashift" pool property (if set) */
696 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
697 int intval;
698 zprop_source_t src;
699 char strval[ZPOOL_MAXPROPLEN];
700
701 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
702 if (src != ZPROP_SRC_DEFAULT) {
703 (void) sprintf(strval, "%" PRId32, intval);
704 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
705 &props, B_TRUE) == 0);
706 }
707 }
708
34dc7c2f 709 /* pass off to get_vdev_spec for processing */
df831108 710 nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
b128c09f 711 argc, argv);
34dc7c2f
BB
712 if (nvroot == NULL) {
713 zpool_close(zhp);
714 return (1);
715 }
716
717 if (dryrun) {
718 nvlist_t *poolnvroot;
e02b533e
TC
719 nvlist_t **l2child;
720 uint_t l2children, c;
721 char *vname;
722 boolean_t hadcache = B_FALSE;
34dc7c2f
BB
723
724 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
725 &poolnvroot) == 0);
726
727 (void) printf(gettext("would update '%s' to the following "
728 "configuration:\n"), zpool_get_name(zhp));
729
730 /* print original main pool and new tree */
d2f3e292
RY
731 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE,
732 name_flags);
733 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE, name_flags);
34dc7c2f
BB
734
735 /* Do the same for the logs */
736 if (num_logs(poolnvroot) > 0) {
d2f3e292
RY
737 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE,
738 name_flags);
739 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE,
740 name_flags);
34dc7c2f 741 } else if (num_logs(nvroot) > 0) {
d2f3e292
RY
742 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE,
743 name_flags);
34dc7c2f
BB
744 }
745
e02b533e
TC
746 /* Do the same for the caches */
747 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_L2CACHE,
748 &l2child, &l2children) == 0 && l2children) {
749 hadcache = B_TRUE;
750 (void) printf(gettext("\tcache\n"));
751 for (c = 0; c < l2children; c++) {
752 vname = zpool_vdev_name(g_zfs, NULL,
d2f3e292 753 l2child[c], name_flags);
e02b533e
TC
754 (void) printf("\t %s\n", vname);
755 free(vname);
756 }
757 }
758 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
759 &l2child, &l2children) == 0 && l2children) {
760 if (!hadcache)
761 (void) printf(gettext("\tcache\n"));
762 for (c = 0; c < l2children; c++) {
763 vname = zpool_vdev_name(g_zfs, NULL,
d2f3e292 764 l2child[c], name_flags);
e02b533e
TC
765 (void) printf("\t %s\n", vname);
766 free(vname);
767 }
768 }
769
34dc7c2f
BB
770 ret = 0;
771 } else {
772 ret = (zpool_add(zhp, nvroot) != 0);
773 }
774
df831108 775 nvlist_free(props);
34dc7c2f
BB
776 nvlist_free(nvroot);
777 zpool_close(zhp);
778
779 return (ret);
780}
781
782/*
428870ff 783 * zpool remove <pool> <vdev> ...
34dc7c2f 784 *
428870ff
BB
785 * Removes the given vdev from the pool. Currently, this supports removing
786 * spares, cache, and log devices from the pool.
34dc7c2f
BB
787 */
788int
789zpool_do_remove(int argc, char **argv)
790{
791 char *poolname;
792 int i, ret = 0;
884385a0 793 zpool_handle_t *zhp = NULL;
34dc7c2f
BB
794
795 argc--;
796 argv++;
797
798 /* get pool name and check number of arguments */
799 if (argc < 1) {
800 (void) fprintf(stderr, gettext("missing pool name argument\n"));
801 usage(B_FALSE);
802 }
803 if (argc < 2) {
804 (void) fprintf(stderr, gettext("missing device\n"));
805 usage(B_FALSE);
806 }
807
808 poolname = argv[0];
809
810 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
811 return (1);
812
813 for (i = 1; i < argc; i++) {
814 if (zpool_vdev_remove(zhp, argv[i]) != 0)
815 ret = 1;
816 }
884385a0 817 zpool_close(zhp);
34dc7c2f
BB
818
819 return (ret);
820}
821
131cc95c 822/*
dbb38f66
YP
823 * zpool labelclear [-f] <vdev>
824 *
825 * -f Force clearing the label for the vdevs which are members of
826 * the exported or foreign pools.
131cc95c
DK
827 *
828 * Verifies that the vdev is not active and zeros out the label information
829 * on the device.
830 */
831int
832zpool_do_labelclear(int argc, char **argv)
833{
dbb38f66
YP
834 char vdev[MAXPATHLEN];
835 char *name = NULL;
836 struct stat st;
131cc95c 837 int c, fd = -1, ret = 0;
dbb38f66 838 nvlist_t *config;
131cc95c
DK
839 pool_state_t state;
840 boolean_t inuse = B_FALSE;
841 boolean_t force = B_FALSE;
842
843 /* check options */
844 while ((c = getopt(argc, argv, "f")) != -1) {
845 switch (c) {
846 case 'f':
847 force = B_TRUE;
848 break;
849 default:
850 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
851 optopt);
852 usage(B_FALSE);
853 }
854 }
855
856 argc -= optind;
857 argv += optind;
858
859 /* get vdev name */
860 if (argc < 1) {
dbb38f66
YP
861 (void) fprintf(stderr, gettext("missing vdev name\n"));
862 usage(B_FALSE);
863 }
864 if (argc > 1) {
865 (void) fprintf(stderr, gettext("too many arguments\n"));
131cc95c
DK
866 usage(B_FALSE);
867 }
868
dbb38f66
YP
869 /*
870 * Check if we were given absolute path and use it as is.
871 * Otherwise if the provided vdev name doesn't point to a file,
872 * try prepending expected disk paths and partition numbers.
873 */
874 (void) strlcpy(vdev, argv[0], sizeof (vdev));
875 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
876 int error;
877
878 error = zfs_resolve_shortname(argv[0], vdev, MAXPATHLEN);
879 if (error == 0 && zfs_dev_is_whole_disk(vdev)) {
880 if (zfs_append_partition(vdev, MAXPATHLEN) == -1)
881 error = ENOENT;
882 }
883
884 if (error || (stat(vdev, &st) != 0)) {
885 (void) fprintf(stderr, gettext(
886 "failed to find device %s, try specifying absolute "
887 "path instead\n"), argv[0]);
888 return (1);
889 }
131cc95c
DK
890 }
891
dbb38f66
YP
892 if ((fd = open(vdev, O_RDWR)) < 0) {
893 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
894 vdev, strerror(errno));
895 return (1);
896 }
131cc95c 897
a167aa7c
GDN
898 if (ioctl(fd, BLKFLSBUF) != 0)
899 (void) fprintf(stderr, gettext("failed to invalidate "
900 "cache for %s: %s\n"), vdev, strerror(errno));
901
dbb38f66 902 if (zpool_read_label(fd, &config, NULL) != 0 || config == NULL) {
131cc95c 903 (void) fprintf(stderr,
dbb38f66 904 gettext("failed to check state for %s\n"), vdev);
c721ba43
TH
905 ret = 1;
906 goto errout;
dbb38f66
YP
907 }
908 nvlist_free(config);
131cc95c 909
dbb38f66
YP
910 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
911 if (ret != 0) {
912 (void) fprintf(stderr,
913 gettext("failed to check state for %s\n"), vdev);
c721ba43
TH
914 ret = 1;
915 goto errout;
131cc95c
DK
916 }
917
dbb38f66
YP
918 if (!inuse)
919 goto wipe_label;
920
921 switch (state) {
922 default:
923 case POOL_STATE_ACTIVE:
924 case POOL_STATE_SPARE:
925 case POOL_STATE_L2CACHE:
926 (void) fprintf(stderr, gettext(
927 "%s is a member (%s) of pool \"%s\"\n"),
928 vdev, zpool_pool_state_to_name(state), name);
929 ret = 1;
930 goto errout;
131cc95c 931
dbb38f66
YP
932 case POOL_STATE_EXPORTED:
933 if (force)
131cc95c 934 break;
dbb38f66
YP
935 (void) fprintf(stderr, gettext(
936 "use '-f' to override the following error:\n"
937 "%s is a member of exported pool \"%s\"\n"),
938 vdev, name);
939 ret = 1;
940 goto errout;
941
942 case POOL_STATE_POTENTIALLY_ACTIVE:
943 if (force)
944 break;
945 (void) fprintf(stderr, gettext(
946 "use '-f' to override the following error:\n"
947 "%s is a member of potentially active pool \"%s\"\n"),
948 vdev, name);
949 ret = 1;
950 goto errout;
951
952 case POOL_STATE_DESTROYED:
953 /* inuse should never be set for a destroyed pool */
954 assert(0);
955 break;
131cc95c
DK
956 }
957
958wipe_label:
dbb38f66
YP
959 ret = zpool_clear_label(fd);
960 if (ret != 0) {
131cc95c 961 (void) fprintf(stderr,
dbb38f66 962 gettext("failed to clear label for %s\n"), vdev);
131cc95c
DK
963 }
964
965errout:
dbb38f66
YP
966 free(name);
967 (void) close(fd);
131cc95c
DK
968
969 return (ret);
970}
971
34dc7c2f 972/*
9ae529ec 973 * zpool create [-fnd] [-o property=value] ...
b128c09f
BB
974 * [-O file-system-property=value] ...
975 * [-R root] [-m mountpoint] <pool> <dev> ...
34dc7c2f
BB
976 *
977 * -f Force creation, even if devices appear in use
978 * -n Do not create the pool, but display the resulting layout if it
979 * were to be created.
980 * -R Create a pool under an alternate root
981 * -m Set default mountpoint for the root dataset. By default it's
9ae529ec 982 * '/<pool>'
34dc7c2f 983 * -o Set property=value.
e4010f27 984 * -o Set feature@feature=enabled|disabled.
9ae529ec
CS
985 * -d Don't automatically enable all supported pool features
986 * (individual features can be enabled with -o).
b128c09f 987 * -O Set fsproperty=value in the pool's root file system
34dc7c2f
BB
988 *
989 * Creates the named pool according to the given vdev specification. The
990 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
991 * we get the nvlist back from get_vdev_spec(), we either print out the contents
992 * (if '-n' was specified), or pass it to libzfs to do the creation.
993 */
994int
995zpool_do_create(int argc, char **argv)
996{
997 boolean_t force = B_FALSE;
998 boolean_t dryrun = B_FALSE;
9ae529ec 999 boolean_t enable_all_pool_feat = B_TRUE;
34dc7c2f
BB
1000 int c;
1001 nvlist_t *nvroot = NULL;
1002 char *poolname;
023bbe6f 1003 char *tname = NULL;
34dc7c2f
BB
1004 int ret = 1;
1005 char *altroot = NULL;
1006 char *mountpoint = NULL;
b128c09f 1007 nvlist_t *fsprops = NULL;
34dc7c2f
BB
1008 nvlist_t *props = NULL;
1009 char *propval;
1010
1011 /* check options */
83e9986f 1012 while ((c = getopt(argc, argv, ":fndR:m:o:O:t:")) != -1) {
34dc7c2f
BB
1013 switch (c) {
1014 case 'f':
1015 force = B_TRUE;
1016 break;
1017 case 'n':
1018 dryrun = B_TRUE;
1019 break;
9ae529ec
CS
1020 case 'd':
1021 enable_all_pool_feat = B_FALSE;
1022 break;
34dc7c2f
BB
1023 case 'R':
1024 altroot = optarg;
1025 if (add_prop_list(zpool_prop_to_name(
b128c09f 1026 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
34dc7c2f 1027 goto errout;
2f3ec900 1028 if (add_prop_list_default(zpool_prop_to_name(
b128c09f 1029 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
34dc7c2f
BB
1030 goto errout;
1031 break;
1032 case 'm':
7bc7f250 1033 /* Equivalent to -O mountpoint=optarg */
34dc7c2f
BB
1034 mountpoint = optarg;
1035 break;
1036 case 'o':
1037 if ((propval = strchr(optarg, '=')) == NULL) {
1038 (void) fprintf(stderr, gettext("missing "
1039 "'=' for -o option\n"));
1040 goto errout;
1041 }
1042 *propval = '\0';
1043 propval++;
1044
b128c09f
BB
1045 if (add_prop_list(optarg, propval, &props, B_TRUE))
1046 goto errout;
9ae529ec
CS
1047
1048 /*
1049 * If the user is creating a pool that doesn't support
1050 * feature flags, don't enable any features.
1051 */
1052 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1053 char *end;
1054 u_longlong_t ver;
1055
1056 ver = strtoull(propval, &end, 10);
1057 if (*end == '\0' &&
1058 ver < SPA_VERSION_FEATURES) {
1059 enable_all_pool_feat = B_FALSE;
1060 }
1061 }
3ac2794c
BB
1062 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1063 altroot = propval;
b128c09f
BB
1064 break;
1065 case 'O':
1066 if ((propval = strchr(optarg, '=')) == NULL) {
1067 (void) fprintf(stderr, gettext("missing "
1068 "'=' for -O option\n"));
1069 goto errout;
1070 }
1071 *propval = '\0';
1072 propval++;
1073
7bc7f250
WA
1074 /*
1075 * Mountpoints are checked and then added later.
1076 * Uniquely among properties, they can be specified
1077 * more than once, to avoid conflict with -m.
1078 */
1079 if (0 == strcmp(optarg,
1080 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1081 mountpoint = propval;
1082 } else if (add_prop_list(optarg, propval, &fsprops,
1083 B_FALSE)) {
34dc7c2f 1084 goto errout;
7bc7f250 1085 }
34dc7c2f 1086 break;
83e9986f
RY
1087 case 't':
1088 /*
1089 * Sanity check temporary pool name.
1090 */
1091 if (strchr(optarg, '/') != NULL) {
1092 (void) fprintf(stderr, gettext("cannot create "
1093 "'%s': invalid character '/' in temporary "
1094 "name\n"), optarg);
1095 (void) fprintf(stderr, gettext("use 'zfs "
1096 "create' to create a dataset\n"));
1097 goto errout;
1098 }
1099
1100 if (add_prop_list(zpool_prop_to_name(
1101 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1102 goto errout;
1103 if (add_prop_list_default(zpool_prop_to_name(
1104 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1105 goto errout;
023bbe6f 1106 tname = optarg;
83e9986f 1107 break;
34dc7c2f
BB
1108 case ':':
1109 (void) fprintf(stderr, gettext("missing argument for "
1110 "'%c' option\n"), optopt);
1111 goto badusage;
1112 case '?':
1113 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1114 optopt);
1115 goto badusage;
1116 }
1117 }
1118
1119 argc -= optind;
1120 argv += optind;
1121
1122 /* get pool name and check number of arguments */
1123 if (argc < 1) {
1124 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1125 goto badusage;
1126 }
1127 if (argc < 2) {
1128 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1129 goto badusage;
1130 }
1131
1132 poolname = argv[0];
1133
1134 /*
1135 * As a special case, check for use of '/' in the name, and direct the
1136 * user to use 'zfs create' instead.
1137 */
1138 if (strchr(poolname, '/') != NULL) {
1139 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1140 "character '/' in pool name\n"), poolname);
1141 (void) fprintf(stderr, gettext("use 'zfs create' to "
1142 "create a dataset\n"));
1143 goto errout;
1144 }
1145
1146 /* pass off to get_vdev_spec for bulk processing */
df30f566 1147 nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
b128c09f 1148 argc - 1, argv + 1);
34dc7c2f 1149 if (nvroot == NULL)
b128c09f 1150 goto errout;
34dc7c2f
BB
1151
1152 /* make_root_vdev() allows 0 toplevel children if there are spares */
1153 if (!zfs_allocatable_devs(nvroot)) {
1154 (void) fprintf(stderr, gettext("invalid vdev "
1155 "specification: at least one toplevel vdev must be "
1156 "specified\n"));
1157 goto errout;
1158 }
1159
34dc7c2f
BB
1160 if (altroot != NULL && altroot[0] != '/') {
1161 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1162 "must be an absolute path\n"), altroot);
1163 goto errout;
1164 }
1165
1166 /*
1167 * Check the validity of the mountpoint and direct the user to use the
1168 * '-m' mountpoint option if it looks like its in use.
1169 */
1170 if (mountpoint == NULL ||
1171 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1172 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1173 char buf[MAXPATHLEN];
1174 DIR *dirp;
1175
1176 if (mountpoint && mountpoint[0] != '/') {
1177 (void) fprintf(stderr, gettext("invalid mountpoint "
1178 "'%s': must be an absolute path, 'legacy', or "
1179 "'none'\n"), mountpoint);
1180 goto errout;
1181 }
1182
1183 if (mountpoint == NULL) {
1184 if (altroot != NULL)
1185 (void) snprintf(buf, sizeof (buf), "%s/%s",
1186 altroot, poolname);
1187 else
1188 (void) snprintf(buf, sizeof (buf), "/%s",
1189 poolname);
1190 } else {
1191 if (altroot != NULL)
1192 (void) snprintf(buf, sizeof (buf), "%s%s",
1193 altroot, mountpoint);
1194 else
1195 (void) snprintf(buf, sizeof (buf), "%s",
1196 mountpoint);
1197 }
1198
1199 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1200 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1201 "%s\n"), buf, strerror(errno));
1202 (void) fprintf(stderr, gettext("use '-m' "
1203 "option to provide a different default\n"));
1204 goto errout;
1205 } else if (dirp) {
1206 int count = 0;
1207
1208 while (count < 3 && readdir(dirp) != NULL)
1209 count++;
1210 (void) closedir(dirp);
1211
1212 if (count > 2) {
1213 (void) fprintf(stderr, gettext("mountpoint "
1214 "'%s' exists and is not empty\n"), buf);
1215 (void) fprintf(stderr, gettext("use '-m' "
1216 "option to provide a "
1217 "different default\n"));
1218 goto errout;
1219 }
1220 }
1221 }
1222
7bc7f250
WA
1223 /*
1224 * Now that the mountpoint's validity has been checked, ensure that
1225 * the property is set appropriately prior to creating the pool.
1226 */
1227 if (mountpoint != NULL) {
1228 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1229 mountpoint, &fsprops, B_FALSE);
1230 if (ret != 0)
1231 goto errout;
1232 }
1233
1234 ret = 1;
34dc7c2f
BB
1235 if (dryrun) {
1236 /*
1237 * For a dry run invocation, print out a basic message and run
1238 * through all the vdevs in the list and print out in an
1239 * appropriate hierarchy.
1240 */
1241 (void) printf(gettext("would create '%s' with the "
1242 "following layout:\n\n"), poolname);
1243
d2f3e292 1244 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE, 0);
34dc7c2f 1245 if (num_logs(nvroot) > 0)
d2f3e292 1246 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE, 0);
34dc7c2f
BB
1247
1248 ret = 0;
1249 } else {
1250 /*
1251 * Hand off to libzfs.
1252 */
e4010f27 1253 spa_feature_t i;
1254 for (i = 0; i < SPA_FEATURES; i++) {
1255 char propname[MAXPATHLEN];
1256 char *propval;
1257 zfeature_info_t *feat = &spa_feature_table[i];
9ae529ec 1258
e4010f27 1259 (void) snprintf(propname, sizeof (propname),
1260 "feature@%s", feat->fi_uname);
1261
1262 /*
1263 * Only features contained in props will be enabled:
1264 * remove from the nvlist every ZFS_FEATURE_DISABLED
1265 * value and add every missing ZFS_FEATURE_ENABLED if
1266 * enable_all_pool_feat is set.
1267 */
1268 if (!nvlist_lookup_string(props, propname, &propval)) {
1269 if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0)
1270 (void) nvlist_remove_all(props,
1271 propname);
1272 } else if (enable_all_pool_feat) {
7bc7f250
WA
1273 ret = add_prop_list(propname,
1274 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1275 if (ret != 0)
9ae529ec
CS
1276 goto errout;
1277 }
1278 }
7bc7f250
WA
1279
1280 ret = 1;
b128c09f
BB
1281 if (zpool_create(g_zfs, poolname,
1282 nvroot, props, fsprops) == 0) {
023bbe6f 1283 zfs_handle_t *pool = zfs_open(g_zfs,
1284 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
34dc7c2f 1285 if (pool != NULL) {
34dc7c2f
BB
1286 if (zfs_mount(pool, NULL, 0) == 0)
1287 ret = zfs_shareall(pool);
1288 zfs_close(pool);
1289 }
1290 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1291 (void) fprintf(stderr, gettext("pool name may have "
1292 "been omitted\n"));
1293 }
1294 }
1295
1296errout:
1297 nvlist_free(nvroot);
b128c09f 1298 nvlist_free(fsprops);
34dc7c2f
BB
1299 nvlist_free(props);
1300 return (ret);
1301badusage:
b128c09f 1302 nvlist_free(fsprops);
34dc7c2f
BB
1303 nvlist_free(props);
1304 usage(B_FALSE);
1305 return (2);
1306}
1307
1308/*
1309 * zpool destroy <pool>
1310 *
1311 * -f Forcefully unmount any datasets
1312 *
1313 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1314 */
1315int
1316zpool_do_destroy(int argc, char **argv)
1317{
1318 boolean_t force = B_FALSE;
1319 int c;
1320 char *pool;
1321 zpool_handle_t *zhp;
1322 int ret;
1323
1324 /* check options */
1325 while ((c = getopt(argc, argv, "f")) != -1) {
1326 switch (c) {
1327 case 'f':
1328 force = B_TRUE;
1329 break;
1330 case '?':
1331 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1332 optopt);
1333 usage(B_FALSE);
1334 }
1335 }
1336
1337 argc -= optind;
1338 argv += optind;
1339
1340 /* check arguments */
1341 if (argc < 1) {
1342 (void) fprintf(stderr, gettext("missing pool argument\n"));
1343 usage(B_FALSE);
1344 }
1345 if (argc > 1) {
1346 (void) fprintf(stderr, gettext("too many arguments\n"));
1347 usage(B_FALSE);
1348 }
1349
1350 pool = argv[0];
1351
1352 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1353 /*
1354 * As a special case, check for use of '/' in the name, and
1355 * direct the user to use 'zfs destroy' instead.
1356 */
1357 if (strchr(pool, '/') != NULL)
1358 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1359 "destroy a dataset\n"));
1360 return (1);
1361 }
1362
1363 if (zpool_disable_datasets(zhp, force) != 0) {
1364 (void) fprintf(stderr, gettext("could not destroy '%s': "
1365 "could not unmount datasets\n"), zpool_get_name(zhp));
a425f5bf 1366 zpool_close(zhp);
34dc7c2f
BB
1367 return (1);
1368 }
1369
6f1ffb06
MA
1370 /* The history must be logged as part of the export */
1371 log_history = B_FALSE;
1372
1373 ret = (zpool_destroy(zhp, history_str) != 0);
34dc7c2f
BB
1374
1375 zpool_close(zhp);
1376
1377 return (ret);
1378}
1379
859735c0
TF
1380typedef struct export_cbdata {
1381 boolean_t force;
1382 boolean_t hardforce;
1383} export_cbdata_t;
1384
1385/*
1386 * Export one pool
1387 */
1388int
1389zpool_export_one(zpool_handle_t *zhp, void *data)
1390{
1391 export_cbdata_t *cb = data;
1392
1393 if (zpool_disable_datasets(zhp, cb->force) != 0)
1394 return (1);
1395
1396 /* The history must be logged as part of the export */
1397 log_history = B_FALSE;
1398
1399 if (cb->hardforce) {
1400 if (zpool_export_force(zhp, history_str) != 0)
1401 return (1);
1402 } else if (zpool_export(zhp, cb->force, history_str) != 0) {
1403 return (1);
1404 }
1405
1406 return (0);
1407}
1408
34dc7c2f
BB
1409/*
1410 * zpool export [-f] <pool> ...
1411 *
859735c0 1412 * -a Export all pools
34dc7c2f
BB
1413 * -f Forcefully unmount datasets
1414 *
1415 * Export the given pools. By default, the command will attempt to cleanly
1416 * unmount any active datasets within the pool. If the '-f' flag is specified,
1417 * then the datasets will be forcefully unmounted.
1418 */
1419int
1420zpool_do_export(int argc, char **argv)
1421{
859735c0
TF
1422 export_cbdata_t cb;
1423 boolean_t do_all = B_FALSE;
34dc7c2f 1424 boolean_t force = B_FALSE;
fb5f0bc8 1425 boolean_t hardforce = B_FALSE;
859735c0 1426 int c, ret;
34dc7c2f
BB
1427
1428 /* check options */
859735c0 1429 while ((c = getopt(argc, argv, "afF")) != -1) {
34dc7c2f 1430 switch (c) {
859735c0
TF
1431 case 'a':
1432 do_all = B_TRUE;
1433 break;
34dc7c2f
BB
1434 case 'f':
1435 force = B_TRUE;
1436 break;
fb5f0bc8
BB
1437 case 'F':
1438 hardforce = B_TRUE;
1439 break;
34dc7c2f
BB
1440 case '?':
1441 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1442 optopt);
1443 usage(B_FALSE);
1444 }
1445 }
1446
859735c0
TF
1447 cb.force = force;
1448 cb.hardforce = hardforce;
34dc7c2f
BB
1449 argc -= optind;
1450 argv += optind;
1451
859735c0
TF
1452 if (do_all) {
1453 if (argc != 0) {
1454 (void) fprintf(stderr, gettext("too many arguments\n"));
1455 usage(B_FALSE);
1456 }
1457
1458 return (for_each_pool(argc, argv, B_TRUE, NULL,
1459 zpool_export_one, &cb));
1460 }
1461
34dc7c2f
BB
1462 /* check arguments */
1463 if (argc < 1) {
1464 (void) fprintf(stderr, gettext("missing pool argument\n"));
1465 usage(B_FALSE);
1466 }
1467
859735c0 1468 ret = for_each_pool(argc, argv, B_TRUE, NULL, zpool_export_one, &cb);
34dc7c2f
BB
1469
1470 return (ret);
1471}
1472
1473/*
1474 * Given a vdev configuration, determine the maximum width needed for the device
1475 * name column.
1476 */
1477static int
d2f3e292
RY
1478max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1479 int name_flags)
34dc7c2f 1480{
d2f3e292 1481 char *name;
34dc7c2f
BB
1482 nvlist_t **child;
1483 uint_t c, children;
1484 int ret;
1485
5f20c145 1486 name = zpool_vdev_name(g_zfs, zhp, nv, name_flags);
34dc7c2f
BB
1487 if (strlen(name) + depth > max)
1488 max = strlen(name) + depth;
1489
1490 free(name);
1491
1492 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1493 &child, &children) == 0) {
1494 for (c = 0; c < children; c++)
1495 if ((ret = max_width(zhp, child[c], depth + 2,
d2f3e292 1496 max, name_flags)) > max)
34dc7c2f
BB
1497 max = ret;
1498 }
1499
1500 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1501 &child, &children) == 0) {
1502 for (c = 0; c < children; c++)
1503 if ((ret = max_width(zhp, child[c], depth + 2,
d2f3e292 1504 max, name_flags)) > max)
34dc7c2f
BB
1505 max = ret;
1506 }
1507
1508 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1509 &child, &children) == 0) {
1510 for (c = 0; c < children; c++)
1511 if ((ret = max_width(zhp, child[c], depth + 2,
d2f3e292 1512 max, name_flags)) > max)
34dc7c2f
BB
1513 max = ret;
1514 }
1515
34dc7c2f
BB
1516 return (max);
1517}
1518
9babb374
BB
1519typedef struct spare_cbdata {
1520 uint64_t cb_guid;
1521 zpool_handle_t *cb_zhp;
1522} spare_cbdata_t;
1523
1524static boolean_t
1525find_vdev(nvlist_t *nv, uint64_t search)
1526{
1527 uint64_t guid;
1528 nvlist_t **child;
1529 uint_t c, children;
1530
1531 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1532 search == guid)
1533 return (B_TRUE);
1534
1535 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1536 &child, &children) == 0) {
1537 for (c = 0; c < children; c++)
1538 if (find_vdev(child[c], search))
1539 return (B_TRUE);
1540 }
1541
1542 return (B_FALSE);
1543}
1544
1545static int
1546find_spare(zpool_handle_t *zhp, void *data)
1547{
1548 spare_cbdata_t *cbp = data;
1549 nvlist_t *config, *nvroot;
1550
1551 config = zpool_get_config(zhp, NULL);
1552 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1553 &nvroot) == 0);
1554
1555 if (find_vdev(nvroot, cbp->cb_guid)) {
1556 cbp->cb_zhp = zhp;
1557 return (1);
1558 }
1559
1560 zpool_close(zhp);
1561 return (0);
1562}
1563
fea33e4e
HJ
1564typedef struct status_cbdata {
1565 int cb_count;
1566 int cb_name_flags;
1567 int cb_namewidth;
1568 boolean_t cb_allpools;
1569 boolean_t cb_verbose;
1570 boolean_t cb_explain;
1571 boolean_t cb_first;
1572 boolean_t cb_dedup_stats;
1573 boolean_t cb_print_status;
8720e9e7 1574 vdev_cmd_data_list_t *vcdl;
fea33e4e
HJ
1575} status_cbdata_t;
1576
d6418de0
TH
1577/* Return 1 if string is NULL, empty, or whitespace; return 0 otherwise. */
1578static int
1579is_blank_str(char *str)
1580{
1581 while (str != NULL && *str != '\0') {
1582 if (!isblank(*str))
1583 return (0);
1584 str++;
1585 }
1586 return (1);
1587}
1588
1589/* Print command output lines for specific vdev in a specific pool */
8720e9e7
TH
1590static void
1591zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, char *path)
1592{
d6418de0
TH
1593 vdev_cmd_data_t *data;
1594 int i, j;
1595 char *val;
1596
8720e9e7 1597 for (i = 0; i < vcdl->count; i++) {
d6418de0
TH
1598 if ((strcmp(vcdl->data[i].path, path) != 0) ||
1599 (strcmp(vcdl->data[i].pool, pool) != 0)) {
1600 /* Not the vdev we're looking for */
1601 continue;
8720e9e7 1602 }
d6418de0
TH
1603
1604 data = &vcdl->data[i];
1605 /* Print out all the output values for this vdev */
1606 for (j = 0; j < vcdl->uniq_cols_cnt; j++) {
1607 val = NULL;
1608 /* Does this vdev have values for this column? */
1609 for (int k = 0; k < data->cols_cnt; k++) {
1610 if (strcmp(data->cols[k],
1611 vcdl->uniq_cols[j]) == 0) {
1612 /* yes it does, record the value */
1613 val = data->lines[k];
1614 break;
1615 }
1616 }
1617 /*
1618 * Mark empty values with dashes to make output
1619 * awk-able.
1620 */
1621 if (is_blank_str(val))
1622 val = "-";
1623
1624 printf("%*s", vcdl->uniq_cols_width[j], val);
1625 if (j < vcdl->uniq_cols_cnt - 1)
1626 printf(" ");
1627 }
1628
1629 /* Print out any values that aren't in a column at the end */
1630 for (j = data->cols_cnt; j < data->lines_cnt; j++) {
1631 /* Did we have any columns? If so print a spacer. */
1632 if (vcdl->uniq_cols_cnt > 0)
1633 printf(" ");
1634
1635 val = data->lines[j];
1636 printf("%s", val ? val : "");
1637 }
1638 break;
8720e9e7
TH
1639 }
1640}
1641
9babb374
BB
1642/*
1643 * Print out configuration state as requested by status_callback.
1644 */
d2f3e292 1645static void
fea33e4e
HJ
1646print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
1647 nvlist_t *nv, int depth, boolean_t isspare)
9babb374
BB
1648{
1649 nvlist_t **child;
1650 uint_t c, children;
428870ff 1651 pool_scan_stat_t *ps = NULL;
9babb374 1652 vdev_stat_t *vs;
428870ff 1653 char rbuf[6], wbuf[6], cbuf[6];
9babb374
BB
1654 char *vname;
1655 uint64_t notpresent;
fea33e4e 1656 spare_cbdata_t spare_cb;
9babb374 1657 char *state;
8720e9e7 1658 char *path = NULL;
9babb374 1659
9babb374
BB
1660 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1661 &child, &children) != 0)
1662 children = 0;
1663
428870ff
BB
1664 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1665 (uint64_t **)&vs, &c) == 0);
1666
9babb374
BB
1667 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1668 if (isspare) {
1669 /*
1670 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1671 * online drives.
1672 */
1673 if (vs->vs_aux == VDEV_AUX_SPARED)
1674 state = "INUSE";
1675 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1676 state = "AVAIL";
1677 }
1678
fea33e4e 1679 (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
9babb374
BB
1680 name, state);
1681
1682 if (!isspare) {
1683 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1684 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1685 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1686 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1687 }
1688
1689 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1690 &notpresent) == 0) {
9babb374
BB
1691 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1692 (void) printf(" was %s", path);
1693 } else if (vs->vs_aux != 0) {
1694 (void) printf(" ");
1695
1696 switch (vs->vs_aux) {
1697 case VDEV_AUX_OPEN_FAILED:
1698 (void) printf(gettext("cannot open"));
1699 break;
1700
1701 case VDEV_AUX_BAD_GUID_SUM:
1702 (void) printf(gettext("missing device"));
1703 break;
1704
1705 case VDEV_AUX_NO_REPLICAS:
1706 (void) printf(gettext("insufficient replicas"));
1707 break;
1708
1709 case VDEV_AUX_VERSION_NEWER:
1710 (void) printf(gettext("newer version"));
1711 break;
1712
9ae529ec
CS
1713 case VDEV_AUX_UNSUP_FEAT:
1714 (void) printf(gettext("unsupported feature(s)"));
1715 break;
1716
9babb374
BB
1717 case VDEV_AUX_SPARED:
1718 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
fea33e4e
HJ
1719 &spare_cb.cb_guid) == 0);
1720 if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
1721 if (strcmp(zpool_get_name(spare_cb.cb_zhp),
9babb374
BB
1722 zpool_get_name(zhp)) == 0)
1723 (void) printf(gettext("currently in "
1724 "use"));
1725 else
1726 (void) printf(gettext("in use by "
1727 "pool '%s'"),
fea33e4e
HJ
1728 zpool_get_name(spare_cb.cb_zhp));
1729 zpool_close(spare_cb.cb_zhp);
9babb374
BB
1730 } else {
1731 (void) printf(gettext("currently in use"));
1732 }
1733 break;
1734
1735 case VDEV_AUX_ERR_EXCEEDED:
1736 (void) printf(gettext("too many errors"));
1737 break;
1738
1739 case VDEV_AUX_IO_FAILURE:
1740 (void) printf(gettext("experienced I/O failures"));
1741 break;
1742
1743 case VDEV_AUX_BAD_LOG:
1744 (void) printf(gettext("bad intent log"));
1745 break;
1746
428870ff
BB
1747 case VDEV_AUX_EXTERNAL:
1748 (void) printf(gettext("external device fault"));
1749 break;
1750
1751 case VDEV_AUX_SPLIT_POOL:
1752 (void) printf(gettext("split into new pool"));
1753 break;
1754
379ca9cf
OF
1755 case VDEV_AUX_ACTIVE:
1756 (void) printf(gettext("currently in use"));
4265a929 1757 break;
379ca9cf 1758
9babb374
BB
1759 default:
1760 (void) printf(gettext("corrupted data"));
1761 break;
1762 }
428870ff
BB
1763 }
1764
1765 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1766 (uint64_t **)&ps, &c);
1767
d4a72f23 1768 if (ps != NULL && ps->pss_state == DSS_SCANNING &&
428870ff
BB
1769 vs->vs_scan_processed != 0 && children == 0) {
1770 (void) printf(gettext(" (%s)"),
1771 (ps->pss_func == POOL_SCAN_RESILVER) ?
1772 "resilvering" : "repairing");
9babb374
BB
1773 }
1774
8720e9e7
TH
1775 if (cb->vcdl != NULL) {
1776 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
1777 printf(" ");
1778 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path);
1779 }
1780 }
1781
9babb374
BB
1782 (void) printf("\n");
1783
1784 for (c = 0; c < children; c++) {
428870ff 1785 uint64_t islog = B_FALSE, ishole = B_FALSE;
9babb374 1786
428870ff 1787 /* Don't print logs or holes here */
9babb374 1788 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
428870ff
BB
1789 &islog);
1790 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1791 &ishole);
1792 if (islog || ishole)
9babb374 1793 continue;
d2f3e292 1794 vname = zpool_vdev_name(g_zfs, zhp, child[c],
fea33e4e
HJ
1795 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
1796 print_status_config(zhp, cb, vname, child[c], depth + 2,
1797 isspare);
9babb374
BB
1798 free(vname);
1799 }
1800}
1801
34dc7c2f
BB
1802/*
1803 * Print the configuration of an exported pool. Iterate over all vdevs in the
1804 * pool, printing out the name and status for each one.
1805 */
d2f3e292 1806static void
fea33e4e
HJ
1807print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
1808 int depth)
34dc7c2f
BB
1809{
1810 nvlist_t **child;
1811 uint_t c, children;
1812 vdev_stat_t *vs;
1813 char *type, *vname;
1814
1815 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
428870ff
BB
1816 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1817 strcmp(type, VDEV_TYPE_HOLE) == 0)
34dc7c2f
BB
1818 return;
1819
428870ff 1820 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
1821 (uint64_t **)&vs, &c) == 0);
1822
fea33e4e 1823 (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
34dc7c2f
BB
1824 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1825
1826 if (vs->vs_aux != 0) {
1827 (void) printf(" ");
1828
1829 switch (vs->vs_aux) {
1830 case VDEV_AUX_OPEN_FAILED:
1831 (void) printf(gettext("cannot open"));
1832 break;
1833
1834 case VDEV_AUX_BAD_GUID_SUM:
1835 (void) printf(gettext("missing device"));
1836 break;
1837
1838 case VDEV_AUX_NO_REPLICAS:
1839 (void) printf(gettext("insufficient replicas"));
1840 break;
1841
1842 case VDEV_AUX_VERSION_NEWER:
1843 (void) printf(gettext("newer version"));
1844 break;
1845
9ae529ec
CS
1846 case VDEV_AUX_UNSUP_FEAT:
1847 (void) printf(gettext("unsupported feature(s)"));
1848 break;
1849
34dc7c2f
BB
1850 case VDEV_AUX_ERR_EXCEEDED:
1851 (void) printf(gettext("too many errors"));
1852 break;
1853
379ca9cf
OF
1854 case VDEV_AUX_ACTIVE:
1855 (void) printf(gettext("currently in use"));
1856 break;
1857
34dc7c2f
BB
1858 default:
1859 (void) printf(gettext("corrupted data"));
1860 break;
1861 }
1862 }
1863 (void) printf("\n");
1864
1865 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1866 &child, &children) != 0)
1867 return;
1868
1869 for (c = 0; c < children; c++) {
1870 uint64_t is_log = B_FALSE;
1871
1872 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1873 &is_log);
9babb374 1874 if (is_log)
34dc7c2f
BB
1875 continue;
1876
d2f3e292 1877 vname = zpool_vdev_name(g_zfs, NULL, child[c],
fea33e4e
HJ
1878 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
1879 print_import_config(cb, vname, child[c], depth + 2);
34dc7c2f
BB
1880 free(vname);
1881 }
1882
1883 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1884 &child, &children) == 0) {
1885 (void) printf(gettext("\tcache\n"));
1886 for (c = 0; c < children; c++) {
d2f3e292 1887 vname = zpool_vdev_name(g_zfs, NULL, child[c],
fea33e4e 1888 cb->cb_name_flags);
34dc7c2f
BB
1889 (void) printf("\t %s\n", vname);
1890 free(vname);
1891 }
1892 }
1893
1894 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1895 &child, &children) == 0) {
1896 (void) printf(gettext("\tspares\n"));
1897 for (c = 0; c < children; c++) {
d2f3e292 1898 vname = zpool_vdev_name(g_zfs, NULL, child[c],
fea33e4e 1899 cb->cb_name_flags);
34dc7c2f
BB
1900 (void) printf("\t %s\n", vname);
1901 free(vname);
1902 }
1903 }
1904}
1905
9babb374
BB
1906/*
1907 * Print log vdevs.
1908 * Logs are recorded as top level vdevs in the main pool child array
1909 * but with "is_log" set to 1. We use either print_status_config() or
1910 * print_import_config() to print the top level logs then any log
1911 * children (eg mirrored slogs) are printed recursively - which
1912 * works because only the top level vdev is marked "is_log"
1913 */
1914static void
fea33e4e 1915print_logs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv)
9babb374
BB
1916{
1917 uint_t c, children;
1918 nvlist_t **child;
1919
1920 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1921 &children) != 0)
1922 return;
1923
1924 (void) printf(gettext("\tlogs\n"));
1925
1926 for (c = 0; c < children; c++) {
1927 uint64_t is_log = B_FALSE;
1928 char *name;
1929
1930 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1931 &is_log);
1932 if (!is_log)
1933 continue;
d2f3e292 1934 name = zpool_vdev_name(g_zfs, zhp, child[c],
fea33e4e
HJ
1935 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
1936 if (cb->cb_print_status)
1937 print_status_config(zhp, cb, name, child[c], 2,
1938 B_FALSE);
9babb374 1939 else
fea33e4e 1940 print_import_config(cb, name, child[c], 2);
9babb374
BB
1941 free(name);
1942 }
1943}
428870ff 1944
34dc7c2f
BB
1945/*
1946 * Display the status for the given pool.
1947 */
1948static void
1949show_import(nvlist_t *config)
1950{
1951 uint64_t pool_state;
1952 vdev_stat_t *vs;
1953 char *name;
1954 uint64_t guid;
379ca9cf 1955 uint64_t hostid = 0;
34dc7c2f 1956 char *msgid;
379ca9cf
OF
1957 char *hostname = "unknown";
1958 nvlist_t *nvroot, *nvinfo;
731782ec 1959 zpool_status_t reason;
ffe9d382 1960 zpool_errata_t errata;
34dc7c2f
BB
1961 const char *health;
1962 uint_t vsc;
d96eb2b1 1963 char *comment;
fea33e4e 1964 status_cbdata_t cb = { 0 };
34dc7c2f
BB
1965
1966 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1967 &name) == 0);
1968 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1969 &guid) == 0);
1970 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1971 &pool_state) == 0);
1972 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1973 &nvroot) == 0);
1974
428870ff 1975 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
1976 (uint64_t **)&vs, &vsc) == 0);
1977 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1978
ffe9d382 1979 reason = zpool_import_status(config, &msgid, &errata);
34dc7c2f 1980
d96eb2b1
DM
1981 (void) printf(gettext(" pool: %s\n"), name);
1982 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1983 (void) printf(gettext(" state: %s"), health);
34dc7c2f
BB
1984 if (pool_state == POOL_STATE_DESTROYED)
1985 (void) printf(gettext(" (DESTROYED)"));
1986 (void) printf("\n");
1987
1988 switch (reason) {
1989 case ZPOOL_STATUS_MISSING_DEV_R:
1990 case ZPOOL_STATUS_MISSING_DEV_NR:
1991 case ZPOOL_STATUS_BAD_GUID_SUM:
d96eb2b1
DM
1992 (void) printf(gettext(" status: One or more devices are "
1993 "missing from the system.\n"));
34dc7c2f
BB
1994 break;
1995
1996 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1997 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
d96eb2b1 1998 (void) printf(gettext(" status: One or more devices contains "
34dc7c2f
BB
1999 "corrupted data.\n"));
2000 break;
2001
2002 case ZPOOL_STATUS_CORRUPT_DATA:
d96eb2b1
DM
2003 (void) printf(
2004 gettext(" status: The pool data is corrupted.\n"));
34dc7c2f
BB
2005 break;
2006
2007 case ZPOOL_STATUS_OFFLINE_DEV:
d96eb2b1 2008 (void) printf(gettext(" status: One or more devices "
34dc7c2f
BB
2009 "are offlined.\n"));
2010 break;
2011
2012 case ZPOOL_STATUS_CORRUPT_POOL:
d96eb2b1 2013 (void) printf(gettext(" status: The pool metadata is "
34dc7c2f
BB
2014 "corrupted.\n"));
2015 break;
2016
2017 case ZPOOL_STATUS_VERSION_OLDER:
b9b24bb4
CS
2018 (void) printf(gettext(" status: The pool is formatted using a "
2019 "legacy on-disk version.\n"));
34dc7c2f
BB
2020 break;
2021
2022 case ZPOOL_STATUS_VERSION_NEWER:
d96eb2b1 2023 (void) printf(gettext(" status: The pool is formatted using an "
34dc7c2f
BB
2024 "incompatible version.\n"));
2025 break;
b128c09f 2026
b9b24bb4
CS
2027 case ZPOOL_STATUS_FEAT_DISABLED:
2028 (void) printf(gettext(" status: Some supported features are "
2029 "not enabled on the pool.\n"));
2030 break;
2031
9ae529ec
CS
2032 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2033 (void) printf(gettext("status: The pool uses the following "
4e33ba4c 2034 "feature(s) not supported on this system:\n"));
9ae529ec
CS
2035 zpool_print_unsup_feat(config);
2036 break;
2037
2038 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2039 (void) printf(gettext("status: The pool can only be accessed "
2040 "in read-only mode on this system. It\n\tcannot be "
2041 "accessed in read-write mode because it uses the "
2042 "following\n\tfeature(s) not supported on this system:\n"));
2043 zpool_print_unsup_feat(config);
2044 break;
2045
379ca9cf
OF
2046 case ZPOOL_STATUS_HOSTID_ACTIVE:
2047 (void) printf(gettext(" status: The pool is currently "
2048 "imported by another system.\n"));
2049 break;
2050
2051 case ZPOOL_STATUS_HOSTID_REQUIRED:
2052 (void) printf(gettext(" status: The pool has the "
2053 "multihost property on. It cannot\n\tbe safely imported "
2054 "when the system hostid is not set.\n"));
2055 break;
2056
34dc7c2f 2057 case ZPOOL_STATUS_HOSTID_MISMATCH:
d96eb2b1 2058 (void) printf(gettext(" status: The pool was last accessed by "
34dc7c2f
BB
2059 "another system.\n"));
2060 break;
b128c09f 2061
34dc7c2f
BB
2062 case ZPOOL_STATUS_FAULTED_DEV_R:
2063 case ZPOOL_STATUS_FAULTED_DEV_NR:
d96eb2b1 2064 (void) printf(gettext(" status: One or more devices are "
34dc7c2f
BB
2065 "faulted.\n"));
2066 break;
2067
b128c09f 2068 case ZPOOL_STATUS_BAD_LOG:
d96eb2b1 2069 (void) printf(gettext(" status: An intent log record cannot be "
b128c09f
BB
2070 "read.\n"));
2071 break;
2072
428870ff 2073 case ZPOOL_STATUS_RESILVERING:
d96eb2b1 2074 (void) printf(gettext(" status: One or more devices were being "
428870ff
BB
2075 "resilvered.\n"));
2076 break;
2077
ffe9d382
BB
2078 case ZPOOL_STATUS_ERRATA:
2079 (void) printf(gettext(" status: Errata #%d detected.\n"),
2080 errata);
2081 break;
2082
34dc7c2f
BB
2083 default:
2084 /*
2085 * No other status can be seen when importing pools.
2086 */
2087 assert(reason == ZPOOL_STATUS_OK);
2088 }
2089
2090 /*
2091 * Print out an action according to the overall state of the pool.
2092 */
2093 if (vs->vs_state == VDEV_STATE_HEALTHY) {
b9b24bb4
CS
2094 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2095 reason == ZPOOL_STATUS_FEAT_DISABLED) {
d96eb2b1 2096 (void) printf(gettext(" action: The pool can be "
34dc7c2f
BB
2097 "imported using its name or numeric identifier, "
2098 "though\n\tsome features will not be available "
2099 "without an explicit 'zpool upgrade'.\n"));
b9b24bb4 2100 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
d96eb2b1 2101 (void) printf(gettext(" action: The pool can be "
34dc7c2f
BB
2102 "imported using its name or numeric "
2103 "identifier and\n\tthe '-f' flag.\n"));
ffe9d382
BB
2104 } else if (reason == ZPOOL_STATUS_ERRATA) {
2105 switch (errata) {
2106 case ZPOOL_ERRATA_NONE:
2107 break;
2108
4f2dcb3e
RY
2109 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
2110 (void) printf(gettext(" action: The pool can "
2111 "be imported using its name or numeric "
2112 "identifier,\n\thowever there is a compat"
2113 "ibility issue which should be corrected"
2114 "\n\tby running 'zpool scrub'\n"));
2115 break;
2116
2117 case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
2118 (void) printf(gettext(" action: The pool can"
2119 "not be imported with this version of ZFS "
2120 "due to\n\tan active asynchronous destroy. "
2121 "Revert to an earlier version\n\tand "
2122 "allow the destroy to complete before "
2123 "updating.\n"));
2124 break;
2125
ae76f45c
TC
2126 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
2127 (void) printf(gettext(" action: Existing "
2128 "encrypted datasets contain an on-disk "
2129 "incompatibility, which\n\tneeds to be "
2130 "corrected. Backup these datasets to new "
2131 "encrypted datasets\n\tand destroy the "
2132 "old ones.\n"));
2133 break;
2134
ffe9d382
BB
2135 default:
2136 /*
2137 * All errata must contain an action message.
2138 */
2139 assert(0);
2140 }
b9b24bb4 2141 } else {
d96eb2b1 2142 (void) printf(gettext(" action: The pool can be "
34dc7c2f
BB
2143 "imported using its name or numeric "
2144 "identifier.\n"));
b9b24bb4 2145 }
34dc7c2f 2146 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
d96eb2b1 2147 (void) printf(gettext(" action: The pool can be imported "
34dc7c2f
BB
2148 "despite missing or damaged devices. The\n\tfault "
2149 "tolerance of the pool may be compromised if imported.\n"));
2150 } else {
2151 switch (reason) {
2152 case ZPOOL_STATUS_VERSION_NEWER:
d96eb2b1 2153 (void) printf(gettext(" action: The pool cannot be "
34dc7c2f
BB
2154 "imported. Access the pool on a system running "
2155 "newer\n\tsoftware, or recreate the pool from "
2156 "backup.\n"));
2157 break;
9ae529ec
CS
2158 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2159 (void) printf(gettext("action: The pool cannot be "
2160 "imported. Access the pool on a system that "
2161 "supports\n\tthe required feature(s), or recreate "
2162 "the pool from backup.\n"));
2163 break;
2164 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2165 (void) printf(gettext("action: The pool cannot be "
2166 "imported in read-write mode. Import the pool "
2167 "with\n"
2168 "\t\"-o readonly=on\", access the pool on a system "
2169 "that supports the\n\trequired feature(s), or "
2170 "recreate the pool from backup.\n"));
2171 break;
34dc7c2f
BB
2172 case ZPOOL_STATUS_MISSING_DEV_R:
2173 case ZPOOL_STATUS_MISSING_DEV_NR:
2174 case ZPOOL_STATUS_BAD_GUID_SUM:
d96eb2b1 2175 (void) printf(gettext(" action: The pool cannot be "
34dc7c2f
BB
2176 "imported. Attach the missing\n\tdevices and try "
2177 "again.\n"));
2178 break;
379ca9cf
OF
2179 case ZPOOL_STATUS_HOSTID_ACTIVE:
2180 VERIFY0(nvlist_lookup_nvlist(config,
2181 ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
2182
2183 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2184 hostname = fnvlist_lookup_string(nvinfo,
2185 ZPOOL_CONFIG_MMP_HOSTNAME);
2186
2187 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2188 hostid = fnvlist_lookup_uint64(nvinfo,
2189 ZPOOL_CONFIG_MMP_HOSTID);
2190
2191 (void) printf(gettext(" action: The pool must be "
2192 "exported from %s (hostid=%lx)\n\tbefore it "
2193 "can be safely imported.\n"), hostname,
2194 (unsigned long) hostid);
2195 break;
2196 case ZPOOL_STATUS_HOSTID_REQUIRED:
2197 (void) printf(gettext(" action: Set a unique system "
b9373170 2198 "hostid with the zgenhostid(8) command.\n"));
379ca9cf 2199 break;
34dc7c2f 2200 default:
d96eb2b1 2201 (void) printf(gettext(" action: The pool cannot be "
34dc7c2f
BB
2202 "imported due to damaged devices or data.\n"));
2203 }
2204 }
2205
d96eb2b1
DM
2206 /* Print the comment attached to the pool. */
2207 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2208 (void) printf(gettext("comment: %s\n"), comment);
2209
34dc7c2f
BB
2210 /*
2211 * If the state is "closed" or "can't open", and the aux state
2212 * is "corrupt data":
2213 */
2214 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2215 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2216 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2217 if (pool_state == POOL_STATE_DESTROYED)
2218 (void) printf(gettext("\tThe pool was destroyed, "
2219 "but can be imported using the '-Df' flags.\n"));
2220 else if (pool_state != POOL_STATE_EXPORTED)
2221 (void) printf(gettext("\tThe pool may be active on "
2222 "another system, but can be imported using\n\t"
2223 "the '-f' flag.\n"));
2224 }
2225
2226 if (msgid != NULL)
3cee2262 2227 (void) printf(gettext(" see: http://zfsonlinux.org/msg/%s\n"),
34dc7c2f
BB
2228 msgid);
2229
d96eb2b1 2230 (void) printf(gettext(" config:\n\n"));
34dc7c2f 2231
2df9ad1c
GG
2232 cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
2233 VDEV_NAME_TYPE_ID);
fea33e4e
HJ
2234 if (cb.cb_namewidth < 10)
2235 cb.cb_namewidth = 10;
34dc7c2f 2236
fea33e4e 2237 print_import_config(&cb, name, nvroot, 0);
9babb374 2238 if (num_logs(nvroot) > 0)
fea33e4e 2239 print_logs(NULL, &cb, nvroot);
34dc7c2f
BB
2240
2241 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2242 (void) printf(gettext("\n\tAdditional devices are known to "
2243 "be part of this pool, though their\n\texact "
2244 "configuration cannot be determined.\n"));
2245 }
2246}
2247
379ca9cf
OF
2248static boolean_t
2249zfs_force_import_required(nvlist_t *config)
2250{
2251 uint64_t state;
2252 uint64_t hostid = 0;
2253 nvlist_t *nvinfo;
2254
2255 state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
2256 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
2257
2258 if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
2259 return (B_TRUE);
2260
2261 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2262 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
2263 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
2264 ZPOOL_CONFIG_MMP_STATE);
2265
2266 if (mmp_state != MMP_STATE_INACTIVE)
2267 return (B_TRUE);
2268 }
2269
2270 return (B_FALSE);
2271}
2272
34dc7c2f
BB
2273/*
2274 * Perform the import for the given configuration. This passes the heavy
2275 * lifting off to zpool_import_props(), and then mounts the datasets contained
2276 * within the pool.
2277 */
2278static int
2279do_import(nvlist_t *config, const char *newname, const char *mntopts,
572e2857 2280 nvlist_t *props, int flags)
34dc7c2f 2281{
b5256303 2282 int ret = 0;
34dc7c2f
BB
2283 zpool_handle_t *zhp;
2284 char *name;
34dc7c2f 2285 uint64_t version;
34dc7c2f 2286
379ca9cf 2287 name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
379ca9cf 2288 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
34dc7c2f 2289
9ae529ec 2290 if (!SPA_VERSION_IS_SUPPORTED(version)) {
34dc7c2f 2291 (void) fprintf(stderr, gettext("cannot import '%s': pool "
9ae529ec 2292 "is formatted using an unsupported ZFS version\n"), name);
34dc7c2f 2293 return (1);
379ca9cf 2294 } else if (zfs_force_import_required(config) &&
572e2857 2295 !(flags & ZFS_IMPORT_ANY_HOST)) {
379ca9cf
OF
2296 mmp_state_t mmp_state = MMP_STATE_INACTIVE;
2297 nvlist_t *nvinfo;
2298
2299 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2300 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
2301 mmp_state = fnvlist_lookup_uint64(nvinfo,
2302 ZPOOL_CONFIG_MMP_STATE);
2303
2304 if (mmp_state == MMP_STATE_ACTIVE) {
2305 char *hostname = "<unknown>";
2306 uint64_t hostid = 0;
2307
2308 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2309 hostname = fnvlist_lookup_string(nvinfo,
2310 ZPOOL_CONFIG_MMP_HOSTNAME);
2311
2312 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2313 hostid = fnvlist_lookup_uint64(nvinfo,
2314 ZPOOL_CONFIG_MMP_HOSTID);
2315
2316 (void) fprintf(stderr, gettext("cannot import '%s': "
2317 "pool is imported on %s (hostid: "
2318 "0x%lx)\nExport the pool on the other system, "
2319 "then run 'zpool import'.\n"),
2320 name, hostname, (unsigned long) hostid);
2321 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2322 (void) fprintf(stderr, gettext("Cannot import '%s': "
2323 "pool has the multihost property on and the\n"
2324 "system's hostid is not set. Set a unique hostid "
b9373170 2325 "with the zgenhostid(8) command.\n"), name);
379ca9cf
OF
2326 } else {
2327 char *hostname = "<unknown>";
2328 uint64_t timestamp = 0;
2329 uint64_t hostid = 0;
2330
2331 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
2332 hostname = fnvlist_lookup_string(config,
2333 ZPOOL_CONFIG_HOSTNAME);
2334
2335 if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
2336 timestamp = fnvlist_lookup_uint64(config,
2337 ZPOOL_CONFIG_TIMESTAMP);
2338
2339 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
2340 hostid = fnvlist_lookup_uint64(config,
2341 ZPOOL_CONFIG_HOSTID);
2342
2343 (void) fprintf(stderr, gettext("cannot import '%s': "
2344 "pool was previously in use from another system.\n"
2345 "Last accessed by %s (hostid=%lx) at %s"
2346 "The pool can be imported, use 'zpool import -f' "
2347 "to import the pool.\n"), name, hostname,
2348 (unsigned long)hostid, ctime((time_t *)&timestamp));
34dc7c2f 2349 }
379ca9cf
OF
2350
2351 return (1);
34dc7c2f
BB
2352 }
2353
572e2857 2354 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
34dc7c2f
BB
2355 return (1);
2356
2357 if (newname != NULL)
2358 name = (char *)newname;
2359
45d1cae3
BB
2360 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2361 return (1);
34dc7c2f 2362
b5256303
TC
2363 /*
2364 * Loading keys is best effort. We don't want to return immediately
2365 * if it fails but we do want to give the error to the caller.
2366 */
2367 if (flags & ZFS_IMPORT_LOAD_KEYS) {
2368 ret = zfs_crypto_attempt_load_keys(g_zfs, name);
2369 if (ret != 0)
2370 ret = 1;
2371 }
2372
d164b209 2373 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
572e2857 2374 !(flags & ZFS_IMPORT_ONLY) &&
d164b209 2375 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
34dc7c2f
BB
2376 zpool_close(zhp);
2377 return (1);
2378 }
2379
2380 zpool_close(zhp);
b5256303 2381 return (ret);
34dc7c2f
BB
2382}
2383
2384/*
2385 * zpool import [-d dir] [-D]
b5256303 2386 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
34dc7c2f 2387 * [-d dir | -c cachefile] [-f] -a
b5256303 2388 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
428870ff 2389 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
34dc7c2f
BB
2390 *
2391 * -c Read pool information from a cachefile instead of searching
2392 * devices.
2393 *
d603ed6c 2394 * -d Scan in a specific directory, other than /dev/. More than
34dc7c2f
BB
2395 * one directory can be specified using multiple '-d' options.
2396 *
2397 * -D Scan for previously destroyed pools or import all or only
2398 * specified destroyed pools.
2399 *
2400 * -R Temporarily import the pool, with all mountpoints relative to
2401 * the given root. The pool will remain exported when the machine
2402 * is rebooted.
2403 *
428870ff 2404 * -V Import even in the presence of faulted vdevs. This is an
b128c09f
BB
2405 * intentionally undocumented option for testing purposes, and
2406 * treats the pool configuration as complete, leaving any bad
45d1cae3
BB
2407 * vdevs in the FAULTED state. In other words, it does verbatim
2408 * import.
b128c09f 2409 *
428870ff
BB
2410 * -f Force import, even if it appears that the pool is active.
2411 *
2412 * -F Attempt rewind if necessary.
2413 *
2414 * -n See if rewind would work, but don't actually rewind.
2415 *
572e2857
BB
2416 * -N Import the pool but don't mount datasets.
2417 *
2418 * -T Specify a starting txg to use for import. This option is
2419 * intentionally undocumented option for testing purposes.
2420 *
34dc7c2f
BB
2421 * -a Import all pools found.
2422 *
b5256303
TC
2423 * -l Load encryption keys while importing.
2424 *
34dc7c2f
BB
2425 * -o Set property=value and/or temporary mount options (without '=').
2426 *
7d11e37e
BB
2427 * -s Scan using the default search path, the libblkid cache will
2428 * not be consulted.
2429 *
34dc7c2f
BB
2430 * The import command scans for pools to import, and import pools based on pool
2431 * name and GUID. The pool can also be renamed as part of the import process.
2432 */
2433int
2434zpool_do_import(int argc, char **argv)
2435{
2436 char **searchdirs = NULL;
44867b6d 2437 char *env, *envdup = NULL;
34dc7c2f
BB
2438 int nsearch = 0;
2439 int c;
428870ff 2440 int err = 0;
34dc7c2f
BB
2441 nvlist_t *pools = NULL;
2442 boolean_t do_all = B_FALSE;
2443 boolean_t do_destroyed = B_FALSE;
2444 char *mntopts = NULL;
34dc7c2f
BB
2445 nvpair_t *elem;
2446 nvlist_t *config;
b128c09f
BB
2447 uint64_t searchguid = 0;
2448 char *searchname = NULL;
34dc7c2f
BB
2449 char *propval;
2450 nvlist_t *found_config;
428870ff 2451 nvlist_t *policy = NULL;
34dc7c2f
BB
2452 nvlist_t *props = NULL;
2453 boolean_t first;
572e2857 2454 int flags = ZFS_IMPORT_NORMAL;
428870ff
BB
2455 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2456 boolean_t dryrun = B_FALSE;
2457 boolean_t do_rewind = B_FALSE;
2458 boolean_t xtreme_rewind = B_FALSE;
7d11e37e 2459 boolean_t do_scan = B_FALSE;
572e2857 2460 uint64_t pool_state, txg = -1ULL;
34dc7c2f 2461 char *cachefile = NULL;
428870ff 2462 importargs_t idata = { 0 };
572e2857 2463 char *endptr;
34dc7c2f
BB
2464
2465 /* check options */
b5256303 2466 while ((c = getopt(argc, argv, ":aCc:d:DEfFlmnNo:R:stT:VX")) != -1) {
34dc7c2f
BB
2467 switch (c) {
2468 case 'a':
2469 do_all = B_TRUE;
2470 break;
2471 case 'c':
2472 cachefile = optarg;
2473 break;
2474 case 'd':
2475 if (searchdirs == NULL) {
2476 searchdirs = safe_malloc(sizeof (char *));
2477 } else {
2478 char **tmp = safe_malloc((nsearch + 1) *
2479 sizeof (char *));
2480 bcopy(searchdirs, tmp, nsearch *
2481 sizeof (char *));
2482 free(searchdirs);
2483 searchdirs = tmp;
2484 }
2485 searchdirs[nsearch++] = optarg;
2486 break;
2487 case 'D':
2488 do_destroyed = B_TRUE;
2489 break;
2490 case 'f':
572e2857 2491 flags |= ZFS_IMPORT_ANY_HOST;
34dc7c2f 2492 break;
b128c09f 2493 case 'F':
428870ff
BB
2494 do_rewind = B_TRUE;
2495 break;
b5256303
TC
2496 case 'l':
2497 flags |= ZFS_IMPORT_LOAD_KEYS;
2498 break;
572e2857
BB
2499 case 'm':
2500 flags |= ZFS_IMPORT_MISSING_LOG;
2501 break;
428870ff
BB
2502 case 'n':
2503 dryrun = B_TRUE;
b128c09f 2504 break;
572e2857
BB
2505 case 'N':
2506 flags |= ZFS_IMPORT_ONLY;
2507 break;
34dc7c2f
BB
2508 case 'o':
2509 if ((propval = strchr(optarg, '=')) != NULL) {
2510 *propval = '\0';
2511 propval++;
b128c09f
BB
2512 if (add_prop_list(optarg, propval,
2513 &props, B_TRUE))
34dc7c2f
BB
2514 goto error;
2515 } else {
2516 mntopts = optarg;
2517 }
2518 break;
2519 case 'R':
2520 if (add_prop_list(zpool_prop_to_name(
b128c09f 2521 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
34dc7c2f 2522 goto error;
2f3ec900 2523 if (add_prop_list_default(zpool_prop_to_name(
b128c09f 2524 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
34dc7c2f
BB
2525 goto error;
2526 break;
7d11e37e
BB
2527 case 's':
2528 do_scan = B_TRUE;
2529 break;
26b42f3f
RY
2530 case 't':
2531 flags |= ZFS_IMPORT_TEMP_NAME;
00d2a8c9
RY
2532 if (add_prop_list_default(zpool_prop_to_name(
2533 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2534 goto error;
26b42f3f
RY
2535 break;
2536
572e2857
BB
2537 case 'T':
2538 errno = 0;
dea377c0 2539 txg = strtoull(optarg, &endptr, 0);
572e2857
BB
2540 if (errno != 0 || *endptr != '\0') {
2541 (void) fprintf(stderr,
2542 gettext("invalid txg value\n"));
2543 usage(B_FALSE);
2544 }
2545 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2546 break;
428870ff 2547 case 'V':
572e2857 2548 flags |= ZFS_IMPORT_VERBATIM;
428870ff
BB
2549 break;
2550 case 'X':
2551 xtreme_rewind = B_TRUE;
2552 break;
34dc7c2f
BB
2553 case ':':
2554 (void) fprintf(stderr, gettext("missing argument for "
2555 "'%c' option\n"), optopt);
2556 usage(B_FALSE);
2557 break;
2558 case '?':
2559 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2560 optopt);
2561 usage(B_FALSE);
2562 }
2563 }
2564
2565 argc -= optind;
2566 argv += optind;
2567
2568 if (cachefile && nsearch != 0) {
2569 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2570 usage(B_FALSE);
2571 }
2572
b5256303
TC
2573 if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
2574 (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
2575 usage(B_FALSE);
2576 }
2577
2578 if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
2579 (void) fprintf(stderr, gettext("-l is only meaningful during "
2580 "an import\n"));
2581 usage(B_FALSE);
2582 }
2583
428870ff
BB
2584 if ((dryrun || xtreme_rewind) && !do_rewind) {
2585 (void) fprintf(stderr,
2586 gettext("-n or -X only meaningful with -F\n"));
2587 usage(B_FALSE);
2588 }
2589 if (dryrun)
2590 rewind_policy = ZPOOL_TRY_REWIND;
2591 else if (do_rewind)
2592 rewind_policy = ZPOOL_DO_REWIND;
2593 if (xtreme_rewind)
2594 rewind_policy |= ZPOOL_EXTREME_REWIND;
2595
2596 /* In the future, we can capture further policy and include it here */
2597 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
572e2857 2598 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
428870ff
BB
2599 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2600 goto error;
2601
34dc7c2f
BB
2602 /* check argument count */
2603 if (do_all) {
2604 if (argc != 0) {
2605 (void) fprintf(stderr, gettext("too many arguments\n"));
2606 usage(B_FALSE);
2607 }
2608 } else {
2609 if (argc > 2) {
2610 (void) fprintf(stderr, gettext("too many arguments\n"));
2611 usage(B_FALSE);
2612 }
f74b821a 2613 }
34dc7c2f 2614
f74b821a
BB
2615 /*
2616 * Check for the effective uid. We do this explicitly here because
2617 * otherwise any attempt to discover pools will silently fail.
2618 */
2619 if (argc == 0 && geteuid() != 0) {
2620 (void) fprintf(stderr, gettext("cannot "
2621 "discover pools: permission denied\n"));
2622 if (searchdirs != NULL)
2623 free(searchdirs);
d603ed6c 2624
a425f5bf 2625 nvlist_free(props);
f74b821a
BB
2626 nvlist_free(policy);
2627 return (1);
34dc7c2f
BB
2628 }
2629
34dc7c2f 2630 /*
34dc7c2f
BB
2631 * Depending on the arguments given, we do one of the following:
2632 *
2633 * <none> Iterate through all pools and display information about
2634 * each one.
2635 *
2636 * -a Iterate through all pools and try to import each one.
2637 *
2638 * <id> Find the pool that corresponds to the given GUID/pool
2639 * name and import that one.
2640 *
2641 * -D Above options applies only to destroyed pools.
2642 */
2643 if (argc != 0) {
2644 char *endptr;
2645
2646 errno = 0;
2647 searchguid = strtoull(argv[0], &endptr, 10);
eaa52d32 2648 if (errno != 0 || *endptr != '\0') {
34dc7c2f 2649 searchname = argv[0];
eaa52d32
PJ
2650 searchguid = 0;
2651 }
34dc7c2f 2652 found_config = NULL;
34dc7c2f 2653
b128c09f 2654 /*
428870ff 2655 * User specified a name or guid. Ensure it's unique.
b128c09f 2656 */
428870ff 2657 idata.unique = B_TRUE;
b128c09f
BB
2658 }
2659
44867b6d
BB
2660 /*
2661 * Check the environment for the preferred search path.
2662 */
2663 if ((searchdirs == NULL) && (env = getenv("ZPOOL_IMPORT_PATH"))) {
2664 char *dir;
2665
2666 envdup = strdup(env);
2667
2668 dir = strtok(envdup, ":");
2669 while (dir != NULL) {
2670 if (searchdirs == NULL) {
2671 searchdirs = safe_malloc(sizeof (char *));
2672 } else {
2673 char **tmp = safe_malloc((nsearch + 1) *
2674 sizeof (char *));
2675 bcopy(searchdirs, tmp, nsearch *
2676 sizeof (char *));
2677 free(searchdirs);
2678 searchdirs = tmp;
2679 }
2680 searchdirs[nsearch++] = dir;
2681 dir = strtok(NULL, ":");
2682 }
2683 }
428870ff
BB
2684
2685 idata.path = searchdirs;
2686 idata.paths = nsearch;
2687 idata.poolname = searchname;
2688 idata.guid = searchguid;
2689 idata.cachefile = cachefile;
7d11e37e 2690 idata.scan = do_scan;
428870ff
BB
2691
2692 pools = zpool_search_import(g_zfs, &idata);
2693
2694 if (pools != NULL && idata.exists &&
2695 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2696 (void) fprintf(stderr, gettext("cannot import '%s': "
2697 "a pool with that name already exists\n"),
2698 argv[0]);
2699 (void) fprintf(stderr, gettext("use the form '%s "
2700 "<pool | id> <newpool>' to give it a new name\n"),
2701 "zpool import");
2702 err = 1;
2703 } else if (pools == NULL && idata.exists) {
2704 (void) fprintf(stderr, gettext("cannot import '%s': "
2705 "a pool with that name is already created/imported,\n"),
2706 argv[0]);
2707 (void) fprintf(stderr, gettext("and no additional pools "
2708 "with that name were found\n"));
2709 err = 1;
2710 } else if (pools == NULL) {
b128c09f
BB
2711 if (argc != 0) {
2712 (void) fprintf(stderr, gettext("cannot import '%s': "
2713 "no such pool available\n"), argv[0]);
2714 }
428870ff
BB
2715 err = 1;
2716 }
2717
2718 if (err == 1) {
d603ed6c
BB
2719 if (searchdirs != NULL)
2720 free(searchdirs);
44867b6d
BB
2721 if (envdup != NULL)
2722 free(envdup);
428870ff 2723 nvlist_free(policy);
a425f5bf 2724 nvlist_free(pools);
2725 nvlist_free(props);
b128c09f
BB
2726 return (1);
2727 }
2728
2729 /*
2730 * At this point we have a list of import candidate configs. Even if
2731 * we were searching by pool name or guid, we still need to
2732 * post-process the list to deal with pool state and possible
2733 * duplicate names.
2734 */
34dc7c2f
BB
2735 err = 0;
2736 elem = NULL;
2737 first = B_TRUE;
2738 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2739
2740 verify(nvpair_value_nvlist(elem, &config) == 0);
2741
2742 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2743 &pool_state) == 0);
2744 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2745 continue;
2746 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2747 continue;
2748
428870ff
BB
2749 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2750 policy) == 0);
2751
34dc7c2f
BB
2752 if (argc == 0) {
2753 if (first)
2754 first = B_FALSE;
2755 else if (!do_all)
2756 (void) printf("\n");
2757
428870ff 2758 if (do_all) {
34dc7c2f 2759 err |= do_import(config, NULL, mntopts,
572e2857 2760 props, flags);
428870ff 2761 } else {
34dc7c2f 2762 show_import(config);
428870ff 2763 }
34dc7c2f
BB
2764 } else if (searchname != NULL) {
2765 char *name;
2766
2767 /*
2768 * We are searching for a pool based on name.
2769 */
2770 verify(nvlist_lookup_string(config,
2771 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2772
2773 if (strcmp(name, searchname) == 0) {
2774 if (found_config != NULL) {
2775 (void) fprintf(stderr, gettext(
2776 "cannot import '%s': more than "
2777 "one matching pool\n"), searchname);
2778 (void) fprintf(stderr, gettext(
2779 "import by numeric ID instead\n"));
2780 err = B_TRUE;
2781 }
2782 found_config = config;
2783 }
2784 } else {
2785 uint64_t guid;
2786
2787 /*
2788 * Search for a pool by guid.
2789 */
2790 verify(nvlist_lookup_uint64(config,
2791 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2792
2793 if (guid == searchguid)
2794 found_config = config;
2795 }
2796 }
2797
2798 /*
2799 * If we were searching for a specific pool, verify that we found a
2800 * pool, and then do the import.
2801 */
2802 if (argc != 0 && err == 0) {
2803 if (found_config == NULL) {
2804 (void) fprintf(stderr, gettext("cannot import '%s': "
2805 "no such pool available\n"), argv[0]);
2806 err = B_TRUE;
2807 } else {
2808 err |= do_import(found_config, argc == 1 ? NULL :
572e2857 2809 argv[1], mntopts, props, flags);
34dc7c2f
BB
2810 }
2811 }
2812
2813 /*
2814 * If we were just looking for pools, report an error if none were
2815 * found.
2816 */
2817 if (argc == 0 && first)
2818 (void) fprintf(stderr,
2819 gettext("no pools available to import\n"));
2820
2821error:
2822 nvlist_free(props);
2823 nvlist_free(pools);
428870ff 2824 nvlist_free(policy);
d603ed6c
BB
2825 if (searchdirs != NULL)
2826 free(searchdirs);
44867b6d
BB
2827 if (envdup != NULL)
2828 free(envdup);
34dc7c2f
BB
2829
2830 return (err ? 1 : 0);
2831}
2832
bec1067d
AP
2833/*
2834 * zpool sync [-f] [pool] ...
2835 *
2836 * -f (undocumented) force uberblock (and config including zpool cache file)
2837 * update.
2838 *
2839 * Sync the specified pool(s).
2840 * Without arguments "zpool sync" will sync all pools.
2841 * This command initiates TXG sync(s) and will return after the TXG(s) commit.
2842 *
2843 */
2844static int
2845zpool_do_sync(int argc, char **argv)
2846{
2847 int ret;
2848 boolean_t force = B_FALSE;
2849
2850 /* check options */
2851 while ((ret = getopt(argc, argv, "f")) != -1) {
2852 switch (ret) {
2853 case 'f':
2854 force = B_TRUE;
2855 break;
2856 case '?':
2857 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2858 optopt);
2859 usage(B_FALSE);
2860 }
2861 }
2862
2863 argc -= optind;
2864 argv += optind;
2865
2866 /* if argc == 0 we will execute zpool_sync_one on all pools */
2867 ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);
2868
2869 return (ret);
2870}
2871
34dc7c2f 2872typedef struct iostat_cbdata {
193a37cb 2873 uint64_t cb_flags;
d2f3e292 2874 int cb_name_flags;
34dc7c2f 2875 int cb_namewidth;
1bd201e7 2876 int cb_iteration;
193a37cb
TH
2877 char **cb_vdev_names; /* Only show these vdevs */
2878 unsigned int cb_vdev_names_count;
2879 boolean_t cb_verbose;
2880 boolean_t cb_literal;
2881 boolean_t cb_scripted;
1bd201e7 2882 zpool_list_t *cb_list;
8720e9e7 2883 vdev_cmd_data_list_t *vcdl;
34dc7c2f
BB
2884} iostat_cbdata_t;
2885
193a37cb
TH
2886/* iostat labels */
2887typedef struct name_and_columns {
2888 const char *name; /* Column name */
2889 unsigned int columns; /* Center name to this number of columns */
2890} name_and_columns_t;
2891
2892#define IOSTAT_MAX_LABELS 11 /* Max number of labels on one line */
2893
2894static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
2895{
2896 [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2},
2897 {NULL}},
2898 [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
2899 {"asyncq_wait", 2}, {"scrub"}},
2900 [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
2901 {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
2902 {NULL}},
2903 [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2},
2904 {"sync_queue", 2}, {"async_queue", 2}, {NULL}},
7e945072
TH
2905 [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
2906 {"async_read", 2}, {"async_write", 2}, {"scrub", 2}, {NULL}},
2907
193a37cb
TH
2908};
2909
2910/* Shorthand - if "columns" field not set, default to 1 column */
2911static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
2912{
2913 [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"},
2914 {"write"}, {NULL}},
2915 [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
2916 {"write"}, {"read"}, {"write"}, {"wait"}, {NULL}},
2917 [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
2918 {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"}, {NULL}},
2919 [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
2920 {"write"}, {"read"}, {"write"}, {"scrub"}, {NULL}},
7e945072
TH
2921 [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
2922 {"ind"}, {"agg"}, {"ind"}, {"agg"}, {NULL}},
2923};
2924
2925static const char *histo_to_title[] = {
2926 [IOS_L_HISTO] = "latency",
2927 [IOS_RQ_HISTO] = "req_size",
193a37cb
TH
2928};
2929
2930/*
2931 * Return the number of labels in a null-terminated name_and_columns_t
2932 * array.
2933 *
2934 */
2935static unsigned int
2936label_array_len(const name_and_columns_t *labels)
2937{
2938 int i = 0;
2939
2940 while (labels[i].name)
2941 i++;
2942
2943 return (i);
2944}
2945
7e945072
TH
2946/*
2947 * Return the number of strings in a null-terminated string array.
2948 * For example:
2949 *
2950 * const char foo[] = {"bar", "baz", NULL}
2951 *
2952 * returns 2
2953 */
2954static uint64_t
2955str_array_len(const char *array[])
2956{
2957 uint64_t i = 0;
2958 while (array[i])
2959 i++;
2960
2961 return (i);
2962}
2963
2964
193a37cb
TH
2965/*
2966 * Return a default column width for default/latency/queue columns. This does
2967 * not include histograms, which have their columns autosized.
2968 */
2969static unsigned int
2970default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
2971{
2972 unsigned long column_width = 5; /* Normal niceprint */
2973 static unsigned long widths[] = {
2974 /*
2975 * Choose some sane default column sizes for printing the
2976 * raw numbers.
2977 */
2978 [IOS_DEFAULT] = 15, /* 1PB capacity */
2979 [IOS_LATENCY] = 10, /* 1B ns = 10sec */
2980 [IOS_QUEUES] = 6, /* 1M queue entries */
2981 };
2982
2983 if (cb->cb_literal)
2984 column_width = widths[type];
2985
2986 return (column_width);
2987}
2988
2989/*
2990 * Print the column labels, i.e:
2991 *
2992 * capacity operations bandwidth
2993 * alloc free read write read write ...
2994 *
2995 * If force_column_width is set, use it for the column width. If not set, use
2996 * the default column width.
2997 */
2998void
2999print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width,
3000 const name_and_columns_t labels[][IOSTAT_MAX_LABELS])
3001{
3002 int i, idx, s;
3003 unsigned int text_start, rw_column_width, spaces_to_end;
3004 uint64_t flags = cb->cb_flags;
3005 uint64_t f;
3006 unsigned int column_width = force_column_width;
3007
3008 /* For each bit set in flags */
3009 for (f = flags; f; f &= ~(1ULL << idx)) {
3010 idx = lowbit64(f) - 1;
3011 if (!force_column_width)
3012 column_width = default_column_width(cb, idx);
3013 /* Print our top labels centered over "read write" label. */
3014 for (i = 0; i < label_array_len(labels[idx]); i++) {
3015 const char *name = labels[idx][i].name;
3016 /*
3017 * We treat labels[][].columns == 0 as shorthand
3018 * for one column. It makes writing out the label
3019 * tables more concise.
3020 */
3021 unsigned int columns = MAX(1, labels[idx][i].columns);
3022 unsigned int slen = strlen(name);
3023
3024 rw_column_width = (column_width * columns) +
3025 (2 * (columns - 1));
3026
02730c33 3027 text_start = (int)((rw_column_width)/columns -
193a37cb
TH
3028 slen/columns);
3029
3030 printf(" "); /* Two spaces between columns */
3031
3032 /* Space from beginning of column to label */
3033 for (s = 0; s < text_start; s++)
3034 printf(" ");
3035
3036 printf("%s", name);
3037
3038 /* Print space after label to end of column */
3039 spaces_to_end = rw_column_width - text_start - slen;
3040 for (s = 0; s < spaces_to_end; s++)
3041 printf(" ");
3042
3043 }
3044 }
193a37cb
TH
3045}
3046
d6418de0
TH
3047
3048/*
3049 * print_cmd_columns - Print custom column titles from -c
3050 *
3051 * If the user specified the "zpool status|iostat -c" then print their custom
3052 * column titles in the header. For example, print_cmd_columns() would print
3053 * the " col1 col2" part of this:
3054 *
3055 * $ zpool iostat -vc 'echo col1=val1; echo col2=val2'
3056 * ...
3057 * capacity operations bandwidth
3058 * pool alloc free read write read write col1 col2
3059 * ---------- ----- ----- ----- ----- ----- ----- ---- ----
3060 * mypool 269K 1008M 0 0 107 946
3061 * mirror 269K 1008M 0 0 107 946
3062 * sdb - - 0 0 102 473 val1 val2
3063 * sdc - - 0 0 5 473 val1 val2
3064 * ---------- ----- ----- ----- ----- ----- ----- ---- ----
3065 */
3066void
3067print_cmd_columns(vdev_cmd_data_list_t *vcdl, int use_dashes)
3068{
3069 int i, j;
3070 vdev_cmd_data_t *data = &vcdl->data[0];
3071
3072 if (vcdl->count == 0 || data == NULL)
3073 return;
3074
3075 /*
3076 * Each vdev cmd should have the same column names unless the user did
3077 * something weird with their cmd. Just take the column names from the
3078 * first vdev and assume it works for all of them.
3079 */
3080 for (i = 0; i < vcdl->uniq_cols_cnt; i++) {
3081 printf(" ");
3082 if (use_dashes) {
3083 for (j = 0; j < vcdl->uniq_cols_width[i]; j++)
3084 printf("-");
3085 } else {
3086 printf("%*s", vcdl->uniq_cols_width[i],
3087 vcdl->uniq_cols[i]);
3088 }
3089 }
3090}
3091
3092
193a37cb
TH
3093/*
3094 * Utility function to print out a line of dashes like:
3095 *
3096 * -------------------------------- ----- ----- ----- ----- -----
3097 *
3098 * ...or a dashed named-row line like:
3099 *
3100 * logs - - - - -
3101 *
3102 * @cb: iostat data
3103 *
3104 * @force_column_width If non-zero, use the value as the column width.
3105 * Otherwise use the default column widths.
3106 *
3107 * @name: Print a dashed named-row line starting
3108 * with @name. Otherwise, print a regular
3109 * dashed line.
3110 */
3111static void
3112print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width,
3113 const char *name)
3114{
3115 int i;
3116 unsigned int namewidth;
3117 uint64_t flags = cb->cb_flags;
3118 uint64_t f;
3119 int idx;
3120 const name_and_columns_t *labels;
7e945072
TH
3121 const char *title;
3122
3123
3124 if (cb->cb_flags & IOS_ANYHISTO_M) {
3125 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3126 } else if (cb->cb_vdev_names_count) {
3127 title = "vdev";
3128 } else {
3129 title = "pool";
3130 }
3131
3132 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3133 name ? strlen(name) : 0);
193a37cb 3134
193a37cb
TH
3135
3136 if (name) {
193a37cb
TH
3137 printf("%-*s", namewidth, name);
3138 } else {
3139 for (i = 0; i < namewidth; i++)
3140 (void) printf("-");
3141 }
3142
3143 /* For each bit in flags */
3144 for (f = flags; f; f &= ~(1ULL << idx)) {
3145 unsigned int column_width;
3146 idx = lowbit64(f) - 1;
3147 if (force_column_width)
3148 column_width = force_column_width;
3149 else
3150 column_width = default_column_width(cb, idx);
3151
3152 labels = iostat_bottom_labels[idx];
3153 for (i = 0; i < label_array_len(labels); i++) {
3154 if (name)
3155 printf(" %*s-", column_width - 1, " ");
3156 else
3157 printf(" %.*s", column_width,
3158 "--------------------");
3159 }
3160 }
193a37cb
TH
3161}
3162
3163
3164static void
3165print_iostat_separator_impl(iostat_cbdata_t *cb,
3166 unsigned int force_column_width)
3167{
3168 print_iostat_dashes(cb, force_column_width, NULL);
3169}
3170
34dc7c2f
BB
3171static void
3172print_iostat_separator(iostat_cbdata_t *cb)
3173{
193a37cb
TH
3174 print_iostat_separator_impl(cb, 0);
3175}
3176
3177static void
3178print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
3179 const char *histo_vdev_name)
3180{
3181 unsigned int namewidth;
7e945072
TH
3182 const char *title;
3183
3184 if (cb->cb_flags & IOS_ANYHISTO_M) {
3185 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3186 } else if (cb->cb_vdev_names_count) {
3187 title = "vdev";
3188 } else {
3189 title = "pool";
3190 }
34dc7c2f 3191
7e945072
TH
3192 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3193 histo_vdev_name ? strlen(histo_vdev_name) : 0);
193a37cb 3194
7e945072 3195 if (histo_vdev_name)
193a37cb
TH
3196 printf("%-*s", namewidth, histo_vdev_name);
3197 else
3198 printf("%*s", namewidth, "");
3199
7e945072 3200
193a37cb 3201 print_iostat_labels(cb, force_column_width, iostat_top_labels);
d6418de0 3202 printf("\n");
193a37cb 3203
7e945072 3204 printf("%-*s", namewidth, title);
193a37cb
TH
3205
3206 print_iostat_labels(cb, force_column_width, iostat_bottom_labels);
d6418de0
TH
3207 if (cb->vcdl != NULL)
3208 print_cmd_columns(cb->vcdl, 0);
3209
3210 printf("\n");
193a37cb
TH
3211
3212 print_iostat_separator_impl(cb, force_column_width);
d6418de0
TH
3213
3214 if (cb->vcdl != NULL)
3215 print_cmd_columns(cb->vcdl, 1);
3216
3217 printf("\n");
34dc7c2f
BB
3218}
3219
3220static void
3221print_iostat_header(iostat_cbdata_t *cb)
3222{
193a37cb 3223 print_iostat_header_impl(cb, 0, NULL);
34dc7c2f
BB
3224}
3225
193a37cb 3226
34dc7c2f
BB
3227/*
3228 * Display a single statistic.
3229 */
3230static void
193a37cb
TH
3231print_one_stat(uint64_t value, enum zfs_nicenum_format format,
3232 unsigned int column_size, boolean_t scripted)
34dc7c2f
BB
3233{
3234 char buf[64];
3235
193a37cb
TH
3236 zfs_nicenum_format(value, buf, sizeof (buf), format);
3237
3238 if (scripted)
3239 printf("\t%s", buf);
3240 else
3241 printf(" %*s", column_size, buf);
3242}
3243
3244/*
3245 * Calculate the default vdev stats
3246 *
3247 * Subtract oldvs from newvs, apply a scaling factor, and save the resulting
3248 * stats into calcvs.
3249 */
3250static void
3251calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs,
3252 vdev_stat_t *calcvs)
3253{
3254 int i;
3255
3256 memcpy(calcvs, newvs, sizeof (*calcvs));
3257 for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++)
3258 calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]);
3259
3260 for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++)
3261 calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]);
3262}
3263
3264/*
3265 * Internal representation of the extended iostats data.
3266 *
3267 * The extended iostat stats are exported in nvlists as either uint64_t arrays
3268 * or single uint64_t's. We make both look like arrays to make them easier
3269 * to process. In order to make single uint64_t's look like arrays, we set
3270 * __data to the stat data, and then set *data = &__data with count = 1. Then,
3271 * we can just use *data and count.
3272 */
3273struct stat_array {
3274 uint64_t *data;
3275 uint_t count; /* Number of entries in data[] */
3276 uint64_t __data; /* Only used when data is a single uint64_t */
3277};
3278
3279static uint64_t
4ea3f864
GM
3280stat_histo_max(struct stat_array *nva, unsigned int len)
3281{
193a37cb
TH
3282 uint64_t max = 0;
3283 int i;
3284 for (i = 0; i < len; i++)
3285 max = MAX(max, array64_max(nva[i].data, nva[i].count));
3286
3287 return (max);
3288}
3289
3290/*
3291 * Helper function to lookup a uint64_t array or uint64_t value and store its
3292 * data as a stat_array. If the nvpair is a single uint64_t value, then we make
3293 * it look like a one element array to make it easier to process.
3294 */
3295static int
3296nvpair64_to_stat_array(nvlist_t *nvl, const char *name,
4ea3f864
GM
3297 struct stat_array *nva)
3298{
193a37cb
TH
3299 nvpair_t *tmp;
3300 int ret;
3301
3302 verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0);
3303 switch (nvpair_type(tmp)) {
3304 case DATA_TYPE_UINT64_ARRAY:
3305 ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count);
3306 break;
3307 case DATA_TYPE_UINT64:
3308 ret = nvpair_value_uint64(tmp, &nva->__data);
3309 nva->data = &nva->__data;
3310 nva->count = 1;
3311 break;
3312 default:
3313 /* Not a uint64_t */
3314 ret = EINVAL;
3315 break;
3316 }
3317
3318 return (ret);
3319}
3320
3321/*
3322 * Given a list of nvlist names, look up the extended stats in newnv and oldnv,
3323 * subtract them, and return the results in a newly allocated stat_array.
3324 * You must free the returned array after you are done with it with
3325 * free_calc_stats().
3326 *
3327 * Additionally, you can set "oldnv" to NULL if you simply want the newnv
3328 * values.
3329 */
3330static struct stat_array *
3331calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv,
3332 nvlist_t *newnv)
3333{
3334 nvlist_t *oldnvx = NULL, *newnvx;
3335 struct stat_array *oldnva, *newnva, *calcnva;
3336 int i, j;
3337 unsigned int alloc_size = (sizeof (struct stat_array)) * len;
3338
3339 /* Extract our extended stats nvlist from the main list */
3340 verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3341 &newnvx) == 0);
3342 if (oldnv) {
3343 verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3344 &oldnvx) == 0);
3345 }
3346
3347 newnva = safe_malloc(alloc_size);
3348 oldnva = safe_malloc(alloc_size);
3349 calcnva = safe_malloc(alloc_size);
3350
3351 for (j = 0; j < len; j++) {
3352 verify(nvpair64_to_stat_array(newnvx, names[j],
3353 &newnva[j]) == 0);
3354 calcnva[j].count = newnva[j].count;
3355 alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]);
3356 calcnva[j].data = safe_malloc(alloc_size);
3357 memcpy(calcnva[j].data, newnva[j].data, alloc_size);
3358
3359 if (oldnvx) {
3360 verify(nvpair64_to_stat_array(oldnvx, names[j],
3361 &oldnva[j]) == 0);
3362 for (i = 0; i < oldnva[j].count; i++)
3363 calcnva[j].data[i] -= oldnva[j].data[i];
3364 }
3365 }
3366 free(newnva);
3367 free(oldnva);
3368 return (calcnva);
3369}
3370
3371static void
3372free_calc_stats(struct stat_array *nva, unsigned int len)
3373{
3374 int i;
3375 for (i = 0; i < len; i++)
3376 free(nva[i].data);
3377
3378 free(nva);
3379}
3380
3381static void
3382print_iostat_histo(struct stat_array *nva, unsigned int len,
3383 iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth,
3384 double scale)
3385{
3386 int i, j;
3387 char buf[6];
3388 uint64_t val;
3389 enum zfs_nicenum_format format;
3390 unsigned int buckets;
7e945072 3391 unsigned int start_bucket;
193a37cb
TH
3392
3393 if (cb->cb_literal)
3394 format = ZFS_NICENUM_RAW;
3395 else
3396 format = ZFS_NICENUM_1024;
3397
3398 /* All these histos are the same size, so just use nva[0].count */
3399 buckets = nva[0].count;
3400
7e945072
TH
3401 if (cb->cb_flags & IOS_RQ_HISTO_M) {
3402 /* Start at 512 - req size should never be lower than this */
3403 start_bucket = 9;
3404 } else {
3405 start_bucket = 0;
3406 }
193a37cb 3407
7e945072 3408 for (j = start_bucket; j < buckets; j++) {
193a37cb 3409 /* Print histogram bucket label */
7e945072
TH
3410 if (cb->cb_flags & IOS_L_HISTO_M) {
3411 /* Ending range of this bucket */
3412 val = (1UL << (j + 1)) - 1;
3413 zfs_nicetime(val, buf, sizeof (buf));
3414 } else {
3415 /* Request size (starting range of bucket) */
3416 val = (1UL << j);
3417 zfs_nicenum(val, buf, sizeof (buf));
3418 }
3419
193a37cb 3420 if (cb->cb_scripted)
02730c33 3421 printf("%llu", (u_longlong_t)val);
193a37cb
TH
3422 else
3423 printf("%-*s", namewidth, buf);
3424
3425 /* Print the values on the line */
3426 for (i = 0; i < len; i++) {
3427 print_one_stat(nva[i].data[j] * scale, format,
3428 column_width, cb->cb_scripted);
3429 }
3430 printf("\n");
3431 }
3432}
3433
3434static void
3435print_solid_separator(unsigned int length)
3436{
3437 while (length--)
3438 printf("-");
3439 printf("\n");
3440}
3441
3442static void
3443print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv,
3444 nvlist_t *newnv, double scale, const char *name)
3445{
3446 unsigned int column_width;
3447 unsigned int namewidth;
3448 unsigned int entire_width;
7e945072 3449 enum iostat_type type;
193a37cb 3450 struct stat_array *nva;
7e945072
TH
3451 const char **names;
3452 unsigned int names_len;
3453
3454 /* What type of histo are we? */
3455 type = IOS_HISTO_IDX(cb->cb_flags);
3456
3457 /* Get NULL-terminated array of nvlist names for our histo */
3458 names = vsx_type_to_nvlist[type];
3459 names_len = str_array_len(names); /* num of names */
3460
3461 nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv);
193a37cb
TH
3462
3463 if (cb->cb_literal) {
3464 column_width = MAX(5,
7e945072 3465 (unsigned int) log10(stat_histo_max(nva, names_len)) + 1);
193a37cb
TH
3466 } else {
3467 column_width = 5;
3468 }
3469
7e945072
TH
3470 namewidth = MAX(cb->cb_namewidth,
3471 strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]));
193a37cb
TH
3472
3473 /*
3474 * Calculate the entire line width of what we're printing. The
3475 * +2 is for the two spaces between columns:
3476 */
3477 /* read write */
3478 /* ----- ----- */
3479 /* |___| <---------- column_width */
3480 /* */
3481 /* |__________| <--- entire_width */
3482 /* */
3483 entire_width = namewidth + (column_width + 2) *
7e945072 3484 label_array_len(iostat_bottom_labels[type]);
193a37cb
TH
3485
3486 if (cb->cb_scripted)
3487 printf("%s\n", name);
3488 else
3489 print_iostat_header_impl(cb, column_width, name);
3490
7e945072 3491 print_iostat_histo(nva, names_len, cb, column_width,
193a37cb
TH
3492 namewidth, scale);
3493
7e945072 3494 free_calc_stats(nva, names_len);
193a37cb
TH
3495 if (!cb->cb_scripted)
3496 print_solid_separator(entire_width);
3497}
3498
3499/*
3500 * Calculate the average latency of a power-of-two latency histogram
3501 */
3502static uint64_t
3503single_histo_average(uint64_t *histo, unsigned int buckets)
3504{
3505 int i;
3506 uint64_t count = 0, total = 0;
3507
3508 for (i = 0; i < buckets; i++) {
3509 /*
3510 * Our buckets are power-of-two latency ranges. Use the
3511 * midpoint latency of each bucket to calculate the average.
3512 * For example:
3513 *
3514 * Bucket Midpoint
3515 * 8ns-15ns: 12ns
3516 * 16ns-31ns: 24ns
3517 * ...
3518 */
3519 if (histo[i] != 0) {
3520 total += histo[i] * (((1UL << i) + ((1UL << i)/2)));
3521 count += histo[i];
3522 }
3523 }
3524
3525 /* Prevent divide by zero */
3526 return (count == 0 ? 0 : total / count);
3527}
3528
3529static void
3530print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *oldnv,
3531 nvlist_t *newnv, double scale)
3532{
3533 int i;
3534 uint64_t val;
3535 const char *names[] = {
3536 ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE,
3537 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
3538 ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE,
3539 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
3540 ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE,
3541 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
3542 ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE,
3543 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
3544 ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE,
3545 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
3546 };
3547
3548 struct stat_array *nva;
3549
3550 unsigned int column_width = default_column_width(cb, IOS_QUEUES);
3551 enum zfs_nicenum_format format;
3552
3553 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv);
3554
3555 if (cb->cb_literal)
3556 format = ZFS_NICENUM_RAW;
3557 else
3558 format = ZFS_NICENUM_1024;
3559
3560 for (i = 0; i < ARRAY_SIZE(names); i++) {
3561 val = nva[i].data[0] * scale;
3562 print_one_stat(val, format, column_width, cb->cb_scripted);
3563 }
3564
3565 free_calc_stats(nva, ARRAY_SIZE(names));
3566}
3567
3568static void
3569print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv,
3570 nvlist_t *newnv, double scale)
3571{
3572 int i;
3573 uint64_t val;
3574 const char *names[] = {
3575 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
3576 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
3577 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
3578 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
3579 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
3580 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
3581 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
3582 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
3583 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
3584 };
3585 struct stat_array *nva;
3586
3587 unsigned int column_width = default_column_width(cb, IOS_LATENCY);
3588 enum zfs_nicenum_format format;
3589
3590 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv);
3591
3592 if (cb->cb_literal)
29eb4942 3593 format = ZFS_NICENUM_RAWTIME;
193a37cb
TH
3594 else
3595 format = ZFS_NICENUM_TIME;
3596
3597 /* Print our avg latencies on the line */
3598 for (i = 0; i < ARRAY_SIZE(names); i++) {
3599 /* Compute average latency for a latency histo */
3600 val = single_histo_average(nva[i].data, nva[i].count) * scale;
3601 print_one_stat(val, format, column_width, cb->cb_scripted);
3602 }
3603 free_calc_stats(nva, ARRAY_SIZE(names));
3604}
3605
3606/*
3607 * Print default statistics (capacity/operations/bandwidth)
3608 */
3609static void
3610print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale)
3611{
3612 unsigned int column_width = default_column_width(cb, IOS_DEFAULT);
3613 enum zfs_nicenum_format format;
3614 char na; /* char to print for "not applicable" values */
3615
3616 if (cb->cb_literal) {
3617 format = ZFS_NICENUM_RAW;
3618 na = '0';
3619 } else {
3620 format = ZFS_NICENUM_1024;
3621 na = '-';
3622 }
3623
3624 /* only toplevel vdevs have capacity stats */
3625 if (vs->vs_space == 0) {
3626 if (cb->cb_scripted)
3627 printf("\t%c\t%c", na, na);
3628 else
3629 printf(" %*c %*c", column_width, na, column_width,
3630 na);
3631 } else {
3632 print_one_stat(vs->vs_alloc, format, column_width,
3633 cb->cb_scripted);
3634 print_one_stat(vs->vs_space - vs->vs_alloc, format,
3635 column_width, cb->cb_scripted);
3636 }
3637
3638 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale),
3639 format, column_width, cb->cb_scripted);
3640 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale),
3641 format, column_width, cb->cb_scripted);
3642 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale),
3643 format, column_width, cb->cb_scripted);
3644 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale),
3645 format, column_width, cb->cb_scripted);
34dc7c2f
BB
3646}
3647
3648/*
3649 * Print out all the statistics for the given vdev. This can either be the
3650 * toplevel configuration, or called recursively. If 'name' is NULL, then this
3651 * is a verbose output, and we don't want to display the toplevel pool stats.
193a37cb
TH
3652 *
3653 * Returns the number of stat lines printed.
34dc7c2f 3654 */
193a37cb 3655unsigned int
34dc7c2f
BB
3656print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
3657 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
3658{
3659 nvlist_t **oldchild, **newchild;
674b8934 3660 uint_t c, children, oldchildren;
193a37cb 3661 vdev_stat_t *oldvs, *newvs, *calcvs;
34dc7c2f 3662 vdev_stat_t zerovs = { 0 };
193a37cb
TH
3663 char *vname;
3664 int i;
3665 int ret = 0;
34dc7c2f
BB
3666 uint64_t tdelta;
3667 double scale;
193a37cb
TH
3668
3669 calcvs = safe_malloc(sizeof (*calcvs));
34dc7c2f
BB
3670
3671 if (oldnv != NULL) {
428870ff
BB
3672 verify(nvlist_lookup_uint64_array(oldnv,
3673 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
34dc7c2f
BB
3674 } else {
3675 oldvs = &zerovs;
3676 }
3677
193a37cb
TH
3678 /* Do we only want to see a specific vdev? */
3679 for (i = 0; i < cb->cb_vdev_names_count; i++) {
3680 /* Yes we do. Is this the vdev? */
3681 if (strcmp(name, cb->cb_vdev_names[i]) == 0) {
3682 /*
3683 * This is our vdev. Since it is the only vdev we
3684 * will be displaying, make depth = 0 so that it
3685 * doesn't get indented.
3686 */
3687 depth = 0;
3688 break;
3689 }
3690 }
3691
3692 if (cb->cb_vdev_names_count && (i == cb->cb_vdev_names_count)) {
3693 /* Couldn't match the name */
3694 goto children;
3695 }
3696
3697
428870ff 3698 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
3699 (uint64_t **)&newvs, &c) == 0);
3700
193a37cb
TH
3701 /*
3702 * Print the vdev name unless it's is a histogram. Histograms
3703 * display the vdev name in the header itself.
3704 */
7e945072 3705 if (!(cb->cb_flags & IOS_ANYHISTO_M)) {
193a37cb
TH
3706 if (cb->cb_scripted) {
3707 printf("%s", name);
3708 } else {
3709 if (strlen(name) + depth > cb->cb_namewidth)
3710 (void) printf("%*s%s", depth, "", name);
3711 else
3712 (void) printf("%*s%s%*s", depth, "", name,
3713 (int)(cb->cb_namewidth - strlen(name) -
3714 depth), "");
3715 }
3716 }
34dc7c2f 3717
193a37cb 3718 /* Calculate our scaling factor */
34dc7c2f 3719 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
7e945072 3720 if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) {
193a37cb
TH
3721 /*
3722 * If we specify printing histograms with no time interval, then
3723 * print the histogram numbers over the entire lifetime of the
3724 * vdev.
3725 */
3726 scale = 1;
34dc7c2f 3727 } else {
193a37cb
TH
3728 if (tdelta == 0)
3729 scale = 1.0;
3730 else
3731 scale = (double)NANOSEC / tdelta;
34dc7c2f
BB
3732 }
3733
193a37cb
TH
3734 if (cb->cb_flags & IOS_DEFAULT_M) {
3735 calc_default_iostats(oldvs, newvs, calcvs);
3736 print_iostat_default(calcvs, cb, scale);
3737 }
3738 if (cb->cb_flags & IOS_LATENCY_M)
3739 print_iostat_latency(cb, oldnv, newnv, scale);
3740 if (cb->cb_flags & IOS_QUEUES_M)
3741 print_iostat_queues(cb, oldnv, newnv, scale);
7e945072 3742 if (cb->cb_flags & IOS_ANYHISTO_M) {
193a37cb
TH
3743 printf("\n");
3744 print_iostat_histos(cb, oldnv, newnv, scale, name);
3745 }
34dc7c2f 3746
8720e9e7
TH
3747 if (cb->vcdl != NULL) {
3748 char *path;
3749 if (nvlist_lookup_string(newnv, ZPOOL_CONFIG_PATH,
3750 &path) == 0) {
d6418de0 3751 printf(" ");
8720e9e7 3752 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path);
8720e9e7
TH
3753 }
3754 }
3755
7e945072 3756 if (!(cb->cb_flags & IOS_ANYHISTO_M))
193a37cb 3757 printf("\n");
34dc7c2f 3758
193a37cb 3759 ret++;
34dc7c2f 3760
193a37cb 3761children:
92bc9278 3762
3763 free(calcvs);
3764
34dc7c2f 3765 if (!cb->cb_verbose)
193a37cb 3766 return (ret);
34dc7c2f
BB
3767
3768 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
3769 &newchild, &children) != 0)
193a37cb 3770 return (ret);
34dc7c2f 3771
674b8934
TH
3772 if (oldnv) {
3773 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
3774 &oldchild, &oldchildren) != 0)
3775 return (ret);
3776
3777 children = MIN(oldchildren, children);
3778 }
34dc7c2f
BB
3779
3780 for (c = 0; c < children; c++) {
187632dc 3781 uint64_t ishole = B_FALSE, islog = B_FALSE;
428870ff 3782
187632dc
MH
3783 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
3784 &ishole);
3785
3786 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
3787 &islog);
3788
3789 if (ishole || islog)
428870ff
BB
3790 continue;
3791
d2f3e292
RY
3792 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
3793 cb->cb_name_flags);
193a37cb 3794 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
34dc7c2f
BB
3795 newchild[c], cb, depth + 2);
3796 free(vname);
3797 }
3798
187632dc
MH
3799 /*
3800 * Log device section
3801 */
3802
3803 if (num_logs(newnv) > 0) {
7e945072 3804 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted &&
193a37cb
TH
3805 !cb->cb_vdev_names) {
3806 print_iostat_dashes(cb, 0, "logs");
3807 }
5034557b 3808 printf("\n");
187632dc
MH
3809
3810 for (c = 0; c < children; c++) {
3811 uint64_t islog = B_FALSE;
3812 (void) nvlist_lookup_uint64(newchild[c],
3813 ZPOOL_CONFIG_IS_LOG, &islog);
3814
3815 if (islog) {
3816 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
d2f3e292 3817 cb->cb_name_flags);
193a37cb 3818 ret += print_vdev_stats(zhp, vname, oldnv ?
187632dc
MH
3819 oldchild[c] : NULL, newchild[c],
3820 cb, depth + 2);
3821 free(vname);
3822 }
3823 }
3824
3825 }
3826
34dc7c2f
BB
3827 /*
3828 * Include level 2 ARC devices in iostat output
3829 */
3830 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
3831 &newchild, &children) != 0)
193a37cb 3832 return (ret);
34dc7c2f 3833
674b8934
TH
3834 if (oldnv) {
3835 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
3836 &oldchild, &oldchildren) != 0)
3837 return (ret);
3838
3839 children = MIN(oldchildren, children);
3840 }
34dc7c2f
BB
3841
3842 if (children > 0) {
7e945072 3843 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted &&
193a37cb
TH
3844 !cb->cb_vdev_names) {
3845 print_iostat_dashes(cb, 0, "cache");
3846 }
5034557b 3847 printf("\n");
193a37cb 3848
34dc7c2f 3849 for (c = 0; c < children; c++) {
428870ff 3850 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
d2f3e292 3851 cb->cb_name_flags);
193a37cb
TH
3852 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c]
3853 : NULL, newchild[c], cb, depth + 2);
34dc7c2f
BB
3854 free(vname);
3855 }
3856 }
193a37cb
TH
3857
3858 return (ret);
34dc7c2f
BB
3859}
3860
3861static int
3862refresh_iostat(zpool_handle_t *zhp, void *data)
3863{
3864 iostat_cbdata_t *cb = data;
3865 boolean_t missing;
3866
3867 /*
3868 * If the pool has disappeared, remove it from the list and continue.
3869 */
3870 if (zpool_refresh_stats(zhp, &missing) != 0)
3871 return (-1);
3872
3873 if (missing)
3874 pool_list_remove(cb->cb_list, zhp);
3875
3876 return (0);
3877}
3878
3879/*
3880 * Callback to print out the iostats for the given pool.
3881 */
3882int
3883print_iostat(zpool_handle_t *zhp, void *data)
3884{
3885 iostat_cbdata_t *cb = data;
3886 nvlist_t *oldconfig, *newconfig;
3887 nvlist_t *oldnvroot, *newnvroot;
193a37cb 3888 int ret;
34dc7c2f
BB
3889
3890 newconfig = zpool_get_config(zhp, &oldconfig);
3891
3892 if (cb->cb_iteration == 1)
3893 oldconfig = NULL;
3894
3895 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
3896 &newnvroot) == 0);
3897
3898 if (oldconfig == NULL)
3899 oldnvroot = NULL;
3900 else
3901 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
3902 &oldnvroot) == 0);
3903
193a37cb 3904 ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot,
02730c33 3905 cb, 0);
7e945072
TH
3906 if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) &&
3907 !cb->cb_scripted && cb->cb_verbose && !cb->cb_vdev_names_count) {
3908 print_iostat_separator(cb);
d6418de0
TH
3909 if (cb->vcdl != NULL) {
3910 print_cmd_columns(cb->vcdl, 1);
3911 }
3912 printf("\n");
7e945072 3913 }
34dc7c2f 3914
193a37cb 3915 return (ret);
34dc7c2f
BB
3916}
3917
9fc60702
CS
3918static int
3919get_columns(void)
3920{
3921 struct winsize ws;
3922 int columns = 80;
3923 int error;
3924
3925 if (isatty(STDOUT_FILENO)) {
3926 error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
3927 if (error == 0)
3928 columns = ws.ws_col;
3929 } else {
3930 columns = 999;
3931 }
3932
d1d7e268 3933 return (columns);
9fc60702
CS
3934}
3935
34dc7c2f
BB
3936int
3937get_namewidth(zpool_handle_t *zhp, void *data)
3938{
3939 iostat_cbdata_t *cb = data;
3940 nvlist_t *config, *nvroot;
9fc60702 3941 int columns;
34dc7c2f
BB
3942
3943 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
3944 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3945 &nvroot) == 0);
193a37cb 3946 unsigned int poolname_len = strlen(zpool_get_name(zhp));
34dc7c2f 3947 if (!cb->cb_verbose)
2df9ad1c 3948 cb->cb_namewidth = MAX(poolname_len, cb->cb_namewidth);
34dc7c2f 3949 else
193a37cb
TH
3950 cb->cb_namewidth = MAX(poolname_len,
3951 max_width(zhp, nvroot, 0, cb->cb_namewidth,
3952 cb->cb_name_flags));
34dc7c2f 3953 }
34dc7c2f 3954 /*
9fc60702
CS
3955 * The width must be at least 10, but may be as large as the
3956 * column width - 42 so that we can still fit in one line.
34dc7c2f 3957 */
9fc60702
CS
3958 columns = get_columns();
3959
34dc7c2f
BB
3960 if (cb->cb_namewidth < 10)
3961 cb->cb_namewidth = 10;
9fc60702
CS
3962 if (cb->cb_namewidth > columns - 42)
3963 cb->cb_namewidth = columns - 42;
34dc7c2f
BB
3964
3965 return (0);
3966}
3967
3968/*
428870ff 3969 * Parse the input string, get the 'interval' and 'count' value if there is one.
34dc7c2f 3970 */
428870ff 3971static void
193a37cb 3972get_interval_count(int *argcp, char **argv, float *iv,
428870ff 3973 unsigned long *cnt)
34dc7c2f 3974{
193a37cb
TH
3975 float interval = 0;
3976 unsigned long count = 0;
1fde1e37 3977 int argc = *argcp;
34dc7c2f
BB
3978
3979 /*
3980 * Determine if the last argument is an integer or a pool name
3981 */
193a37cb 3982 if (argc > 0 && isnumber(argv[argc - 1])) {
34dc7c2f
BB
3983 char *end;
3984
3985 errno = 0;
193a37cb 3986 interval = strtof(argv[argc - 1], &end);
34dc7c2f
BB
3987
3988 if (*end == '\0' && errno == 0) {
3989 if (interval == 0) {
3990 (void) fprintf(stderr, gettext("interval "
3991 "cannot be zero\n"));
3992 usage(B_FALSE);
3993 }
34dc7c2f
BB
3994 /*
3995 * Ignore the last parameter
3996 */
3997 argc--;
3998 } else {
3999 /*
4000 * If this is not a valid number, just plow on. The
4001 * user will get a more informative error message later
4002 * on.
4003 */
4004 interval = 0;
4005 }
4006 }
4007
4008 /*
4009 * If the last argument is also an integer, then we have both a count
428870ff 4010 * and an interval.
34dc7c2f 4011 */
193a37cb 4012 if (argc > 0 && isnumber(argv[argc - 1])) {
34dc7c2f
BB
4013 char *end;
4014
4015 errno = 0;
4016 count = interval;
193a37cb 4017 interval = strtof(argv[argc - 1], &end);
34dc7c2f
BB
4018
4019 if (*end == '\0' && errno == 0) {
4020 if (interval == 0) {
4021 (void) fprintf(stderr, gettext("interval "
4022 "cannot be zero\n"));
4023 usage(B_FALSE);
4024 }
4025
4026 /*
4027 * Ignore the last parameter
4028 */
4029 argc--;
4030 } else {
4031 interval = 0;
4032 }
4033 }
4034
428870ff
BB
4035 *iv = interval;
4036 *cnt = count;
4037 *argcp = argc;
4038}
4039
4040static void
4041get_timestamp_arg(char c)
4042{
4043 if (c == 'u')
4044 timestamp_fmt = UDATE;
4045 else if (c == 'd')
4046 timestamp_fmt = DDATE;
4047 else
4048 usage(B_FALSE);
4049}
4050
4051/*
193a37cb
TH
4052 * Return stat flags that are supported by all pools by both the module and
4053 * zpool iostat. "*data" should be initialized to all 0xFFs before running.
4054 * It will get ANDed down until only the flags that are supported on all pools
4055 * remain.
4056 */
4057static int
4058get_stat_flags_cb(zpool_handle_t *zhp, void *data)
4059{
4060 uint64_t *mask = data;
4061 nvlist_t *config, *nvroot, *nvx;
4062 uint64_t flags = 0;
4063 int i, j;
4064
193a37cb
TH
4065 config = zpool_get_config(zhp, NULL);
4066 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4067 &nvroot) == 0);
4068
4069 /* Default stats are always supported, but for completeness.. */
4070 if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS))
4071 flags |= IOS_DEFAULT_M;
4072
4073 /* Get our extended stats nvlist from the main list */
4074 if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX,
4075 &nvx) != 0) {
4076 /*
4077 * No extended stats; they're probably running an older
4078 * module. No big deal, we support that too.
4079 */
4080 goto end;
4081 }
4082
4083 /* For each extended stat, make sure all its nvpairs are supported */
4084 for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) {
4085 if (!vsx_type_to_nvlist[j][0])
4086 continue;
4087
4088 /* Start off by assuming the flag is supported, then check */
4089 flags |= (1ULL << j);
4090 for (i = 0; vsx_type_to_nvlist[j][i]; i++) {
4091 if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) {
4092 /* flag isn't supported */
4093 flags = flags & ~(1ULL << j);
4094 break;
4095 }
4096 }
4097 }
4098end:
4099 *mask = *mask & flags;
4100 return (0);
4101}
4102
4103/*
4104 * Return a bitmask of stats that are supported on all pools by both the module
4105 * and zpool iostat.
4106 */
4107static uint64_t
4108get_stat_flags(zpool_list_t *list)
4109{
4110 uint64_t mask = -1;
4111
4112 /*
4113 * get_stat_flags_cb() will lop off bits from "mask" until only the
4114 * flags that are supported on all pools remain.
4115 */
4116 pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask);
4117 return (mask);
4118}
4119
4120/*
4121 * Return 1 if cb_data->cb_vdev_names[0] is this vdev's name, 0 otherwise.
4122 */
4123static int
4124is_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_data)
4125{
4126 iostat_cbdata_t *cb = cb_data;
92bc9278 4127 char *name = NULL;
4128 int ret = 0;
193a37cb
TH
4129
4130 name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags);
4131
4132 if (strcmp(name, cb->cb_vdev_names[0]) == 0)
92bc9278 4133 ret = 1; /* match */
4134 free(name);
193a37cb 4135
92bc9278 4136 return (ret);
193a37cb
TH
4137}
4138
4139/*
4140 * Returns 1 if cb_data->cb_vdev_names[0] is a vdev name, 0 otherwise.
4141 */
4142static int
4143is_vdev(zpool_handle_t *zhp, void *cb_data)
4144{
4145 return (for_each_vdev(zhp, is_vdev_cb, cb_data));
4146}
4147
4148/*
4149 * Check if vdevs are in a pool
4150 *
4151 * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise
4152 * return 0. If pool_name is NULL, then search all pools.
4153 */
4154static int
4155are_vdevs_in_pool(int argc, char **argv, char *pool_name,
4156 iostat_cbdata_t *cb)
4157{
4158 char **tmp_name;
4159 int ret = 0;
4160 int i;
4161 int pool_count = 0;
4162
4163 if ((argc == 0) || !*argv)
4164 return (0);
4165
4166 if (pool_name)
4167 pool_count = 1;
4168
4169 /* Temporarily hijack cb_vdev_names for a second... */
4170 tmp_name = cb->cb_vdev_names;
4171
4172 /* Go though our list of prospective vdev names */
4173 for (i = 0; i < argc; i++) {
4174 cb->cb_vdev_names = argv + i;
4175
4176 /* Is this name a vdev in our pools? */
4177 ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL,
4178 is_vdev, cb);
4179 if (!ret) {
4180 /* No match */
4181 break;
4182 }
4183 }
4184
4185 cb->cb_vdev_names = tmp_name;
4186
4187 return (ret);
4188}
4189
4190static int
4191is_pool_cb(zpool_handle_t *zhp, void *data)
4192{
4193 char *name = data;
4194 if (strcmp(name, zpool_get_name(zhp)) == 0)
4195 return (1);
4196
4197 return (0);
4198}
4199
4200/*
4201 * Do we have a pool named *name? If so, return 1, otherwise 0.
4202 */
4203static int
4204is_pool(char *name)
4205{
4206 return (for_each_pool(0, NULL, B_TRUE, NULL, is_pool_cb, name));
4207}
4208
4209/* Are all our argv[] strings pool names? If so return 1, 0 otherwise. */
4210static int
4ea3f864
GM
4211are_all_pools(int argc, char **argv)
4212{
193a37cb
TH
4213 if ((argc == 0) || !*argv)
4214 return (0);
4215
4216 while (--argc >= 0)
4217 if (!is_pool(argv[argc]))
4218 return (0);
4219
4220 return (1);
4221}
4222
4223/*
4224 * Helper function to print out vdev/pool names we can't resolve. Used for an
4225 * error message.
4226 */
4227static void
4228error_list_unresolved_vdevs(int argc, char **argv, char *pool_name,
4229 iostat_cbdata_t *cb)
4230{
4231 int i;
4232 char *name;
4233 char *str;
4234 for (i = 0; i < argc; i++) {
4235 name = argv[i];
4236
4237 if (is_pool(name))
4238 str = gettext("pool");
4239 else if (are_vdevs_in_pool(1, &name, pool_name, cb))
4240 str = gettext("vdev in this pool");
4241 else if (are_vdevs_in_pool(1, &name, NULL, cb))
4242 str = gettext("vdev in another pool");
4243 else
4244 str = gettext("unknown");
4245
4246 fprintf(stderr, "\t%s (%s)\n", name, str);
4247 }
4248}
4249
4250/*
4251 * Same as get_interval_count(), but with additional checks to not misinterpret
4252 * guids as interval/count values. Assumes VDEV_NAME_GUID is set in
4253 * cb.cb_name_flags.
4254 */
4255static void
4256get_interval_count_filter_guids(int *argc, char **argv, float *interval,
4257 unsigned long *count, iostat_cbdata_t *cb)
4258{
4259 char **tmpargv = argv;
4260 int argc_for_interval = 0;
4261
4262 /* Is the last arg an interval value? Or a guid? */
4263 if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL, cb)) {
4264 /*
4265 * The last arg is not a guid, so it's probably an
4266 * interval value.
4267 */
4268 argc_for_interval++;
4269
4270 if (*argc >= 2 &&
4271 !are_vdevs_in_pool(1, &argv[*argc - 2], NULL, cb)) {
4272 /*
4273 * The 2nd to last arg is not a guid, so it's probably
4274 * an interval value.
4275 */
4276 argc_for_interval++;
4277 }
4278 }
4279
4280 /* Point to our list of possible intervals */
4281 tmpargv = &argv[*argc - argc_for_interval];
4282
4283 *argc = *argc - argc_for_interval;
4284 get_interval_count(&argc_for_interval, tmpargv,
4285 interval, count);
4286}
4287
4288/*
4289 * Floating point sleep(). Allows you to pass in a floating point value for
4290 * seconds.
4291 */
4292static void
4ea3f864
GM
4293fsleep(float sec)
4294{
193a37cb
TH
4295 struct timespec req;
4296 req.tv_sec = floor(sec);
4297 req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
4298 nanosleep(&req, NULL);
4299}
4300
d6418de0
TH
4301/*
4302 * Run one of the zpool status/iostat -c scripts with the help (-h) option and
4303 * print the result.
4304 *
4305 * name: Short name of the script ('iostat').
4306 * path: Full path to the script ('/usr/local/etc/zfs/zpool.d/iostat');
4307 */
4308static void
4309print_zpool_script_help(char *name, char *path)
4310{
4311 char *argv[] = {path, "-h", NULL};
4312 char **lines = NULL;
4313 int lines_cnt = 0;
4314 int rc;
4315
4316 rc = libzfs_run_process_get_stdout_nopath(path, argv, NULL, &lines,
4317 &lines_cnt);
3e2ecae0
GDN
4318 if (rc != 0 || lines == NULL || lines_cnt <= 0) {
4319 if (lines != NULL)
4320 libzfs_free_str_array(lines, lines_cnt);
d6418de0 4321 return;
3e2ecae0 4322 }
d6418de0
TH
4323
4324 for (int i = 0; i < lines_cnt; i++)
4325 if (!is_blank_str(lines[i]))
4326 printf(" %-14s %s\n", name, lines[i]);
4327
4328 libzfs_free_str_array(lines, lines_cnt);
4329}
4330
193a37cb 4331/*
099700d9 4332 * Go though the zpool status/iostat -c scripts in the user's path, run their
d6418de0
TH
4333 * help option (-h), and print out the results.
4334 */
4335static void
099700d9 4336print_zpool_dir_scripts(char *dirpath)
d6418de0
TH
4337{
4338 DIR *dir;
4339 struct dirent *ent;
4340 char fullpath[MAXPATHLEN];
4341 struct stat dir_stat;
4342
099700d9 4343 if ((dir = opendir(dirpath)) != NULL) {
d6418de0
TH
4344 /* print all the files and directories within directory */
4345 while ((ent = readdir(dir)) != NULL) {
099700d9 4346 sprintf(fullpath, "%s/%s", dirpath, ent->d_name);
d6418de0
TH
4347
4348 /* Print the scripts */
4349 if (stat(fullpath, &dir_stat) == 0)
4350 if (dir_stat.st_mode & S_IXUSR &&
4351 S_ISREG(dir_stat.st_mode))
4352 print_zpool_script_help(ent->d_name,
4353 fullpath);
4354 }
d6418de0 4355 closedir(dir);
d6418de0
TH
4356 }
4357}
4358
099700d9
GDN
4359/*
4360 * Print out help text for all zpool status/iostat -c scripts.
4361 */
4362static void
4363print_zpool_script_list(char *subcommand)
4364{
4365 char *dir, *sp;
4366
4367 printf(gettext("Available 'zpool %s -c' commands:\n"), subcommand);
4368
4369 sp = zpool_get_cmd_search_path();
4370 if (sp == NULL)
4371 return;
4372
4373 dir = strtok(sp, ":");
4374 while (dir != NULL) {
4375 print_zpool_dir_scripts(dir);
4376 dir = strtok(NULL, ":");
4377 }
4378
4379 free(sp);
4380}
4381
d6418de0
TH
4382/*
4383 * zpool iostat [[-c [script1,script2,...]] [-lq]|[-rw]] [-ghHLpPvy] [-n name]
4384 * [-T d|u] [[ pool ...]|[pool vdev ...]|[vdev ...]]
4385 * [interval [count]]
428870ff 4386 *
8720e9e7 4387 * -c CMD For each vdev, run command CMD
d2f3e292
RY
4388 * -g Display guid for individual vdev name.
4389 * -L Follow links when resolving vdev path name.
a77f29f9 4390 * -P Display full path for vdev name.
428870ff 4391 * -v Display statistics for individual vdevs
193a37cb
TH
4392 * -h Display help
4393 * -p Display values in parsable (exact) format.
4394 * -H Scripted mode. Don't display headers, and separate properties
4395 * by a single tab.
4396 * -l Display average latency
4397 * -q Display queue depths
7e945072
TH
4398 * -w Display latency histograms
4399 * -r Display request size histogram
428870ff
BB
4400 * -T Display a timestamp in date(1) or Unix format
4401 *
4402 * This command can be tricky because we want to be able to deal with pool
4403 * creation/destruction as well as vdev configuration changes. The bulk of this
4404 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
4405 * on pool_list_update() to detect the addition of new pools. Configuration
4406 * changes are all handled within libzfs.
4407 */
4408int
4409zpool_do_iostat(int argc, char **argv)
4410{
4411 int c;
4412 int ret;
4413 int npools;
193a37cb
TH
4414 float interval = 0;
4415 unsigned long count = 0;
428870ff
BB
4416 zpool_list_t *list;
4417 boolean_t verbose = B_FALSE;
7e945072 4418 boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
3491d6eb 4419 boolean_t queues = B_FALSE, parsable = B_FALSE, scripted = B_FALSE;
41092124 4420 boolean_t omit_since_boot = B_FALSE;
d2f3e292
RY
4421 boolean_t guid = B_FALSE;
4422 boolean_t follow_links = B_FALSE;
4423 boolean_t full_name = B_FALSE;
4424 iostat_cbdata_t cb = { 0 };
8720e9e7 4425 char *cmd = NULL;
428870ff 4426
193a37cb
TH
4427 /* Used for printing error message */
4428 const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q',
7e945072 4429 [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'};
193a37cb
TH
4430
4431 uint64_t unsupported_flags;
4432
428870ff 4433 /* check options */
8720e9e7 4434 while ((c = getopt(argc, argv, "c:gLPT:vyhplqrwH")) != -1) {
428870ff 4435 switch (c) {
8720e9e7 4436 case 'c':
d6418de0
TH
4437 if (cmd != NULL) {
4438 fprintf(stderr,
4439 gettext("Can't set -c flag twice\n"));
4440 exit(1);
4441 }
099700d9
GDN
4442
4443 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL &&
4444 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) {
4445 fprintf(stderr, gettext(
4446 "Can't run -c, disabled by "
4447 "ZPOOL_SCRIPTS_ENABLED.\n"));
4448 exit(1);
4449 }
4450
d6418de0
TH
4451 if ((getuid() <= 0 || geteuid() <= 0) &&
4452 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) {
4453 fprintf(stderr, gettext(
4454 "Can't run -c with root privileges "
4455 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n"));
4456 exit(1);
4457 }
8720e9e7 4458 cmd = optarg;
d6418de0 4459 verbose = B_TRUE;
8720e9e7 4460 break;
d2f3e292
RY
4461 case 'g':
4462 guid = B_TRUE;
4463 break;
4464 case 'L':
4465 follow_links = B_TRUE;
4466 break;
a77f29f9 4467 case 'P':
d2f3e292
RY
4468 full_name = B_TRUE;
4469 break;
428870ff
BB
4470 case 'T':
4471 get_timestamp_arg(*optarg);
4472 break;
4473 case 'v':
4474 verbose = B_TRUE;
4475 break;
193a37cb 4476 case 'p':
3491d6eb 4477 parsable = B_TRUE;
193a37cb
TH
4478 break;
4479 case 'l':
4480 latency = B_TRUE;
4481 break;
4482 case 'q':
4483 queues = B_TRUE;
4484 break;
4485 case 'H':
4486 scripted = B_TRUE;
4487 break;
4488 case 'w':
7e945072
TH
4489 l_histo = B_TRUE;
4490 break;
4491 case 'r':
4492 rq_histo = B_TRUE;
193a37cb 4493 break;
41092124
HM
4494 case 'y':
4495 omit_since_boot = B_TRUE;
4496 break;
193a37cb
TH
4497 case 'h':
4498 usage(B_FALSE);
4499 break;
428870ff 4500 case '?':
1528bfdb 4501 if (optopt == 'c') {
099700d9 4502 print_zpool_script_list("iostat");
d6418de0 4503 exit(0);
1528bfdb
TH
4504 } else {
4505 fprintf(stderr,
4506 gettext("invalid option '%c'\n"), optopt);
4507 }
428870ff
BB
4508 usage(B_FALSE);
4509 }
4510 }
4511
4512 argc -= optind;
4513 argv += optind;
4514
3491d6eb 4515 cb.cb_literal = parsable;
193a37cb
TH
4516 cb.cb_scripted = scripted;
4517
4518 if (guid)
4519 cb.cb_name_flags |= VDEV_NAME_GUID;
4520 if (follow_links)
4521 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
4522 if (full_name)
4523 cb.cb_name_flags |= VDEV_NAME_PATH;
4524 cb.cb_iteration = 0;
4525 cb.cb_namewidth = 0;
4526 cb.cb_verbose = verbose;
4527
4528 /* Get our interval and count values (if any) */
4529 if (guid) {
4530 get_interval_count_filter_guids(&argc, argv, &interval,
4531 &count, &cb);
4532 } else {
4533 get_interval_count(&argc, argv, &interval, &count);
4534 }
4535
4536 if (argc == 0) {
4537 /* No args, so just print the defaults. */
4538 } else if (are_all_pools(argc, argv)) {
4539 /* All the args are pool names */
4540 } else if (are_vdevs_in_pool(argc, argv, NULL, &cb)) {
4541 /* All the args are vdevs */
4542 cb.cb_vdev_names = argv;
4543 cb.cb_vdev_names_count = argc;
4544 argc = 0; /* No pools to process */
4545 } else if (are_all_pools(1, argv)) {
4546 /* The first arg is a pool name */
4547 if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb)) {
4548 /* ...and the rest are vdev names */
4549 cb.cb_vdev_names = argv + 1;
4550 cb.cb_vdev_names_count = argc - 1;
4551 argc = 1; /* One pool to process */
4552 } else {
4553 fprintf(stderr, gettext("Expected either a list of "));
4554 fprintf(stderr, gettext("pools, or list of vdevs in"));
4555 fprintf(stderr, " \"%s\", ", argv[0]);
4556 fprintf(stderr, gettext("but got:\n"));
4557 error_list_unresolved_vdevs(argc - 1, argv + 1,
4558 argv[0], &cb);
4559 fprintf(stderr, "\n");
4560 usage(B_FALSE);
4561 return (1);
4562 }
4563 } else {
4564 /*
4565 * The args don't make sense. The first arg isn't a pool name,
4566 * nor are all the args vdevs.
4567 */
4568 fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n"));
4569 fprintf(stderr, "\n");
4570 return (1);
4571 }
4572
4573 if (cb.cb_vdev_names_count != 0) {
4574 /*
4575 * If user specified vdevs, it implies verbose.
4576 */
4577 cb.cb_verbose = B_TRUE;
4578 }
428870ff 4579
34dc7c2f
BB
4580 /*
4581 * Construct the list of all interesting pools.
4582 */
4583 ret = 0;
4584 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
4585 return (1);
4586
4587 if (pool_list_count(list) == 0 && argc != 0) {
4588 pool_list_free(list);
4589 return (1);
4590 }
4591
4592 if (pool_list_count(list) == 0 && interval == 0) {
4593 pool_list_free(list);
4594 (void) fprintf(stderr, gettext("no pools available\n"));
4595 return (1);
4596 }
4597
d6418de0 4598 if ((l_histo || rq_histo) && (cmd != NULL || latency || queues)) {
7e945072
TH
4599 pool_list_free(list);
4600 (void) fprintf(stderr,
d6418de0 4601 gettext("[-r|-w] isn't allowed with [-c|-l|-q]\n"));
7e945072
TH
4602 usage(B_FALSE);
4603 return (1);
4604 }
4605
4606 if (l_histo && rq_histo) {
193a37cb
TH
4607 pool_list_free(list);
4608 (void) fprintf(stderr,
7e945072 4609 gettext("Only one of [-r|-w] can be passed at a time\n"));
193a37cb
TH
4610 usage(B_FALSE);
4611 return (1);
4612 }
4613
34dc7c2f
BB
4614 /*
4615 * Enter the main iostat loop.
4616 */
4617 cb.cb_list = list;
193a37cb 4618
7e945072 4619 if (l_histo) {
193a37cb
TH
4620 /*
4621 * Histograms tables look out of place when you try to display
4622 * them with the other stats, so make a rule that you can only
4623 * print histograms by themselves.
4624 */
4625 cb.cb_flags = IOS_L_HISTO_M;
7e945072
TH
4626 } else if (rq_histo) {
4627 cb.cb_flags = IOS_RQ_HISTO_M;
193a37cb
TH
4628 } else {
4629 cb.cb_flags = IOS_DEFAULT_M;
4630 if (latency)
4631 cb.cb_flags |= IOS_LATENCY_M;
4632 if (queues)
4633 cb.cb_flags |= IOS_QUEUES_M;
4634 }
4635
4636 /*
4637 * See if the module supports all the stats we want to display.
4638 */
4639 unsupported_flags = cb.cb_flags & ~get_stat_flags(list);
4640 if (unsupported_flags) {
4641 uint64_t f;
4642 int idx;
4643 fprintf(stderr,
4644 gettext("The loaded zfs module doesn't support:"));
4645
4646 /* for each bit set in unsupported_flags */
4647 for (f = unsupported_flags; f; f &= ~(1ULL << idx)) {
4648 idx = lowbit64(f) - 1;
4649 fprintf(stderr, " -%c", flag_to_arg[idx]);
4650 }
4651
02730c33 4652 fprintf(stderr, ". Try running a newer module.\n");
193a37cb
TH
4653 pool_list_free(list);
4654
4655 return (1);
4656 }
4657
34dc7c2f 4658 for (;;) {
34dc7c2f 4659 if ((npools = pool_list_count(list)) == 0)
42cb3819 4660 (void) fprintf(stderr, gettext("no pools available\n"));
5a521059 4661 else {
41092124
HM
4662 /*
4663 * If this is the first iteration and -y was supplied
4664 * we skip any printing.
4665 */
4666 boolean_t skip = (omit_since_boot &&
193a37cb 4667 cb.cb_iteration == 0);
41092124 4668
5a521059
PJ
4669 /*
4670 * Refresh all statistics. This is done as an
4671 * explicit step before calculating the maximum name
4672 * width, so that any * configuration changes are
4673 * properly accounted for.
4674 */
4675 (void) pool_list_iter(list, B_FALSE, refresh_iostat,
193a37cb 4676 &cb);
34dc7c2f 4677
5a521059
PJ
4678 /*
4679 * Iterate over all pools to determine the maximum width
4680 * for the pool / device name column across all pools.
4681 */
4682 cb.cb_namewidth = 0;
4683 (void) pool_list_iter(list, B_FALSE, get_namewidth,
193a37cb 4684 &cb);
34dc7c2f 4685
5a521059
PJ
4686 if (timestamp_fmt != NODATE)
4687 print_timestamp(timestamp_fmt);
428870ff 4688
d6418de0
TH
4689 if (cmd != NULL && cb.cb_verbose &&
4690 !(cb.cb_flags & IOS_ANYHISTO_M)) {
4691 cb.vcdl = all_pools_for_each_vdev_run(argc,
4692 argv, cmd, g_zfs, cb.cb_vdev_names,
4693 cb.cb_vdev_names_count, cb.cb_name_flags);
4694 } else {
4695 cb.vcdl = NULL;
4696 }
4697
5a521059 4698 /*
41092124
HM
4699 * If it's the first time and we're not skipping it,
4700 * or either skip or verbose mode, print the header.
193a37cb
TH
4701 *
4702 * The histogram code explicitly prints its header on
4703 * every vdev, so skip this for histograms.
5a521059 4704 */
193a37cb
TH
4705 if (((++cb.cb_iteration == 1 && !skip) ||
4706 (skip != verbose)) &&
7e945072 4707 (!(cb.cb_flags & IOS_ANYHISTO_M)) &&
193a37cb 4708 !cb.cb_scripted)
5a521059 4709 print_iostat_header(&cb);
34dc7c2f 4710
41092124 4711 if (skip) {
193a37cb 4712 (void) fsleep(interval);
41092124
HM
4713 continue;
4714 }
4715
8720e9e7 4716
193a37cb 4717 pool_list_iter(list, B_FALSE, print_iostat, &cb);
34dc7c2f 4718
5a521059
PJ
4719 /*
4720 * If there's more than one pool, and we're not in
4721 * verbose mode (which prints a separator for us),
4722 * then print a separator.
193a37cb
TH
4723 *
4724 * In addition, if we're printing specific vdevs then
4725 * we also want an ending separator.
5a521059 4726 */
193a37cb 4727 if (((npools > 1 && !verbose &&
7e945072
TH
4728 !(cb.cb_flags & IOS_ANYHISTO_M)) ||
4729 (!(cb.cb_flags & IOS_ANYHISTO_M) &&
193a37cb
TH
4730 cb.cb_vdev_names_count)) &&
4731 !cb.cb_scripted) {
5a521059 4732 print_iostat_separator(&cb);
d6418de0
TH
4733 if (cb.vcdl != NULL)
4734 print_cmd_columns(cb.vcdl, 1);
4735 printf("\n");
193a37cb 4736 }
d6418de0
TH
4737
4738 if (cb.vcdl != NULL)
4739 free_vdev_cmd_data_list(cb.vcdl);
4740
5a521059 4741 }
34dc7c2f
BB
4742
4743 /*
4744 * Flush the output so that redirection to a file isn't buffered
4745 * indefinitely.
4746 */
4747 (void) fflush(stdout);
4748
4749 if (interval == 0)
4750 break;
4751
4752 if (count != 0 && --count == 0)
4753 break;
4754
193a37cb 4755 (void) fsleep(interval);
34dc7c2f
BB
4756 }
4757
4758 pool_list_free(list);
4759
4760 return (ret);
4761}
4762
4763typedef struct list_cbdata {
1bd201e7 4764 boolean_t cb_verbose;
d2f3e292 4765 int cb_name_flags;
1bd201e7 4766 int cb_namewidth;
34dc7c2f 4767 boolean_t cb_scripted;
34dc7c2f 4768 zprop_list_t *cb_proplist;
2a8b84b7 4769 boolean_t cb_literal;
34dc7c2f
BB
4770} list_cbdata_t;
4771
4772/*
4773 * Given a list of columns to display, output appropriate headers for each one.
4774 */
4775static void
1bd201e7 4776print_header(list_cbdata_t *cb)
34dc7c2f 4777{
1bd201e7 4778 zprop_list_t *pl = cb->cb_proplist;
9ae529ec 4779 char headerbuf[ZPOOL_MAXPROPLEN];
34dc7c2f
BB
4780 const char *header;
4781 boolean_t first = B_TRUE;
4782 boolean_t right_justify;
1bd201e7 4783 size_t width = 0;
34dc7c2f
BB
4784
4785 for (; pl != NULL; pl = pl->pl_next) {
1bd201e7
CS
4786 width = pl->pl_width;
4787 if (first && cb->cb_verbose) {
4788 /*
4789 * Reset the width to accommodate the verbose listing
4790 * of devices.
4791 */
4792 width = cb->cb_namewidth;
4793 }
4794
34dc7c2f
BB
4795 if (!first)
4796 (void) printf(" ");
4797 else
4798 first = B_FALSE;
4799
9ae529ec
CS
4800 right_justify = B_FALSE;
4801 if (pl->pl_prop != ZPROP_INVAL) {
4802 header = zpool_prop_column_name(pl->pl_prop);
4803 right_justify = zpool_prop_align_right(pl->pl_prop);
4804 } else {
4805 int i;
4806
4807 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
4808 headerbuf[i] = toupper(pl->pl_user_prop[i]);
4809 headerbuf[i] = '\0';
4810 header = headerbuf;
4811 }
34dc7c2f
BB
4812
4813 if (pl->pl_next == NULL && !right_justify)
4814 (void) printf("%s", header);
4815 else if (right_justify)
1bd201e7 4816 (void) printf("%*s", (int)width, header);
34dc7c2f 4817 else
1bd201e7 4818 (void) printf("%-*s", (int)width, header);
34dc7c2f
BB
4819 }
4820
4821 (void) printf("\n");
4822}
4823
4824/*
4825 * Given a pool and a list of properties, print out all the properties according
4826 * to the described layout.
4827 */
4828static void
1bd201e7 4829print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
34dc7c2f 4830{
1bd201e7 4831 zprop_list_t *pl = cb->cb_proplist;
34dc7c2f
BB
4832 boolean_t first = B_TRUE;
4833 char property[ZPOOL_MAXPROPLEN];
4834 char *propstr;
4835 boolean_t right_justify;
1bd201e7 4836 size_t width;
34dc7c2f
BB
4837
4838 for (; pl != NULL; pl = pl->pl_next) {
1bd201e7
CS
4839
4840 width = pl->pl_width;
4841 if (first && cb->cb_verbose) {
4842 /*
4843 * Reset the width to accommodate the verbose listing
4844 * of devices.
4845 */
4846 width = cb->cb_namewidth;
4847 }
4848
34dc7c2f 4849 if (!first) {
1bd201e7 4850 if (cb->cb_scripted)
34dc7c2f
BB
4851 (void) printf("\t");
4852 else
4853 (void) printf(" ");
4854 } else {
4855 first = B_FALSE;
4856 }
4857
4858 right_justify = B_FALSE;
4859 if (pl->pl_prop != ZPROP_INVAL) {
a05dfd00 4860 if (zpool_get_prop(zhp, pl->pl_prop, property,
2a8b84b7 4861 sizeof (property), NULL, cb->cb_literal) != 0)
34dc7c2f
BB
4862 propstr = "-";
4863 else
4864 propstr = property;
4865
4866 right_justify = zpool_prop_align_right(pl->pl_prop);
9ae529ec
CS
4867 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
4868 zpool_prop_unsupported(pl->pl_user_prop)) &&
4869 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
4870 sizeof (property)) == 0) {
4871 propstr = property;
34dc7c2f
BB
4872 } else {
4873 propstr = "-";
4874 }
4875
34dc7c2f
BB
4876
4877 /*
4878 * If this is being called in scripted mode, or if this is the
4879 * last column and it is left-justified, don't include a width
4880 * format specifier.
4881 */
1bd201e7 4882 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
34dc7c2f
BB
4883 (void) printf("%s", propstr);
4884 else if (right_justify)
1bd201e7 4885 (void) printf("%*s", (int)width, propstr);
34dc7c2f 4886 else
1bd201e7 4887 (void) printf("%-*s", (int)width, propstr);
34dc7c2f
BB
4888 }
4889
4890 (void) printf("\n");
4891}
4892
1bd201e7 4893static void
a05dfd00 4894print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
bc2d8093 4895 boolean_t valid, enum zfs_nicenum_format format)
1bd201e7
CS
4896{
4897 char propval[64];
4898 boolean_t fixed;
4899 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
4900
a05dfd00
GW
4901 switch (prop) {
4902 case ZPOOL_PROP_EXPANDSZ:
4903 if (value == 0)
4904 (void) strlcpy(propval, "-", sizeof (propval));
4905 else
bc2d8093
CE
4906 zfs_nicenum_format(value, propval, sizeof (propval),
4907 format);
a05dfd00
GW
4908 break;
4909 case ZPOOL_PROP_FRAGMENTATION:
4910 if (value == ZFS_FRAG_INVALID) {
4911 (void) strlcpy(propval, "-", sizeof (propval));
bc2d8093
CE
4912 } else if (format == ZFS_NICENUM_RAW) {
4913 (void) snprintf(propval, sizeof (propval), "%llu",
4914 (unsigned long long)value);
a05dfd00
GW
4915 } else {
4916 (void) snprintf(propval, sizeof (propval), "%llu%%",
4917 (unsigned long long)value);
4918 }
4919 break;
4920 case ZPOOL_PROP_CAPACITY:
bc2d8093
CE
4921 if (format == ZFS_NICENUM_RAW)
4922 (void) snprintf(propval, sizeof (propval), "%llu",
4923 (unsigned long long)value);
4924 else
4925 (void) snprintf(propval, sizeof (propval), "%llu%%",
4926 (unsigned long long)value);
a05dfd00
GW
4927 break;
4928 default:
bc2d8093 4929 zfs_nicenum_format(value, propval, sizeof (propval), format);
a05dfd00
GW
4930 }
4931
4932 if (!valid)
4933 (void) strlcpy(propval, "-", sizeof (propval));
1bd201e7
CS
4934
4935 if (scripted)
4936 (void) printf("\t%s", propval);
4937 else
4938 (void) printf(" %*s", (int)width, propval);
4939}
4940
4941void
4942print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
4943 list_cbdata_t *cb, int depth)
4944{
4945 nvlist_t **child;
4946 vdev_stat_t *vs;
4947 uint_t c, children;
4948 char *vname;
4949 boolean_t scripted = cb->cb_scripted;
8e4c5c9a
JWK
4950 uint64_t islog = B_FALSE;
4951 boolean_t haslog = B_FALSE;
4952 char *dashes = "%-*s - - - - - -\n";
1bd201e7
CS
4953
4954 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
4955 (uint64_t **)&vs, &c) == 0);
4956
4957 if (name != NULL) {
a05dfd00
GW
4958 boolean_t toplevel = (vs->vs_space != 0);
4959 uint64_t cap;
bc2d8093
CE
4960 enum zfs_nicenum_format format;
4961
4962 if (cb->cb_literal)
4963 format = ZFS_NICENUM_RAW;
4964 else
4965 format = ZFS_NICENUM_1024;
a05dfd00 4966
1bd201e7
CS
4967 if (scripted)
4968 (void) printf("\t%s", name);
4969 else if (strlen(name) + depth > cb->cb_namewidth)
4970 (void) printf("%*s%s", depth, "", name);
4971 else
4972 (void) printf("%*s%s%*s", depth, "", name,
4973 (int)(cb->cb_namewidth - strlen(name) - depth), "");
4974
a05dfd00
GW
4975 /*
4976 * Print the properties for the individual vdevs. Some
4977 * properties are only applicable to toplevel vdevs. The
4978 * 'toplevel' boolean value is passed to the print_one_column()
4979 * to indicate that the value is valid.
4980 */
4981 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
bc2d8093 4982 toplevel, format);
a05dfd00 4983 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
bc2d8093 4984 toplevel, format);
a05dfd00 4985 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
bc2d8093 4986 scripted, toplevel, format);
a05dfd00 4987 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
bc2d8093 4988 B_TRUE, format);
a05dfd00
GW
4989 print_one_column(ZPOOL_PROP_FRAGMENTATION,
4990 vs->vs_fragmentation, scripted,
bc2d8093
CE
4991 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel),
4992 format);
a05dfd00
GW
4993 cap = (vs->vs_space == 0) ? 0 :
4994 (vs->vs_alloc * 100 / vs->vs_space);
bc2d8093
CE
4995 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel,
4996 format);
1bd201e7
CS
4997 (void) printf("\n");
4998 }
4999
5000 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
5001 &child, &children) != 0)
5002 return;
5003
5004 for (c = 0; c < children; c++) {
5005 uint64_t ishole = B_FALSE;
5006
5007 if (nvlist_lookup_uint64(child[c],
5008 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
5009 continue;
5010
8e4c5c9a
JWK
5011 if (nvlist_lookup_uint64(child[c],
5012 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
5013 haslog = B_TRUE;
5014 continue;
5015 }
5016
d2f3e292
RY
5017 vname = zpool_vdev_name(g_zfs, zhp, child[c],
5018 cb->cb_name_flags);
1bd201e7
CS
5019 print_list_stats(zhp, vname, child[c], cb, depth + 2);
5020 free(vname);
5021 }
5022
8e4c5c9a
JWK
5023 if (haslog == B_TRUE) {
5024 /* LINTED E_SEC_PRINTF_VAR_FMT */
5025 (void) printf(dashes, cb->cb_namewidth, "log");
5026 for (c = 0; c < children; c++) {
5027 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
5028 &islog) != 0 || !islog)
5029 continue;
d2f3e292
RY
5030 vname = zpool_vdev_name(g_zfs, zhp, child[c],
5031 cb->cb_name_flags);
8e4c5c9a
JWK
5032 print_list_stats(zhp, vname, child[c], cb, depth + 2);
5033 free(vname);
5034 }
5035 }
5036
1bd201e7 5037 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
8e4c5c9a
JWK
5038 &child, &children) == 0 && children > 0) {
5039 /* LINTED E_SEC_PRINTF_VAR_FMT */
5040 (void) printf(dashes, cb->cb_namewidth, "cache");
5041 for (c = 0; c < children; c++) {
d2f3e292
RY
5042 vname = zpool_vdev_name(g_zfs, zhp, child[c],
5043 cb->cb_name_flags);
8e4c5c9a
JWK
5044 print_list_stats(zhp, vname, child[c], cb, depth + 2);
5045 free(vname);
5046 }
5047 }
1bd201e7 5048
8e4c5c9a
JWK
5049 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
5050 &children) == 0 && children > 0) {
5051 /* LINTED E_SEC_PRINTF_VAR_FMT */
5052 (void) printf(dashes, cb->cb_namewidth, "spare");
1bd201e7 5053 for (c = 0; c < children; c++) {
d2f3e292
RY
5054 vname = zpool_vdev_name(g_zfs, zhp, child[c],
5055 cb->cb_name_flags);
1bd201e7
CS
5056 print_list_stats(zhp, vname, child[c], cb, depth + 2);
5057 free(vname);
5058 }
5059 }
5060}
5061
5062
34dc7c2f
BB
5063/*
5064 * Generic callback function to list a pool.
5065 */
5066int
5067list_callback(zpool_handle_t *zhp, void *data)
5068{
5069 list_cbdata_t *cbp = data;
1bd201e7
CS
5070 nvlist_t *config;
5071 nvlist_t *nvroot;
34dc7c2f 5072
1bd201e7 5073 config = zpool_get_config(zhp, NULL);
34dc7c2f 5074
1bd201e7
CS
5075 print_pool(zhp, cbp);
5076 if (!cbp->cb_verbose)
5077 return (0);
5078
5079 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5080 &nvroot) == 0);
5081 print_list_stats(zhp, NULL, nvroot, cbp, 0);
34dc7c2f
BB
5082
5083 return (0);
5084}
5085
5086/*
2a8b84b7 5087 * zpool list [-gHLpP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
34dc7c2f 5088 *
d2f3e292 5089 * -g Display guid for individual vdev name.
34dc7c2f
BB
5090 * -H Scripted mode. Don't display headers, and separate properties
5091 * by a single tab.
d2f3e292 5092 * -L Follow links when resolving vdev path name.
34dc7c2f 5093 * -o List of properties to display. Defaults to
a05dfd00
GW
5094 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
5095 * "dedupratio,health,altroot"
2a8b84b7 5096 * -p Display values in parsable (exact) format.
a77f29f9 5097 * -P Display full path for vdev name.
428870ff 5098 * -T Display a timestamp in date(1) or Unix format
34dc7c2f
BB
5099 *
5100 * List all pools in the system, whether or not they're healthy. Output space
5101 * statistics for each one, as well as health status summary.
5102 */
5103int
5104zpool_do_list(int argc, char **argv)
5105{
5106 int c;
cd72af9c 5107 int ret = 0;
34dc7c2f
BB
5108 list_cbdata_t cb = { 0 };
5109 static char default_props[] =
a05dfd00 5110 "name,size,allocated,free,expandsize,fragmentation,capacity,"
f3a7f661 5111 "dedupratio,health,altroot";
34dc7c2f 5112 char *props = default_props;
193a37cb
TH
5113 float interval = 0;
5114 unsigned long count = 0;
1bd201e7
CS
5115 zpool_list_t *list;
5116 boolean_t first = B_TRUE;
34dc7c2f
BB
5117
5118 /* check options */
2a8b84b7 5119 while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
34dc7c2f 5120 switch (c) {
d2f3e292
RY
5121 case 'g':
5122 cb.cb_name_flags |= VDEV_NAME_GUID;
5123 break;
34dc7c2f
BB
5124 case 'H':
5125 cb.cb_scripted = B_TRUE;
5126 break;
d2f3e292
RY
5127 case 'L':
5128 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
5129 break;
34dc7c2f
BB
5130 case 'o':
5131 props = optarg;
5132 break;
a77f29f9 5133 case 'P':
d2f3e292
RY
5134 cb.cb_name_flags |= VDEV_NAME_PATH;
5135 break;
2a8b84b7
AS
5136 case 'p':
5137 cb.cb_literal = B_TRUE;
5138 break;
428870ff
BB
5139 case 'T':
5140 get_timestamp_arg(*optarg);
5141 break;
1bd201e7
CS
5142 case 'v':
5143 cb.cb_verbose = B_TRUE;
5144 break;
34dc7c2f
BB
5145 case ':':
5146 (void) fprintf(stderr, gettext("missing argument for "
5147 "'%c' option\n"), optopt);
5148 usage(B_FALSE);
5149 break;
5150 case '?':
5151 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5152 optopt);
5153 usage(B_FALSE);
5154 }
5155 }
5156
5157 argc -= optind;
5158 argv += optind;
5159
428870ff
BB
5160 get_interval_count(&argc, argv, &interval, &count);
5161
34dc7c2f
BB
5162 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
5163 usage(B_FALSE);
5164
428870ff 5165 for (;;) {
3e43edd2
GW
5166 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
5167 &ret)) == NULL)
5168 return (1);
1bd201e7
CS
5169
5170 if (pool_list_count(list) == 0)
5171 break;
34dc7c2f 5172
428870ff
BB
5173 if (timestamp_fmt != NODATE)
5174 print_timestamp(timestamp_fmt);
34dc7c2f 5175
1bd201e7
CS
5176 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
5177 print_header(&cb);
5178 first = B_FALSE;
428870ff 5179 }
1bd201e7 5180 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
428870ff
BB
5181
5182 if (interval == 0)
5183 break;
5184
5185 if (count != 0 && --count == 0)
5186 break;
5187
3e43edd2 5188 pool_list_free(list);
193a37cb 5189 (void) fsleep(interval);
34dc7c2f
BB
5190 }
5191
3e43edd2
GW
5192 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
5193 (void) printf(gettext("no pools available\n"));
5194 ret = 0;
5195 }
5196
5197 pool_list_free(list);
428870ff 5198 zprop_free_list(cb.cb_proplist);
34dc7c2f
BB
5199 return (ret);
5200}
5201
34dc7c2f
BB
5202static int
5203zpool_do_attach_or_replace(int argc, char **argv, int replacing)
5204{
5205 boolean_t force = B_FALSE;
5206 int c;
5207 nvlist_t *nvroot;
5208 char *poolname, *old_disk, *new_disk;
5209 zpool_handle_t *zhp;
df831108
CP
5210 nvlist_t *props = NULL;
5211 char *propval;
34dc7c2f
BB
5212 int ret;
5213
5214 /* check options */
4588bf57 5215 while ((c = getopt(argc, argv, "fo:")) != -1) {
34dc7c2f
BB
5216 switch (c) {
5217 case 'f':
5218 force = B_TRUE;
5219 break;
df831108
CP
5220 case 'o':
5221 if ((propval = strchr(optarg, '=')) == NULL) {
5222 (void) fprintf(stderr, gettext("missing "
5223 "'=' for -o option\n"));
5224 usage(B_FALSE);
5225 }
5226 *propval = '\0';
5227 propval++;
5228
5229 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
5230 (add_prop_list(optarg, propval, &props, B_TRUE)))
5231 usage(B_FALSE);
5232 break;
34dc7c2f
BB
5233 case '?':
5234 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5235 optopt);
5236 usage(B_FALSE);
5237 }
5238 }
5239
5240 argc -= optind;
5241 argv += optind;
5242
5243 /* get pool name and check number of arguments */
5244 if (argc < 1) {
5245 (void) fprintf(stderr, gettext("missing pool name argument\n"));
5246 usage(B_FALSE);
5247 }
5248
5249 poolname = argv[0];
5250
5251 if (argc < 2) {
5252 (void) fprintf(stderr,
5253 gettext("missing <device> specification\n"));
5254 usage(B_FALSE);
5255 }
5256
5257 old_disk = argv[1];
5258
5259 if (argc < 3) {
5260 if (!replacing) {
5261 (void) fprintf(stderr,
5262 gettext("missing <new_device> specification\n"));
5263 usage(B_FALSE);
5264 }
5265 new_disk = old_disk;
5266 argc -= 1;
5267 argv += 1;
5268 } else {
5269 new_disk = argv[2];
5270 argc -= 2;
5271 argv += 2;
5272 }
5273
5274 if (argc > 1) {
5275 (void) fprintf(stderr, gettext("too many arguments\n"));
5276 usage(B_FALSE);
5277 }
5278
a425f5bf 5279 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) {
5280 nvlist_free(props);
34dc7c2f 5281 return (1);
a425f5bf 5282 }
34dc7c2f
BB
5283
5284 if (zpool_get_config(zhp, NULL) == NULL) {
5285 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
5286 poolname);
5287 zpool_close(zhp);
a425f5bf 5288 nvlist_free(props);
34dc7c2f
BB
5289 return (1);
5290 }
5291
dddef7d6 5292 /* unless manually specified use "ashift" pool property (if set) */
5293 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
5294 int intval;
5295 zprop_source_t src;
5296 char strval[ZPOOL_MAXPROPLEN];
5297
5298 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
5299 if (src != ZPROP_SRC_DEFAULT) {
5300 (void) sprintf(strval, "%" PRId32, intval);
5301 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
5302 &props, B_TRUE) == 0);
5303 }
5304 }
5305
df831108 5306 nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
b128c09f 5307 argc, argv);
34dc7c2f
BB
5308 if (nvroot == NULL) {
5309 zpool_close(zhp);
a425f5bf 5310 nvlist_free(props);
34dc7c2f
BB
5311 return (1);
5312 }
5313
5314 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
5315
a425f5bf 5316 nvlist_free(props);
34dc7c2f
BB
5317 nvlist_free(nvroot);
5318 zpool_close(zhp);
5319
5320 return (ret);
5321}
5322
5323/*
5324 * zpool replace [-f] <pool> <device> <new_device>
5325 *
5326 * -f Force attach, even if <new_device> appears to be in use.
5327 *
5328 * Replace <device> with <new_device>.
5329 */
5330/* ARGSUSED */
5331int
5332zpool_do_replace(int argc, char **argv)
5333{
5334 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
5335}
5336
5337/*
df831108 5338 * zpool attach [-f] [-o property=value] <pool> <device> <new_device>
34dc7c2f
BB
5339 *
5340 * -f Force attach, even if <new_device> appears to be in use.
df831108 5341 * -o Set property=value.
34dc7c2f
BB
5342 *
5343 * Attach <new_device> to the mirror containing <device>. If <device> is not
5344 * part of a mirror, then <device> will be transformed into a mirror of
5345 * <device> and <new_device>. In either case, <new_device> will begin life
5346 * with a DTL of [0, now], and will immediately begin to resilver itself.
5347 */
5348int
5349zpool_do_attach(int argc, char **argv)
5350{
5351 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
5352}
5353
5354/*
5355 * zpool detach [-f] <pool> <device>
5356 *
5357 * -f Force detach of <device>, even if DTLs argue against it
5358 * (not supported yet)
5359 *
5360 * Detach a device from a mirror. The operation will be refused if <device>
5361 * is the last device in the mirror, or if the DTLs indicate that this device
5362 * has the only valid copy of some data.
5363 */
5364/* ARGSUSED */
5365int
5366zpool_do_detach(int argc, char **argv)
5367{
5368 int c;
5369 char *poolname, *path;
5370 zpool_handle_t *zhp;
5371 int ret;
5372
5373 /* check options */
5374 while ((c = getopt(argc, argv, "f")) != -1) {
5375 switch (c) {
5376 case 'f':
5377 case '?':
5378 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5379 optopt);
5380 usage(B_FALSE);
5381 }
5382 }
5383
5384 argc -= optind;
5385 argv += optind;
5386
5387 /* get pool name and check number of arguments */
5388 if (argc < 1) {
5389 (void) fprintf(stderr, gettext("missing pool name argument\n"));
5390 usage(B_FALSE);
5391 }
5392
5393 if (argc < 2) {
5394 (void) fprintf(stderr,
5395 gettext("missing <device> specification\n"));
5396 usage(B_FALSE);
5397 }
5398
5399 poolname = argv[0];
5400 path = argv[1];
5401
5402 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5403 return (1);
5404
5405 ret = zpool_vdev_detach(zhp, path);
5406
5407 zpool_close(zhp);
5408
5409 return (ret);
5410}
5411
428870ff 5412/*
a77f29f9 5413 * zpool split [-gLnP] [-o prop=val] ...
428870ff
BB
5414 * [-o mntopt] ...
5415 * [-R altroot] <pool> <newpool> [<device> ...]
5416 *
d2f3e292
RY
5417 * -g Display guid for individual vdev name.
5418 * -L Follow links when resolving vdev path name.
428870ff
BB
5419 * -n Do not split the pool, but display the resulting layout if
5420 * it were to be split.
5421 * -o Set property=value, or set mount options.
a77f29f9 5422 * -P Display full path for vdev name.
428870ff 5423 * -R Mount the split-off pool under an alternate root.
b5256303 5424 * -l Load encryption keys while importing.
428870ff
BB
5425 *
5426 * Splits the named pool and gives it the new pool name. Devices to be split
5427 * off may be listed, provided that no more than one device is specified
5428 * per top-level vdev mirror. The newly split pool is left in an exported
5429 * state unless -R is specified.
5430 *
5431 * Restrictions: the top-level of the pool pool must only be made up of
5432 * mirrors; all devices in the pool must be healthy; no device may be
5433 * undergoing a resilvering operation.
5434 */
5435int
5436zpool_do_split(int argc, char **argv)
5437{
5438 char *srcpool, *newpool, *propval;
5439 char *mntopts = NULL;
5440 splitflags_t flags;
5441 int c, ret = 0;
b5256303 5442 boolean_t loadkeys = B_FALSE;
428870ff
BB
5443 zpool_handle_t *zhp;
5444 nvlist_t *config, *props = NULL;
5445
5446 flags.dryrun = B_FALSE;
5447 flags.import = B_FALSE;
d2f3e292 5448 flags.name_flags = 0;
428870ff
BB
5449
5450 /* check options */
b5256303 5451 while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) {
428870ff 5452 switch (c) {
d2f3e292
RY
5453 case 'g':
5454 flags.name_flags |= VDEV_NAME_GUID;
5455 break;
5456 case 'L':
5457 flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
5458 break;
428870ff
BB
5459 case 'R':
5460 flags.import = B_TRUE;
5461 if (add_prop_list(
5462 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
5463 &props, B_TRUE) != 0) {
8a5fc748 5464 nvlist_free(props);
428870ff
BB
5465 usage(B_FALSE);
5466 }
5467 break;
b5256303
TC
5468 case 'l':
5469 loadkeys = B_TRUE;
5470 break;
428870ff
BB
5471 case 'n':
5472 flags.dryrun = B_TRUE;
5473 break;
5474 case 'o':
5475 if ((propval = strchr(optarg, '=')) != NULL) {
5476 *propval = '\0';
5477 propval++;
5478 if (add_prop_list(optarg, propval,
5479 &props, B_TRUE) != 0) {
8a5fc748 5480 nvlist_free(props);
428870ff
BB
5481 usage(B_FALSE);
5482 }
5483 } else {
5484 mntopts = optarg;
5485 }
5486 break;
a77f29f9 5487 case 'P':
d2f3e292
RY
5488 flags.name_flags |= VDEV_NAME_PATH;
5489 break;
428870ff
BB
5490 case ':':
5491 (void) fprintf(stderr, gettext("missing argument for "
5492 "'%c' option\n"), optopt);
5493 usage(B_FALSE);
5494 break;
5495 case '?':
5496 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5497 optopt);
5498 usage(B_FALSE);
5499 break;
5500 }
5501 }
5502
5503 if (!flags.import && mntopts != NULL) {
5504 (void) fprintf(stderr, gettext("setting mntopts is only "
5505 "valid when importing the pool\n"));
5506 usage(B_FALSE);
5507 }
5508
b5256303
TC
5509 if (!flags.import && loadkeys) {
5510 (void) fprintf(stderr, gettext("loading keys is only "
5511 "valid when importing the pool\n"));
5512 usage(B_FALSE);
5513 }
5514
428870ff
BB
5515 argc -= optind;
5516 argv += optind;
5517
5518 if (argc < 1) {
5519 (void) fprintf(stderr, gettext("Missing pool name\n"));
5520 usage(B_FALSE);
5521 }
5522 if (argc < 2) {
5523 (void) fprintf(stderr, gettext("Missing new pool name\n"));
5524 usage(B_FALSE);
5525 }
5526
5527 srcpool = argv[0];
5528 newpool = argv[1];
5529
5530 argc -= 2;
5531 argv += 2;
5532
a425f5bf 5533 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) {
5534 nvlist_free(props);
428870ff 5535 return (1);
a425f5bf 5536 }
428870ff
BB
5537
5538 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
5539 if (config == NULL) {
5540 ret = 1;
5541 } else {
5542 if (flags.dryrun) {
5543 (void) printf(gettext("would create '%s' with the "
5544 "following layout:\n\n"), newpool);
d2f3e292
RY
5545 print_vdev_tree(NULL, newpool, config, 0, B_FALSE,
5546 flags.name_flags);
428870ff 5547 }
428870ff
BB
5548 }
5549
5550 zpool_close(zhp);
5551
a425f5bf 5552 if (ret != 0 || flags.dryrun || !flags.import) {
5553 nvlist_free(config);
5554 nvlist_free(props);
428870ff 5555 return (ret);
a425f5bf 5556 }
428870ff
BB
5557
5558 /*
5559 * The split was successful. Now we need to open the new
5560 * pool and import it.
5561 */
a425f5bf 5562 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) {
5563 nvlist_free(config);
5564 nvlist_free(props);
428870ff 5565 return (1);
a425f5bf 5566 }
b5256303
TC
5567
5568 if (loadkeys) {
5569 ret = zfs_crypto_attempt_load_keys(g_zfs, newpool);
5570 if (ret != 0)
5571 ret = 1;
5572 }
5573
428870ff
BB
5574 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
5575 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
5576 ret = 1;
af909a10 5577 (void) fprintf(stderr, gettext("Split was successful, but "
428870ff
BB
5578 "the datasets could not all be mounted\n"));
5579 (void) fprintf(stderr, gettext("Try doing '%s' with a "
5580 "different altroot\n"), "zpool import");
5581 }
5582 zpool_close(zhp);
a425f5bf 5583 nvlist_free(config);
5584 nvlist_free(props);
428870ff
BB
5585
5586 return (ret);
5587}
5588
5589
5590
34dc7c2f
BB
5591/*
5592 * zpool online <pool> <device> ...
5593 */
5594int
5595zpool_do_online(int argc, char **argv)
5596{
5597 int c, i;
5598 char *poolname;
5599 zpool_handle_t *zhp;
5600 int ret = 0;
5601 vdev_state_t newstate;
9babb374 5602 int flags = 0;
34dc7c2f
BB
5603
5604 /* check options */
9babb374 5605 while ((c = getopt(argc, argv, "et")) != -1) {
34dc7c2f 5606 switch (c) {
9babb374
BB
5607 case 'e':
5608 flags |= ZFS_ONLINE_EXPAND;
5609 break;
34dc7c2f
BB
5610 case 't':
5611 case '?':
5612 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5613 optopt);
5614 usage(B_FALSE);
5615 }
5616 }
5617
5618 argc -= optind;
5619 argv += optind;
5620
5621 /* get pool name and check number of arguments */
5622 if (argc < 1) {
5623 (void) fprintf(stderr, gettext("missing pool name\n"));
5624 usage(B_FALSE);
5625 }
5626 if (argc < 2) {
5627 (void) fprintf(stderr, gettext("missing device name\n"));
5628 usage(B_FALSE);
5629 }
5630
5631 poolname = argv[0];
5632
5633 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5634 return (1);
5635
5636 for (i = 1; i < argc; i++) {
9babb374 5637 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
34dc7c2f
BB
5638 if (newstate != VDEV_STATE_HEALTHY) {
5639 (void) printf(gettext("warning: device '%s' "
5640 "onlined, but remains in faulted state\n"),
5641 argv[i]);
5642 if (newstate == VDEV_STATE_FAULTED)
5643 (void) printf(gettext("use 'zpool "
5644 "clear' to restore a faulted "
5645 "device\n"));
5646 else
5647 (void) printf(gettext("use 'zpool "
5648 "replace' to replace devices "
5649 "that are no longer present\n"));
5650 }
5651 } else {
5652 ret = 1;
5653 }
5654 }
5655
5656 zpool_close(zhp);
5657
5658 return (ret);
5659}
5660
5661/*
5662 * zpool offline [-ft] <pool> <device> ...
5663 *
4a283c7f 5664 * -f Force the device into a faulted state.
34dc7c2f 5665 *
4a283c7f 5666 * -t Only take the device off-line temporarily. The offline/faulted
34dc7c2f
BB
5667 * state will not be persistent across reboots.
5668 */
5669/* ARGSUSED */
5670int
5671zpool_do_offline(int argc, char **argv)
5672{
5673 int c, i;
5674 char *poolname;
5675 zpool_handle_t *zhp;
5676 int ret = 0;
5677 boolean_t istmp = B_FALSE;
4a283c7f 5678 boolean_t fault = B_FALSE;
34dc7c2f
BB
5679
5680 /* check options */
5681 while ((c = getopt(argc, argv, "ft")) != -1) {
5682 switch (c) {
4a283c7f
TH
5683 case 'f':
5684 fault = B_TRUE;
5685 break;
34dc7c2f
BB
5686 case 't':
5687 istmp = B_TRUE;
5688 break;
34dc7c2f
BB
5689 case '?':
5690 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5691 optopt);
5692 usage(B_FALSE);
5693 }
5694 }
5695
5696 argc -= optind;
5697 argv += optind;
5698
5699 /* get pool name and check number of arguments */
5700 if (argc < 1) {
5701 (void) fprintf(stderr, gettext("missing pool name\n"));
5702 usage(B_FALSE);
5703 }
5704 if (argc < 2) {
5705 (void) fprintf(stderr, gettext("missing device name\n"));
5706 usage(B_FALSE);
5707 }
5708
5709 poolname = argv[0];
5710
5711 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5712 return (1);
5713
5714 for (i = 1; i < argc; i++) {
4a283c7f
TH
5715 if (fault) {
5716 uint64_t guid = zpool_vdev_path_to_guid(zhp, argv[i]);
5717 vdev_aux_t aux;
5718 if (istmp == B_FALSE) {
5719 /* Force the fault to persist across imports */
5720 aux = VDEV_AUX_EXTERNAL_PERSIST;
5721 } else {
5722 aux = VDEV_AUX_EXTERNAL;
5723 }
5724
5725 if (guid == 0 || zpool_vdev_fault(zhp, guid, aux) != 0)
5726 ret = 1;
5727 } else {
5728 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
5729 ret = 1;
5730 }
34dc7c2f
BB
5731 }
5732
5733 zpool_close(zhp);
5734
5735 return (ret);
5736}
5737
5738/*
5739 * zpool clear <pool> [device]
5740 *
5741 * Clear all errors associated with a pool or a particular device.
5742 */
5743int
5744zpool_do_clear(int argc, char **argv)
5745{
428870ff 5746 int c;
34dc7c2f 5747 int ret = 0;
428870ff
BB
5748 boolean_t dryrun = B_FALSE;
5749 boolean_t do_rewind = B_FALSE;
5750 boolean_t xtreme_rewind = B_FALSE;
5751 uint32_t rewind_policy = ZPOOL_NO_REWIND;
5752 nvlist_t *policy = NULL;
34dc7c2f
BB
5753 zpool_handle_t *zhp;
5754 char *pool, *device;
5755
428870ff
BB
5756 /* check options */
5757 while ((c = getopt(argc, argv, "FnX")) != -1) {
5758 switch (c) {
5759 case 'F':
5760 do_rewind = B_TRUE;
5761 break;
5762 case 'n':
5763 dryrun = B_TRUE;
5764 break;
5765 case 'X':
5766 xtreme_rewind = B_TRUE;
5767 break;
5768 case '?':
5769 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5770 optopt);
5771 usage(B_FALSE);
5772 }
5773 }
5774
5775 argc -= optind;
5776 argv += optind;
5777
5778 if (argc < 1) {
34dc7c2f
BB
5779 (void) fprintf(stderr, gettext("missing pool name\n"));
5780 usage(B_FALSE);
5781 }
5782
428870ff 5783 if (argc > 2) {
34dc7c2f
BB
5784 (void) fprintf(stderr, gettext("too many arguments\n"));
5785 usage(B_FALSE);
5786 }
5787
428870ff
BB
5788 if ((dryrun || xtreme_rewind) && !do_rewind) {
5789 (void) fprintf(stderr,
5790 gettext("-n or -X only meaningful with -F\n"));
5791 usage(B_FALSE);
5792 }
5793 if (dryrun)
5794 rewind_policy = ZPOOL_TRY_REWIND;
5795 else if (do_rewind)
5796 rewind_policy = ZPOOL_DO_REWIND;
5797 if (xtreme_rewind)
5798 rewind_policy |= ZPOOL_EXTREME_REWIND;
5799
5800 /* In future, further rewind policy choices can be passed along here */
5801 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
5802 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
5803 return (1);
5804
5805 pool = argv[0];
5806 device = argc == 2 ? argv[1] : NULL;
34dc7c2f 5807
428870ff
BB
5808 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
5809 nvlist_free(policy);
34dc7c2f 5810 return (1);
428870ff 5811 }
34dc7c2f 5812
428870ff 5813 if (zpool_clear(zhp, device, policy) != 0)
34dc7c2f
BB
5814 ret = 1;
5815
5816 zpool_close(zhp);
5817
428870ff
BB
5818 nvlist_free(policy);
5819
34dc7c2f
BB
5820 return (ret);
5821}
5822
3541dc6d
GA
5823/*
5824 * zpool reguid <pool>
5825 */
5826int
5827zpool_do_reguid(int argc, char **argv)
5828{
5829 int c;
5830 char *poolname;
5831 zpool_handle_t *zhp;
5832 int ret = 0;
5833
5834 /* check options */
5835 while ((c = getopt(argc, argv, "")) != -1) {
5836 switch (c) {
5837 case '?':
5838 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5839 optopt);
5840 usage(B_FALSE);
5841 }
5842 }
5843
5844 argc -= optind;
5845 argv += optind;
5846
5847 /* get pool name and check number of arguments */
5848 if (argc < 1) {
5849 (void) fprintf(stderr, gettext("missing pool name\n"));
5850 usage(B_FALSE);
5851 }
5852
5853 if (argc > 1) {
5854 (void) fprintf(stderr, gettext("too many arguments\n"));
5855 usage(B_FALSE);
5856 }
5857
5858 poolname = argv[0];
5859 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5860 return (1);
5861
5862 ret = zpool_reguid(zhp);
5863
5864 zpool_close(zhp);
5865 return (ret);
5866}
5867
5868
1bd201e7
CS
5869/*
5870 * zpool reopen <pool>
5871 *
5872 * Reopen the pool so that the kernel can update the sizes of all vdevs.
1bd201e7
CS
5873 */
5874int
5875zpool_do_reopen(int argc, char **argv)
5876{
5853fe79 5877 int c;
1bd201e7 5878 int ret = 0;
d3f2cd7e 5879 boolean_t scrub_restart = B_TRUE;
1bd201e7 5880
5853fe79 5881 /* check options */
d3f2cd7e 5882 while ((c = getopt(argc, argv, "n")) != -1) {
5853fe79 5883 switch (c) {
d3f2cd7e
AB
5884 case 'n':
5885 scrub_restart = B_FALSE;
5886 break;
5853fe79
GW
5887 case '?':
5888 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5889 optopt);
5890 usage(B_FALSE);
5891 }
5892 }
5893
d3f2cd7e
AB
5894 argc -= optind;
5895 argv += optind;
1bd201e7 5896
d3f2cd7e
AB
5897 /* if argc == 0 we will execute zpool_reopen_one on all pools */
5898 ret = for_each_pool(argc, argv, B_TRUE, NULL, zpool_reopen_one,
5899 &scrub_restart);
1bd201e7 5900
1bd201e7
CS
5901 return (ret);
5902}
5903
34dc7c2f
BB
5904typedef struct scrub_cbdata {
5905 int cb_type;
5906 int cb_argc;
5907 char **cb_argv;
0ea05c64 5908 pool_scrub_cmd_t cb_scrub_cmd;
34dc7c2f
BB
5909} scrub_cbdata_t;
5910
5911int
5912scrub_callback(zpool_handle_t *zhp, void *data)
5913{
5914 scrub_cbdata_t *cb = data;
5915 int err;
5916
5917 /*
5918 * Ignore faulted pools.
5919 */
5920 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5921 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
5922 "currently unavailable\n"), zpool_get_name(zhp));
5923 return (1);
5924 }
5925
0ea05c64 5926 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
34dc7c2f
BB
5927
5928 return (err != 0);
5929}
5930
5931/*
0ea05c64 5932 * zpool scrub [-s | -p] <pool> ...
34dc7c2f
BB
5933 *
5934 * -s Stop. Stops any in-progress scrub.
0ea05c64 5935 * -p Pause. Pause in-progress scrub.
34dc7c2f
BB
5936 */
5937int
5938zpool_do_scrub(int argc, char **argv)
5939{
5940 int c;
5941 scrub_cbdata_t cb;
5942
428870ff 5943 cb.cb_type = POOL_SCAN_SCRUB;
0ea05c64 5944 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
34dc7c2f
BB
5945
5946 /* check options */
0ea05c64 5947 while ((c = getopt(argc, argv, "sp")) != -1) {
34dc7c2f
BB
5948 switch (c) {
5949 case 's':
428870ff 5950 cb.cb_type = POOL_SCAN_NONE;
34dc7c2f 5951 break;
0ea05c64
AP
5952 case 'p':
5953 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
5954 break;
34dc7c2f
BB
5955 case '?':
5956 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5957 optopt);
5958 usage(B_FALSE);
5959 }
5960 }
5961
0ea05c64
AP
5962 if (cb.cb_type == POOL_SCAN_NONE &&
5963 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
5964 (void) fprintf(stderr, gettext("invalid option combination: "
5965 "-s and -p are mutually exclusive\n"));
5966 usage(B_FALSE);
5967 }
5968
34dc7c2f
BB
5969 cb.cb_argc = argc;
5970 cb.cb_argv = argv;
5971 argc -= optind;
5972 argv += optind;
5973
5974 if (argc < 1) {
5975 (void) fprintf(stderr, gettext("missing pool name argument\n"));
5976 usage(B_FALSE);
5977 }
5978
5979 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
5980}
5981
34dc7c2f
BB
5982/*
5983 * Print out detailed scrub status.
5984 */
5985void
428870ff 5986print_scan_status(pool_scan_stat_t *ps)
34dc7c2f 5987{
0ea05c64 5988 time_t start, end, pause;
d4a72f23
TC
5989 uint64_t total_secs_left;
5990 uint64_t elapsed, secs_left, mins_left, hours_left, days_left;
5991 uint64_t pass_scanned, scanned, pass_issued, issued, total;
0cf3430d 5992 uint64_t scan_rate, issue_rate;
34dc7c2f 5993 double fraction_done;
d4a72f23
TC
5994 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
5995 char srate_buf[7], irate_buf[7];
34dc7c2f 5996
24024589 5997 (void) printf(gettext(" scan: "));
34dc7c2f 5998
428870ff
BB
5999 /* If there's never been a scan, there's not much to say. */
6000 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
6001 ps->pss_func >= POOL_SCAN_FUNCS) {
34dc7c2f
BB
6002 (void) printf(gettext("none requested\n"));
6003 return;
6004 }
6005
428870ff
BB
6006 start = ps->pss_start_time;
6007 end = ps->pss_end_time;
0ea05c64 6008 pause = ps->pss_pass_scrub_pause;
d4a72f23 6009
e7fbeb60 6010 zfs_nicebytes(ps->pss_processed, processed_buf, sizeof (processed_buf));
34dc7c2f 6011
428870ff
BB
6012 assert(ps->pss_func == POOL_SCAN_SCRUB ||
6013 ps->pss_func == POOL_SCAN_RESILVER);
d4a72f23
TC
6014
6015 /* Scan is finished or canceled. */
428870ff 6016 if (ps->pss_state == DSS_FINISHED) {
d4a72f23
TC
6017 total_secs_left = end - start;
6018 days_left = total_secs_left / 60 / 60 / 24;
6019 hours_left = (total_secs_left / 60 / 60) % 24;
6020 mins_left = (total_secs_left / 60) % 60;
6021 secs_left = (total_secs_left % 60);
428870ff
BB
6022
6023 if (ps->pss_func == POOL_SCAN_SCRUB) {
d4a72f23
TC
6024 (void) printf(gettext("scrub repaired %s "
6025 "in %llu days %02llu:%02llu:%02llu "
6026 "with %llu errors on %s"), processed_buf,
6027 (u_longlong_t)days_left, (u_longlong_t)hours_left,
6028 (u_longlong_t)mins_left, (u_longlong_t)secs_left,
6029 (u_longlong_t)ps->pss_errors, ctime(&end));
428870ff 6030 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
d4a72f23
TC
6031 (void) printf(gettext("resilvered %s "
6032 "in %llu days %02llu:%02llu:%02llu "
6033 "with %llu errors on %s"), processed_buf,
6034 (u_longlong_t)days_left, (u_longlong_t)hours_left,
6035 (u_longlong_t)mins_left, (u_longlong_t)secs_left,
6036 (u_longlong_t)ps->pss_errors, ctime(&end));
428870ff 6037 }
428870ff
BB
6038 return;
6039 } else if (ps->pss_state == DSS_CANCELED) {
6040 if (ps->pss_func == POOL_SCAN_SCRUB) {
6041 (void) printf(gettext("scrub canceled on %s"),
6042 ctime(&end));
6043 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
6044 (void) printf(gettext("resilver canceled on %s"),
6045 ctime(&end));
6046 }
34dc7c2f
BB
6047 return;
6048 }
6049
428870ff
BB
6050 assert(ps->pss_state == DSS_SCANNING);
6051
d4a72f23 6052 /* Scan is in progress. Resilvers can't be paused. */
428870ff 6053 if (ps->pss_func == POOL_SCAN_SCRUB) {
0ea05c64
AP
6054 if (pause == 0) {
6055 (void) printf(gettext("scrub in progress since %s"),
6056 ctime(&start));
6057 } else {
d4a72f23
TC
6058 (void) printf(gettext("scrub paused since %s"),
6059 ctime(&pause));
6060 (void) printf(gettext("\tscrub started on %s"),
0ea05c64
AP
6061 ctime(&start));
6062 }
428870ff
BB
6063 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
6064 (void) printf(gettext("resilver in progress since %s"),
6065 ctime(&start));
6066 }
34dc7c2f 6067
d4a72f23
TC
6068 scanned = ps->pss_examined;
6069 pass_scanned = ps->pss_pass_exam;
6070 issued = ps->pss_issued;
6071 pass_issued = ps->pss_pass_issued;
428870ff 6072 total = ps->pss_to_examine;
428870ff 6073
d4a72f23
TC
6074 /* we are only done with a block once we have issued the IO for it */
6075 fraction_done = (double)issued / total;
6076
6077 /* elapsed time for this pass, rounding up to 1 if it's 0 */
428870ff 6078 elapsed = time(NULL) - ps->pss_pass_start;
0ea05c64 6079 elapsed -= ps->pss_pass_scrub_spent_paused;
d4a72f23
TC
6080 elapsed = (elapsed != 0) ? elapsed : 1;
6081
6082 scan_rate = pass_scanned / elapsed;
6083 issue_rate = pass_issued / elapsed;
6084 total_secs_left = (issue_rate != 0) ?
6085 ((total - issued) / issue_rate) : UINT64_MAX;
6086
6087 days_left = total_secs_left / 60 / 60 / 24;
6088 hours_left = (total_secs_left / 60 / 60) % 24;
6089 mins_left = (total_secs_left / 60) % 60;
6090 secs_left = (total_secs_left % 60);
6091
6092 /* format all of the numbers we will be reporting */
6093 zfs_nicebytes(scanned, scanned_buf, sizeof (scanned_buf));
6094 zfs_nicebytes(issued, issued_buf, sizeof (issued_buf));
e7fbeb60 6095 zfs_nicebytes(total, total_buf, sizeof (total_buf));
d4a72f23
TC
6096 zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf));
6097 zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf));
428870ff 6098
d4a72f23 6099 /* do not print estimated time if we have a paused scrub */
0ea05c64 6100 if (pause == 0) {
d4a72f23
TC
6101 (void) printf(gettext("\t%s scanned at %s/s, "
6102 "%s issued at %s/s, %s total\n"),
6103 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
572e2857 6104 } else {
d4a72f23
TC
6105 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
6106 scanned_buf, issued_buf, total_buf);
572e2857 6107 }
428870ff
BB
6108
6109 if (ps->pss_func == POOL_SCAN_RESILVER) {
d4a72f23 6110 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
428870ff
BB
6111 processed_buf, 100 * fraction_done);
6112 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
d4a72f23 6113 (void) printf(gettext("\t%s repaired, %.2f%% done"),
428870ff
BB
6114 processed_buf, 100 * fraction_done);
6115 }
d4a72f23
TC
6116
6117 if (pause == 0) {
6118 if (issue_rate >= 10 * 1024 * 1024) {
6119 (void) printf(gettext(", %llu days "
6120 "%02llu:%02llu:%02llu to go\n"),
6121 (u_longlong_t)days_left, (u_longlong_t)hours_left,
6122 (u_longlong_t)mins_left, (u_longlong_t)secs_left);
6123 } else {
6124 (void) printf(gettext(", no estimated "
6125 "completion time\n"));
6126 }
6127 } else {
6128 (void) printf(gettext("\n"));
6129 }
34dc7c2f
BB
6130}
6131
34dc7c2f
BB
6132static void
6133print_error_log(zpool_handle_t *zhp)
6134{
6135 nvlist_t *nverrlist = NULL;
6136 nvpair_t *elem;
6137 char *pathname;
6138 size_t len = MAXPATHLEN * 2;
6139
56a6054d 6140 if (zpool_get_errlog(zhp, &nverrlist) != 0)
34dc7c2f 6141 return;
34dc7c2f
BB
6142
6143 (void) printf("errors: Permanent errors have been "
6144 "detected in the following files:\n\n");
6145
6146 pathname = safe_malloc(len);
6147 elem = NULL;
6148 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
6149 nvlist_t *nv;
6150 uint64_t dsobj, obj;
6151
6152 verify(nvpair_value_nvlist(elem, &nv) == 0);
6153 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
6154 &dsobj) == 0);
6155 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
6156 &obj) == 0);
6157 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
6158 (void) printf("%7s %s\n", "", pathname);
6159 }
6160 free(pathname);
6161 nvlist_free(nverrlist);
6162}
6163
6164static void
fea33e4e
HJ
6165print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
6166 uint_t nspares)
34dc7c2f
BB
6167{
6168 uint_t i;
6169 char *name;
6170
6171 if (nspares == 0)
6172 return;
6173
6174 (void) printf(gettext("\tspares\n"));
6175
6176 for (i = 0; i < nspares; i++) {
fea33e4e
HJ
6177 name = zpool_vdev_name(g_zfs, zhp, spares[i],
6178 cb->cb_name_flags);
6179 print_status_config(zhp, cb, name, spares[i], 2, B_TRUE);
34dc7c2f
BB
6180 free(name);
6181 }
6182}
6183
6184static void
fea33e4e
HJ
6185print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
6186 uint_t nl2cache)
34dc7c2f
BB
6187{
6188 uint_t i;
6189 char *name;
6190
6191 if (nl2cache == 0)
6192 return;
6193
6194 (void) printf(gettext("\tcache\n"));
6195
6196 for (i = 0; i < nl2cache; i++) {
fea33e4e
HJ
6197 name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
6198 cb->cb_name_flags);
6199 print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE);
34dc7c2f
BB
6200 free(name);
6201 }
6202}
6203
428870ff
BB
6204static void
6205print_dedup_stats(nvlist_t *config)
6206{
6207 ddt_histogram_t *ddh;
6208 ddt_stat_t *dds;
6209 ddt_object_t *ddo;
6210 uint_t c;
e7fbeb60 6211 char dspace[6], mspace[6];
428870ff
BB
6212
6213 /*
6214 * If the pool was faulted then we may not have been able to
32a9872b 6215 * obtain the config. Otherwise, if we have anything in the dedup
428870ff
BB
6216 * table continue processing the stats.
6217 */
6218 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
24024589 6219 (uint64_t **)&ddo, &c) != 0)
428870ff
BB
6220 return;
6221
6222 (void) printf("\n");
24024589
YP
6223 (void) printf(gettext(" dedup: "));
6224 if (ddo->ddo_count == 0) {
6225 (void) printf(gettext("no DDT entries\n"));
6226 return;
6227 }
6228
e7fbeb60 6229 zfs_nicebytes(ddo->ddo_dspace, dspace, sizeof (dspace));
6230 zfs_nicebytes(ddo->ddo_mspace, mspace, sizeof (mspace));
6231 (void) printf("DDT entries %llu, size %s on disk, %s in core\n",
428870ff 6232 (u_longlong_t)ddo->ddo_count,
e7fbeb60 6233 dspace,
6234 mspace);
428870ff
BB
6235
6236 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
6237 (uint64_t **)&dds, &c) == 0);
6238 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
6239 (uint64_t **)&ddh, &c) == 0);
6240 zpool_dump_ddt(dds, ddh);
6241}
6242
34dc7c2f
BB
6243/*
6244 * Display a summary of pool status. Displays a summary such as:
6245 *
6246 * pool: tank
6247 * status: DEGRADED
6248 * reason: One or more devices ...
3cee2262 6249 * see: http://zfsonlinux.org/msg/ZFS-xxxx-01
34dc7c2f
BB
6250 * config:
6251 * mirror DEGRADED
6252 * c1t0d0 OK
6253 * c2t0d0 UNAVAIL
6254 *
6255 * When given the '-v' option, we print out the complete config. If the '-e'
6256 * option is specified, then we print out error rate information as well.
6257 */
6258int
6259status_callback(zpool_handle_t *zhp, void *data)
6260{
6261 status_cbdata_t *cbp = data;
6262 nvlist_t *config, *nvroot;
6263 char *msgid;
731782ec 6264 zpool_status_t reason;
ffe9d382 6265 zpool_errata_t errata;
34dc7c2f
BB
6266 const char *health;
6267 uint_t c;
6268 vdev_stat_t *vs;
6269
6270 config = zpool_get_config(zhp, NULL);
ffe9d382 6271 reason = zpool_get_status(zhp, &msgid, &errata);
34dc7c2f
BB
6272
6273 cbp->cb_count++;
6274
6275 /*
6276 * If we were given 'zpool status -x', only report those pools with
6277 * problems.
6278 */
c5b247f3
TC
6279 if (cbp->cb_explain &&
6280 (reason == ZPOOL_STATUS_OK ||
6281 reason == ZPOOL_STATUS_VERSION_OLDER ||
6282 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
34dc7c2f
BB
6283 if (!cbp->cb_allpools) {
6284 (void) printf(gettext("pool '%s' is healthy\n"),
6285 zpool_get_name(zhp));
6286 if (cbp->cb_first)
6287 cbp->cb_first = B_FALSE;
6288 }
6289 return (0);
6290 }
6291
6292 if (cbp->cb_first)
6293 cbp->cb_first = B_FALSE;
6294 else
6295 (void) printf("\n");
6296
6297 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
6298 &nvroot) == 0);
428870ff 6299 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
6300 (uint64_t **)&vs, &c) == 0);
6301 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
6302
6303 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
6304 (void) printf(gettext(" state: %s\n"), health);
6305
6306 switch (reason) {
6307 case ZPOOL_STATUS_MISSING_DEV_R:
6308 (void) printf(gettext("status: One or more devices could not "
6309 "be opened. Sufficient replicas exist for\n\tthe pool to "
6310 "continue functioning in a degraded state.\n"));
6311 (void) printf(gettext("action: Attach the missing device and "
6312 "online it using 'zpool online'.\n"));
6313 break;
6314
6315 case ZPOOL_STATUS_MISSING_DEV_NR:
6316 (void) printf(gettext("status: One or more devices could not "
6317 "be opened. There are insufficient\n\treplicas for the "
6318 "pool to continue functioning.\n"));
6319 (void) printf(gettext("action: Attach the missing device and "
6320 "online it using 'zpool online'.\n"));
6321 break;
6322
6323 case ZPOOL_STATUS_CORRUPT_LABEL_R:
6324 (void) printf(gettext("status: One or more devices could not "
6325 "be used because the label is missing or\n\tinvalid. "
6326 "Sufficient replicas exist for the pool to continue\n\t"
6327 "functioning in a degraded state.\n"));
6328 (void) printf(gettext("action: Replace the device using "
6329 "'zpool replace'.\n"));
6330 break;
6331
6332 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
6333 (void) printf(gettext("status: One or more devices could not "
6334 "be used because the label is missing \n\tor invalid. "
6335 "There are insufficient replicas for the pool to "
6336 "continue\n\tfunctioning.\n"));
428870ff
BB
6337 zpool_explain_recover(zpool_get_handle(zhp),
6338 zpool_get_name(zhp), reason, config);
34dc7c2f
BB
6339 break;
6340
6341 case ZPOOL_STATUS_FAILING_DEV:
6342 (void) printf(gettext("status: One or more devices has "
6343 "experienced an unrecoverable error. An\n\tattempt was "
6344 "made to correct the error. Applications are "
6345 "unaffected.\n"));
6346 (void) printf(gettext("action: Determine if the device needs "
6347 "to be replaced, and clear the errors\n\tusing "
6348 "'zpool clear' or replace the device with 'zpool "
6349 "replace'.\n"));
6350 break;
6351
6352 case ZPOOL_STATUS_OFFLINE_DEV:
6353 (void) printf(gettext("status: One or more devices has "
6354 "been taken offline by the administrator.\n\tSufficient "
6355 "replicas exist for the pool to continue functioning in "
6356 "a\n\tdegraded state.\n"));
6357 (void) printf(gettext("action: Online the device using "
6358 "'zpool online' or replace the device with\n\t'zpool "
6359 "replace'.\n"));
6360 break;
6361
45d1cae3
BB
6362 case ZPOOL_STATUS_REMOVED_DEV:
6363 (void) printf(gettext("status: One or more devices has "
6364 "been removed by the administrator.\n\tSufficient "
6365 "replicas exist for the pool to continue functioning in "
6366 "a\n\tdegraded state.\n"));
6367 (void) printf(gettext("action: Online the device using "
6368 "'zpool online' or replace the device with\n\t'zpool "
6369 "replace'.\n"));
6370 break;
6371
34dc7c2f
BB
6372 case ZPOOL_STATUS_RESILVERING:
6373 (void) printf(gettext("status: One or more devices is "
6374 "currently being resilvered. The pool will\n\tcontinue "
6375 "to function, possibly in a degraded state.\n"));
6376 (void) printf(gettext("action: Wait for the resilver to "
6377 "complete.\n"));
6378 break;
6379
6380 case ZPOOL_STATUS_CORRUPT_DATA:
6381 (void) printf(gettext("status: One or more devices has "
6382 "experienced an error resulting in data\n\tcorruption. "
6383 "Applications may be affected.\n"));
6384 (void) printf(gettext("action: Restore the file in question "
6385 "if possible. Otherwise restore the\n\tentire pool from "
6386 "backup.\n"));
6387 break;
6388
6389 case ZPOOL_STATUS_CORRUPT_POOL:
6390 (void) printf(gettext("status: The pool metadata is corrupted "
6391 "and the pool cannot be opened.\n"));
428870ff
BB
6392 zpool_explain_recover(zpool_get_handle(zhp),
6393 zpool_get_name(zhp), reason, config);
34dc7c2f
BB
6394 break;
6395
6396 case ZPOOL_STATUS_VERSION_OLDER:
b9b24bb4
CS
6397 (void) printf(gettext("status: The pool is formatted using a "
6398 "legacy on-disk format. The pool can\n\tstill be used, "
6399 "but some features are unavailable.\n"));
34dc7c2f
BB
6400 (void) printf(gettext("action: Upgrade the pool using 'zpool "
6401 "upgrade'. Once this is done, the\n\tpool will no longer "
f52b31ea
BB
6402 "be accessible on software that does not support\n\t"
6403 "feature flags.\n"));
34dc7c2f
BB
6404 break;
6405
6406 case ZPOOL_STATUS_VERSION_NEWER:
6407 (void) printf(gettext("status: The pool has been upgraded to a "
6408 "newer, incompatible on-disk version.\n\tThe pool cannot "
6409 "be accessed on this system.\n"));
6410 (void) printf(gettext("action: Access the pool from a system "
6411 "running more recent software, or\n\trestore the pool from "
6412 "backup.\n"));
6413 break;
6414
b9b24bb4
CS
6415 case ZPOOL_STATUS_FEAT_DISABLED:
6416 (void) printf(gettext("status: Some supported features are not "
6417 "enabled on the pool. The pool can\n\tstill be used, but "
6418 "some features are unavailable.\n"));
6419 (void) printf(gettext("action: Enable all features using "
6420 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
6421 "longer be accessible by software that does not support\n\t"
6422 "the features. See zpool-features(5) for details.\n"));
6423 break;
6424
9ae529ec
CS
6425 case ZPOOL_STATUS_UNSUP_FEAT_READ:
6426 (void) printf(gettext("status: The pool cannot be accessed on "
6427 "this system because it uses the\n\tfollowing feature(s) "
6428 "not supported on this system:\n"));
6429 zpool_print_unsup_feat(config);
6430 (void) printf("\n");
6431 (void) printf(gettext("action: Access the pool from a system "
6432 "that supports the required feature(s),\n\tor restore the "
6433 "pool from backup.\n"));
6434 break;
6435
6436 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
6437 (void) printf(gettext("status: The pool can only be accessed "
6438 "in read-only mode on this system. It\n\tcannot be "
6439 "accessed in read-write mode because it uses the "
6440 "following\n\tfeature(s) not supported on this system:\n"));
6441 zpool_print_unsup_feat(config);
6442 (void) printf("\n");
6443 (void) printf(gettext("action: The pool cannot be accessed in "
6444 "read-write mode. Import the pool with\n"
6445 "\t\"-o readonly=on\", access the pool from a system that "
6446 "supports the\n\trequired feature(s), or restore the "
6447 "pool from backup.\n"));
6448 break;
6449
34dc7c2f
BB
6450 case ZPOOL_STATUS_FAULTED_DEV_R:
6451 (void) printf(gettext("status: One or more devices are "
6452 "faulted in response to persistent errors.\n\tSufficient "
6453 "replicas exist for the pool to continue functioning "
6454 "in a\n\tdegraded state.\n"));
6455 (void) printf(gettext("action: Replace the faulted device, "
6456 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
6457 break;
6458
6459 case ZPOOL_STATUS_FAULTED_DEV_NR:
6460 (void) printf(gettext("status: One or more devices are "
6461 "faulted in response to persistent errors. There are "
6462 "insufficient replicas for the pool to\n\tcontinue "
6463 "functioning.\n"));
6464 (void) printf(gettext("action: Destroy and re-create the pool "
6465 "from a backup source. Manually marking the device\n"
6466 "\trepaired using 'zpool clear' may allow some data "
6467 "to be recovered.\n"));
6468 break;
6469
b128c09f
BB
6470 case ZPOOL_STATUS_IO_FAILURE_WAIT:
6471 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
6472 (void) printf(gettext("status: One or more devices are "
6473 "faulted in response to IO failures.\n"));
6474 (void) printf(gettext("action: Make sure the affected devices "
6475 "are connected, then run 'zpool clear'.\n"));
6476 break;
6477
6478 case ZPOOL_STATUS_BAD_LOG:
6479 (void) printf(gettext("status: An intent log record "
6480 "could not be read.\n"
2627e752 6481 "\tWaiting for administrator intervention to fix the "
b128c09f
BB
6482 "faulted pool.\n"));
6483 (void) printf(gettext("action: Either restore the affected "
6484 "device(s) and run 'zpool online',\n"
6485 "\tor ignore the intent log records by running "
6486 "'zpool clear'.\n"));
6487 break;
6488
1cbae971
RY
6489 case ZPOOL_STATUS_HOSTID_MISMATCH:
6490 (void) printf(gettext("status: Mismatch between pool hostid "
6491 "and system hostid on imported pool.\n\tThis pool was "
6492 "previously imported into a system with a different "
6493 "hostid,\n\tand then was verbatim imported into this "
6494 "system.\n"));
6495 (void) printf(gettext("action: Export this pool on all systems "
6496 "on which it is imported.\n"
6497 "\tThen import it to correct the mismatch.\n"));
6498 break;
6499
ffe9d382
BB
6500 case ZPOOL_STATUS_ERRATA:
6501 (void) printf(gettext("status: Errata #%d detected.\n"),
6502 errata);
6503
6504 switch (errata) {
6505 case ZPOOL_ERRATA_NONE:
6506 break;
6507
4f2dcb3e
RY
6508 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
6509 (void) printf(gettext("action: To correct the issue "
6510 "run 'zpool scrub'.\n"));
6511 break;
6512
ae76f45c
TC
6513 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
6514 (void) printf(gettext("\tExisting encrypted datasets "
6515 "contain an on-disk incompatibility\n\twhich "
6516 "needs to be corrected.\n"));
6517 (void) printf(gettext("action: To correct the issue "
6518 "backup existing encrypted datasets to new\n\t"
6519 "encrypted datasets and destroy the old ones. "
6520 "'zfs mount -o ro' can\n\tbe used to temporarily "
6521 "mount existing encrypted datasets readonly.\n"));
6522 break;
6523
ffe9d382
BB
6524 default:
6525 /*
6526 * All errata which allow the pool to be imported
6527 * must contain an action message.
6528 */
6529 assert(0);
6530 }
6531 break;
6532
34dc7c2f
BB
6533 default:
6534 /*
6535 * The remaining errors can't actually be generated, yet.
6536 */
6537 assert(reason == ZPOOL_STATUS_OK);
6538 }
6539
6540 if (msgid != NULL)
3cee2262 6541 (void) printf(gettext(" see: http://zfsonlinux.org/msg/%s\n"),
34dc7c2f
BB
6542 msgid);
6543
6544 if (config != NULL) {
34dc7c2f
BB
6545 uint64_t nerr;
6546 nvlist_t **spares, **l2cache;
6547 uint_t nspares, nl2cache;
428870ff 6548 pool_scan_stat_t *ps = NULL;
34dc7c2f 6549
428870ff
BB
6550 (void) nvlist_lookup_uint64_array(nvroot,
6551 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
6552 print_scan_status(ps);
34dc7c2f 6553
fea33e4e 6554 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
5f20c145 6555 cbp->cb_name_flags | VDEV_NAME_TYPE_ID);
fea33e4e
HJ
6556 if (cbp->cb_namewidth < 10)
6557 cbp->cb_namewidth = 10;
34dc7c2f
BB
6558
6559 (void) printf(gettext("config:\n\n"));
d6418de0 6560 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s"),
fea33e4e
HJ
6561 cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
6562 "CKSUM");
d6418de0
TH
6563
6564 if (cbp->vcdl != NULL)
6565 print_cmd_columns(cbp->vcdl, 0);
6566
6567 printf("\n");
fea33e4e
HJ
6568 print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
6569 B_FALSE);
34dc7c2f 6570
9babb374 6571 if (num_logs(nvroot) > 0)
fea33e4e 6572 print_logs(zhp, cbp, nvroot);
34dc7c2f
BB
6573 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
6574 &l2cache, &nl2cache) == 0)
fea33e4e 6575 print_l2cache(zhp, cbp, l2cache, nl2cache);
34dc7c2f
BB
6576
6577 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
6578 &spares, &nspares) == 0)
fea33e4e 6579 print_spares(zhp, cbp, spares, nspares);
34dc7c2f
BB
6580
6581 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
6582 &nerr) == 0) {
6583 nvlist_t *nverrlist = NULL;
6584
6585 /*
6586 * If the approximate error count is small, get a
6587 * precise count by fetching the entire log and
6588 * uniquifying the results.
6589 */
6590 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
6591 zpool_get_errlog(zhp, &nverrlist) == 0) {
6592 nvpair_t *elem;
6593
6594 elem = NULL;
6595 nerr = 0;
6596 while ((elem = nvlist_next_nvpair(nverrlist,
6597 elem)) != NULL) {
6598 nerr++;
6599 }
6600 }
6601 nvlist_free(nverrlist);
6602
6603 (void) printf("\n");
6604
6605 if (nerr == 0)
6606 (void) printf(gettext("errors: No known data "
6607 "errors\n"));
6608 else if (!cbp->cb_verbose)
6609 (void) printf(gettext("errors: %llu data "
6610 "errors, use '-v' for a list\n"),
6611 (u_longlong_t)nerr);
6612 else
6613 print_error_log(zhp);
6614 }
428870ff
BB
6615
6616 if (cbp->cb_dedup_stats)
6617 print_dedup_stats(config);
34dc7c2f
BB
6618 } else {
6619 (void) printf(gettext("config: The configuration cannot be "
6620 "determined.\n"));
6621 }
6622
6623 return (0);
6624}
6625
6626/*
d6418de0
TH
6627 * zpool status [-c [script1,script2,...]] [-gLPvx] [-T d|u] [pool] ...
6628 * [interval [count]]
34dc7c2f 6629 *
8720e9e7 6630 * -c CMD For each vdev, run command CMD
d2f3e292
RY
6631 * -g Display guid for individual vdev name.
6632 * -L Follow links when resolving vdev path name.
a77f29f9 6633 * -P Display full path for vdev name.
34dc7c2f
BB
6634 * -v Display complete error logs
6635 * -x Display only pools with potential problems
428870ff
BB
6636 * -D Display dedup status (undocumented)
6637 * -T Display a timestamp in date(1) or Unix format
34dc7c2f
BB
6638 *
6639 * Describes the health status of all pools or some subset.
6640 */
6641int
6642zpool_do_status(int argc, char **argv)
6643{
6644 int c;
6645 int ret;
193a37cb
TH
6646 float interval = 0;
6647 unsigned long count = 0;
34dc7c2f 6648 status_cbdata_t cb = { 0 };
8720e9e7 6649 char *cmd = NULL;
34dc7c2f
BB
6650
6651 /* check options */
8720e9e7 6652 while ((c = getopt(argc, argv, "c:gLPvxDT:")) != -1) {
34dc7c2f 6653 switch (c) {
8720e9e7 6654 case 'c':
d6418de0
TH
6655 if (cmd != NULL) {
6656 fprintf(stderr,
6657 gettext("Can't set -c flag twice\n"));
6658 exit(1);
6659 }
099700d9
GDN
6660
6661 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL &&
6662 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) {
6663 fprintf(stderr, gettext(
6664 "Can't run -c, disabled by "
6665 "ZPOOL_SCRIPTS_ENABLED.\n"));
6666 exit(1);
6667 }
6668
d6418de0
TH
6669 if ((getuid() <= 0 || geteuid() <= 0) &&
6670 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) {
6671 fprintf(stderr, gettext(
6672 "Can't run -c with root privileges "
6673 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n"));
6674 exit(1);
6675 }
8720e9e7
TH
6676 cmd = optarg;
6677 break;
d2f3e292
RY
6678 case 'g':
6679 cb.cb_name_flags |= VDEV_NAME_GUID;
6680 break;
6681 case 'L':
6682 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
6683 break;
a77f29f9 6684 case 'P':
d2f3e292
RY
6685 cb.cb_name_flags |= VDEV_NAME_PATH;
6686 break;
34dc7c2f
BB
6687 case 'v':
6688 cb.cb_verbose = B_TRUE;
6689 break;
6690 case 'x':
6691 cb.cb_explain = B_TRUE;
6692 break;
428870ff
BB
6693 case 'D':
6694 cb.cb_dedup_stats = B_TRUE;
6695 break;
6696 case 'T':
6697 get_timestamp_arg(*optarg);
6698 break;
34dc7c2f 6699 case '?':
1528bfdb 6700 if (optopt == 'c') {
099700d9 6701 print_zpool_script_list("status");
d6418de0 6702 exit(0);
1528bfdb
TH
6703 } else {
6704 fprintf(stderr,
6705 gettext("invalid option '%c'\n"), optopt);
6706 }
34dc7c2f
BB
6707 usage(B_FALSE);
6708 }
6709 }
6710
6711 argc -= optind;
6712 argv += optind;
6713
428870ff 6714 get_interval_count(&argc, argv, &interval, &count);
34dc7c2f
BB
6715
6716 if (argc == 0)
6717 cb.cb_allpools = B_TRUE;
6718
428870ff 6719 cb.cb_first = B_TRUE;
fea33e4e 6720 cb.cb_print_status = B_TRUE;
34dc7c2f 6721
428870ff
BB
6722 for (;;) {
6723 if (timestamp_fmt != NODATE)
6724 print_timestamp(timestamp_fmt);
34dc7c2f 6725
8720e9e7 6726 if (cmd != NULL)
1528bfdb
TH
6727 cb.vcdl = all_pools_for_each_vdev_run(argc, argv, cmd,
6728 NULL, NULL, 0, 0);
8720e9e7 6729
428870ff
BB
6730 ret = for_each_pool(argc, argv, B_TRUE, NULL,
6731 status_callback, &cb);
6732
8720e9e7
TH
6733 if (cb.vcdl != NULL)
6734 free_vdev_cmd_data_list(cb.vcdl);
6735
428870ff 6736 if (argc == 0 && cb.cb_count == 0)
42cb3819 6737 (void) fprintf(stderr, gettext("no pools available\n"));
428870ff
BB
6738 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
6739 (void) printf(gettext("all pools are healthy\n"));
6740
6741 if (ret != 0)
6742 return (ret);
6743
6744 if (interval == 0)
6745 break;
6746
6747 if (count != 0 && --count == 0)
6748 break;
6749
193a37cb 6750 (void) fsleep(interval);
428870ff
BB
6751 }
6752
6753 return (0);
34dc7c2f
BB
6754}
6755
6756typedef struct upgrade_cbdata {
34dc7c2f 6757 int cb_first;
34dc7c2f
BB
6758 int cb_argc;
6759 uint64_t cb_version;
6760 char **cb_argv;
6761} upgrade_cbdata_t;
6762
287be44f
DS
6763static int
6764check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs)
6765{
02730c33 6766 int zfs_version = (int)zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
287be44f
DS
6767 int *count = (int *)unsupp_fs;
6768
6769 if (zfs_version > ZPL_VERSION) {
6770 (void) printf(gettext("%s (v%d) is not supported by this "
6771 "implementation of ZFS.\n"),
6772 zfs_get_name(zhp), zfs_version);
6773 (*count)++;
6774 }
6775
6776 zfs_iter_filesystems(zhp, check_unsupp_fs, unsupp_fs);
6777
6778 zfs_close(zhp);
6779
6780 return (0);
6781}
6782
b9b24bb4
CS
6783static int
6784upgrade_version(zpool_handle_t *zhp, uint64_t version)
6785{
6786 int ret;
6787 nvlist_t *config;
6788 uint64_t oldversion;
287be44f 6789 int unsupp_fs = 0;
b9b24bb4
CS
6790
6791 config = zpool_get_config(zhp, NULL);
6792 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6793 &oldversion) == 0);
6794
6795 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
6796 assert(oldversion < version);
6797
287be44f
DS
6798 ret = zfs_iter_root(zpool_get_handle(zhp), check_unsupp_fs, &unsupp_fs);
6799 if (ret != 0)
6800 return (ret);
6801
6802 if (unsupp_fs) {
5c7afad4
BB
6803 (void) fprintf(stderr, gettext("Upgrade not performed due "
6804 "to %d unsupported filesystems (max v%d).\n"),
02730c33 6805 unsupp_fs, (int)ZPL_VERSION);
287be44f
DS
6806 return (1);
6807 }
6808
b9b24bb4
CS
6809 ret = zpool_upgrade(zhp, version);
6810 if (ret != 0)
6811 return (ret);
6812
6813 if (version >= SPA_VERSION_FEATURES) {
6814 (void) printf(gettext("Successfully upgraded "
6815 "'%s' from version %llu to feature flags.\n"),
02730c33 6816 zpool_get_name(zhp), (u_longlong_t)oldversion);
b9b24bb4
CS
6817 } else {
6818 (void) printf(gettext("Successfully upgraded "
6819 "'%s' from version %llu to version %llu.\n"),
02730c33
BB
6820 zpool_get_name(zhp), (u_longlong_t)oldversion,
6821 (u_longlong_t)version);
b9b24bb4
CS
6822 }
6823
6824 return (0);
6825}
6826
6827static int
6828upgrade_enable_all(zpool_handle_t *zhp, int *countp)
6829{
6830 int i, ret, count;
6831 boolean_t firstff = B_TRUE;
6832 nvlist_t *enabled = zpool_get_features(zhp);
6833
6834 count = 0;
6835 for (i = 0; i < SPA_FEATURES; i++) {
6836 const char *fname = spa_feature_table[i].fi_uname;
6837 const char *fguid = spa_feature_table[i].fi_guid;
6838 if (!nvlist_exists(enabled, fguid)) {
6839 char *propname;
6840 verify(-1 != asprintf(&propname, "feature@%s", fname));
6841 ret = zpool_set_prop(zhp, propname,
6842 ZFS_FEATURE_ENABLED);
6843 if (ret != 0) {
6844 free(propname);
6845 return (ret);
6846 }
6847 count++;
6848
6849 if (firstff) {
6850 (void) printf(gettext("Enabled the "
6851 "following features on '%s':\n"),
6852 zpool_get_name(zhp));
6853 firstff = B_FALSE;
6854 }
6855 (void) printf(gettext(" %s\n"), fname);
6856 free(propname);
6857 }
6858 }
6859
6860 if (countp != NULL)
6861 *countp = count;
6862 return (0);
6863}
6864
34dc7c2f
BB
6865static int
6866upgrade_cb(zpool_handle_t *zhp, void *arg)
6867{
6868 upgrade_cbdata_t *cbp = arg;
6869 nvlist_t *config;
6870 uint64_t version;
b9b24bb4
CS
6871 boolean_t printnl = B_FALSE;
6872 int ret;
34dc7c2f
BB
6873
6874 config = zpool_get_config(zhp, NULL);
6875 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6876 &version) == 0);
6877
b9b24bb4 6878 assert(SPA_VERSION_IS_SUPPORTED(version));
34dc7c2f 6879
b9b24bb4
CS
6880 if (version < cbp->cb_version) {
6881 cbp->cb_first = B_FALSE;
6882 ret = upgrade_version(zhp, cbp->cb_version);
6883 if (ret != 0)
6884 return (ret);
6885 printnl = B_TRUE;
6886
b9b24bb4
CS
6887 /*
6888 * If they did "zpool upgrade -a", then we could
6889 * be doing ioctls to different pools. We need
6890 * to log this history once to each pool, and bypass
6891 * the normal history logging that happens in main().
6892 */
6893 (void) zpool_log_history(g_zfs, history_str);
6894 log_history = B_FALSE;
b9b24bb4
CS
6895 }
6896
6897 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
6898 int count;
6899 ret = upgrade_enable_all(zhp, &count);
6900 if (ret != 0)
6901 return (ret);
6902
6903 if (count > 0) {
34dc7c2f 6904 cbp->cb_first = B_FALSE;
b9b24bb4 6905 printnl = B_TRUE;
34dc7c2f 6906 }
b9b24bb4 6907 }
34dc7c2f 6908
b9b24bb4
CS
6909 if (printnl) {
6910 (void) printf(gettext("\n"));
6911 }
6912
6913 return (0);
6914}
6915
6916static int
6917upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
6918{
6919 upgrade_cbdata_t *cbp = arg;
6920 nvlist_t *config;
6921 uint64_t version;
6922
6923 config = zpool_get_config(zhp, NULL);
6924 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6925 &version) == 0);
6926
6927 assert(SPA_VERSION_IS_SUPPORTED(version));
6928
6929 if (version < SPA_VERSION_FEATURES) {
34dc7c2f
BB
6930 if (cbp->cb_first) {
6931 (void) printf(gettext("The following pools are "
b9b24bb4
CS
6932 "formatted with legacy version numbers and can\n"
6933 "be upgraded to use feature flags. After "
6934 "being upgraded, these pools\nwill no "
6935 "longer be accessible by software that does not "
6936 "support feature\nflags.\n\n"));
34dc7c2f
BB
6937 (void) printf(gettext("VER POOL\n"));
6938 (void) printf(gettext("--- ------------\n"));
6939 cbp->cb_first = B_FALSE;
6940 }
6941
6942 (void) printf("%2llu %s\n", (u_longlong_t)version,
6943 zpool_get_name(zhp));
6944 }
6945
b9b24bb4
CS
6946 return (0);
6947}
6948
6949static int
6950upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
6951{
6952 upgrade_cbdata_t *cbp = arg;
6953 nvlist_t *config;
6954 uint64_t version;
6955
6956 config = zpool_get_config(zhp, NULL);
6957 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
6958 &version) == 0);
6959
6960 if (version >= SPA_VERSION_FEATURES) {
6961 int i;
6962 boolean_t poolfirst = B_TRUE;
6963 nvlist_t *enabled = zpool_get_features(zhp);
6964
6965 for (i = 0; i < SPA_FEATURES; i++) {
6966 const char *fguid = spa_feature_table[i].fi_guid;
6967 const char *fname = spa_feature_table[i].fi_uname;
6968 if (!nvlist_exists(enabled, fguid)) {
6969 if (cbp->cb_first) {
6970 (void) printf(gettext("\nSome "
6971 "supported features are not "
6972 "enabled on the following pools. "
6973 "Once a\nfeature is enabled the "
6974 "pool may become incompatible with "
6975 "software\nthat does not support "
6976 "the feature. See "
6977 "zpool-features(5) for "
6978 "details.\n\n"));
6979 (void) printf(gettext("POOL "
6980 "FEATURE\n"));
6981 (void) printf(gettext("------"
6982 "---------\n"));
6983 cbp->cb_first = B_FALSE;
6984 }
6985
6986 if (poolfirst) {
6987 (void) printf(gettext("%s\n"),
6988 zpool_get_name(zhp));
6989 poolfirst = B_FALSE;
6990 }
6991
6992 (void) printf(gettext(" %s\n"), fname);
6993 }
6f1ffb06
MA
6994 /*
6995 * If they did "zpool upgrade -a", then we could
6996 * be doing ioctls to different pools. We need
6997 * to log this history once to each pool, and bypass
6998 * the normal history logging that happens in main().
6999 */
7000 (void) zpool_log_history(g_zfs, history_str);
7001 log_history = B_FALSE;
b9b24bb4
CS
7002 }
7003 }
7004
7005 return (0);
34dc7c2f
BB
7006}
7007
7008/* ARGSUSED */
7009static int
7010upgrade_one(zpool_handle_t *zhp, void *data)
7011{
b9b24bb4 7012 boolean_t printnl = B_FALSE;
34dc7c2f
BB
7013 upgrade_cbdata_t *cbp = data;
7014 uint64_t cur_version;
7015 int ret;
7016
7017 if (strcmp("log", zpool_get_name(zhp)) == 0) {
c66989ba 7018 (void) fprintf(stderr, gettext("'log' is now a reserved word\n"
34dc7c2f
BB
7019 "Pool 'log' must be renamed using export and import"
7020 " to upgrade.\n"));
7021 return (1);
7022 }
7023
7024 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
7025 if (cur_version > cbp->cb_version) {
7026 (void) printf(gettext("Pool '%s' is already formatted "
b9b24bb4 7027 "using more current version '%llu'.\n\n"),
02730c33 7028 zpool_get_name(zhp), (u_longlong_t)cur_version);
34dc7c2f
BB
7029 return (0);
7030 }
b9b24bb4
CS
7031
7032 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
34dc7c2f 7033 (void) printf(gettext("Pool '%s' is already formatted "
b9b24bb4 7034 "using version %llu.\n\n"), zpool_get_name(zhp),
02730c33 7035 (u_longlong_t)cbp->cb_version);
34dc7c2f
BB
7036 return (0);
7037 }
7038
b9b24bb4
CS
7039 if (cur_version != cbp->cb_version) {
7040 printnl = B_TRUE;
7041 ret = upgrade_version(zhp, cbp->cb_version);
7042 if (ret != 0)
7043 return (ret);
7044 }
34dc7c2f 7045
b9b24bb4
CS
7046 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
7047 int count = 0;
7048 ret = upgrade_enable_all(zhp, &count);
7049 if (ret != 0)
7050 return (ret);
7051
7052 if (count != 0) {
7053 printnl = B_TRUE;
7054 } else if (cur_version == SPA_VERSION) {
7055 (void) printf(gettext("Pool '%s' already has all "
7056 "supported features enabled.\n"),
7057 zpool_get_name(zhp));
7058 }
7059 }
7060
7061 if (printnl) {
7062 (void) printf(gettext("\n"));
34dc7c2f
BB
7063 }
7064
b9b24bb4 7065 return (0);
34dc7c2f
BB
7066}
7067
7068/*
7069 * zpool upgrade
7070 * zpool upgrade -v
7071 * zpool upgrade [-V version] <-a | pool ...>
7072 *
7073 * With no arguments, display downrev'd ZFS pool available for upgrade.
7074 * Individual pools can be upgraded by specifying the pool, and '-a' will
7075 * upgrade all pools.
7076 */
7077int
7078zpool_do_upgrade(int argc, char **argv)
7079{
7080 int c;
7081 upgrade_cbdata_t cb = { 0 };
7082 int ret = 0;
7083 boolean_t showversions = B_FALSE;
b9b24bb4 7084 boolean_t upgradeall = B_FALSE;
34dc7c2f
BB
7085 char *end;
7086
7087
7088 /* check options */
9babb374 7089 while ((c = getopt(argc, argv, ":avV:")) != -1) {
34dc7c2f
BB
7090 switch (c) {
7091 case 'a':
b9b24bb4 7092 upgradeall = B_TRUE;
34dc7c2f
BB
7093 break;
7094 case 'v':
7095 showversions = B_TRUE;
7096 break;
7097 case 'V':
7098 cb.cb_version = strtoll(optarg, &end, 10);
9ae529ec
CS
7099 if (*end != '\0' ||
7100 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
34dc7c2f
BB
7101 (void) fprintf(stderr,
7102 gettext("invalid version '%s'\n"), optarg);
7103 usage(B_FALSE);
7104 }
7105 break;
9babb374
BB
7106 case ':':
7107 (void) fprintf(stderr, gettext("missing argument for "
7108 "'%c' option\n"), optopt);
7109 usage(B_FALSE);
7110 break;
34dc7c2f
BB
7111 case '?':
7112 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7113 optopt);
7114 usage(B_FALSE);
7115 }
7116 }
7117
7118 cb.cb_argc = argc;
7119 cb.cb_argv = argv;
7120 argc -= optind;
7121 argv += optind;
7122
7123 if (cb.cb_version == 0) {
7124 cb.cb_version = SPA_VERSION;
b9b24bb4 7125 } else if (!upgradeall && argc == 0) {
34dc7c2f
BB
7126 (void) fprintf(stderr, gettext("-V option is "
7127 "incompatible with other arguments\n"));
7128 usage(B_FALSE);
7129 }
7130
7131 if (showversions) {
b9b24bb4 7132 if (upgradeall || argc != 0) {
34dc7c2f
BB
7133 (void) fprintf(stderr, gettext("-v option is "
7134 "incompatible with other arguments\n"));
7135 usage(B_FALSE);
7136 }
b9b24bb4 7137 } else if (upgradeall) {
34dc7c2f
BB
7138 if (argc != 0) {
7139 (void) fprintf(stderr, gettext("-a option should not "
7140 "be used along with a pool name\n"));
7141 usage(B_FALSE);
7142 }
7143 }
7144
9ae529ec
CS
7145 (void) printf(gettext("This system supports ZFS pool feature "
7146 "flags.\n\n"));
34dc7c2f 7147 if (showversions) {
b9b24bb4
CS
7148 int i;
7149
7150 (void) printf(gettext("The following features are "
7151 "supported:\n\n"));
7152 (void) printf(gettext("FEAT DESCRIPTION\n"));
7153 (void) printf("----------------------------------------------"
7154 "---------------\n");
7155 for (i = 0; i < SPA_FEATURES; i++) {
7156 zfeature_info_t *fi = &spa_feature_table[i];
241b5415
MA
7157 const char *ro =
7158 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
b9b24bb4
CS
7159 " (read-only compatible)" : "";
7160
7161 (void) printf("%-37s%s\n", fi->fi_uname, ro);
7162 (void) printf(" %s\n", fi->fi_desc);
7163 }
7164 (void) printf("\n");
7165
7166 (void) printf(gettext("The following legacy versions are also "
34dc7c2f
BB
7167 "supported:\n\n"));
7168 (void) printf(gettext("VER DESCRIPTION\n"));
7169 (void) printf("--- -----------------------------------------"
7170 "---------------\n");
7171 (void) printf(gettext(" 1 Initial ZFS version\n"));
7172 (void) printf(gettext(" 2 Ditto blocks "
7173 "(replicated metadata)\n"));
7174 (void) printf(gettext(" 3 Hot spares and double parity "
7175 "RAID-Z\n"));
7176 (void) printf(gettext(" 4 zpool history\n"));
7177 (void) printf(gettext(" 5 Compression using the gzip "
7178 "algorithm\n"));
7179 (void) printf(gettext(" 6 bootfs pool property\n"));
7180 (void) printf(gettext(" 7 Separate intent log devices\n"));
7181 (void) printf(gettext(" 8 Delegated administration\n"));
7182 (void) printf(gettext(" 9 refquota and refreservation "
7183 "properties\n"));
7184 (void) printf(gettext(" 10 Cache devices\n"));
b128c09f
BB
7185 (void) printf(gettext(" 11 Improved scrub performance\n"));
7186 (void) printf(gettext(" 12 Snapshot properties\n"));
7187 (void) printf(gettext(" 13 snapused property\n"));
9babb374
BB
7188 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
7189 (void) printf(gettext(" 15 user/group space accounting\n"));
7190 (void) printf(gettext(" 16 stmf property support\n"));
45d1cae3 7191 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
428870ff
BB
7192 (void) printf(gettext(" 18 Snapshot user holds\n"));
7193 (void) printf(gettext(" 19 Log device removal\n"));
7194 (void) printf(gettext(" 20 Compression using zle "
7195 "(zero-length encoding)\n"));
7196 (void) printf(gettext(" 21 Deduplication\n"));
7197 (void) printf(gettext(" 22 Received properties\n"));
7198 (void) printf(gettext(" 23 Slim ZIL\n"));
7199 (void) printf(gettext(" 24 System attributes\n"));
7200 (void) printf(gettext(" 25 Improved scrub stats\n"));
7201 (void) printf(gettext(" 26 Improved snapshot deletion "
7202 "performance\n"));
572e2857
BB
7203 (void) printf(gettext(" 27 Improved snapshot creation "
7204 "performance\n"));
7205 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
428870ff
BB
7206 (void) printf(gettext("\nFor more information on a particular "
7207 "version, including supported releases,\n"));
7208 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
b9b24bb4
CS
7209 } else if (argc == 0 && upgradeall) {
7210 cb.cb_first = B_TRUE;
34dc7c2f 7211 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
b9b24bb4
CS
7212 if (ret == 0 && cb.cb_first) {
7213 if (cb.cb_version == SPA_VERSION) {
7214 (void) printf(gettext("All pools are already "
7215 "formatted using feature flags.\n\n"));
7216 (void) printf(gettext("Every feature flags "
7217 "pool already has all supported features "
7218 "enabled.\n"));
7219 } else {
7220 (void) printf(gettext("All pools are already "
7221 "formatted with version %llu or higher.\n"),
02730c33 7222 (u_longlong_t)cb.cb_version);
34dc7c2f
BB
7223 }
7224 }
b9b24bb4
CS
7225 } else if (argc == 0) {
7226 cb.cb_first = B_TRUE;
7227 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
7228 assert(ret == 0);
34dc7c2f 7229
b9b24bb4
CS
7230 if (cb.cb_first) {
7231 (void) printf(gettext("All pools are formatted "
7232 "using feature flags.\n\n"));
7233 } else {
7234 (void) printf(gettext("\nUse 'zpool upgrade -v' "
7235 "for a list of available legacy versions.\n"));
7236 }
7237
7238 cb.cb_first = B_TRUE;
7239 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
7240 assert(ret == 0);
7241
7242 if (cb.cb_first) {
7243 (void) printf(gettext("Every feature flags pool has "
7244 "all supported features enabled.\n"));
7245 } else {
7246 (void) printf(gettext("\n"));
34dc7c2f
BB
7247 }
7248 } else {
7249 ret = for_each_pool(argc, argv, B_FALSE, NULL,
7250 upgrade_one, &cb);
7251 }
7252
7253 return (ret);
7254}
7255
7256typedef struct hist_cbdata {
7257 boolean_t first;
6f1ffb06
MA
7258 boolean_t longfmt;
7259 boolean_t internal;
34dc7c2f
BB
7260} hist_cbdata_t;
7261
34dc7c2f
BB
7262/*
7263 * Print out the command history for a specific pool.
7264 */
7265static int
7266get_history_one(zpool_handle_t *zhp, void *data)
7267{
7268 nvlist_t *nvhis;
7269 nvlist_t **records;
7270 uint_t numrecords;
34dc7c2f 7271 int ret, i;
34dc7c2f 7272 hist_cbdata_t *cb = (hist_cbdata_t *)data;
34dc7c2f
BB
7273
7274 cb->first = B_FALSE;
7275
7276 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
7277
7278 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
7279 return (ret);
7280
7281 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
7282 &records, &numrecords) == 0);
7283 for (i = 0; i < numrecords; i++) {
6f1ffb06
MA
7284 nvlist_t *rec = records[i];
7285 char tbuf[30] = "";
34dc7c2f 7286
6f1ffb06
MA
7287 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
7288 time_t tsec;
7289 struct tm t;
34dc7c2f 7290
6f1ffb06
MA
7291 tsec = fnvlist_lookup_uint64(records[i],
7292 ZPOOL_HIST_TIME);
7293 (void) localtime_r(&tsec, &t);
7294 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
7295 }
7296
7297 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
7298 (void) printf("%s %s", tbuf,
7299 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
7300 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
7301 int ievent =
7302 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
7303 if (!cb->internal)
34dc7c2f 7304 continue;
6f1ffb06
MA
7305 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
7306 (void) printf("%s unrecognized record:\n",
7307 tbuf);
7308 dump_nvlist(rec, 4);
34dc7c2f 7309 continue;
6f1ffb06
MA
7310 }
7311 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
7312 zfs_history_event_names[ievent],
02730c33 7313 (longlong_t)fnvlist_lookup_uint64(
d1d7e268 7314 rec, ZPOOL_HIST_TXG),
6f1ffb06
MA
7315 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
7316 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
7317 if (!cb->internal)
7318 continue;
7319 (void) printf("%s [txg:%lld] %s", tbuf,
02730c33 7320 (longlong_t)fnvlist_lookup_uint64(
d1d7e268 7321 rec, ZPOOL_HIST_TXG),
6f1ffb06
MA
7322 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
7323 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
7324 (void) printf(" %s (%llu)",
7325 fnvlist_lookup_string(rec,
7326 ZPOOL_HIST_DSNAME),
d1d7e268 7327 (u_longlong_t)fnvlist_lookup_uint64(rec,
6f1ffb06
MA
7328 ZPOOL_HIST_DSID));
7329 }
7330 (void) printf(" %s", fnvlist_lookup_string(rec,
7331 ZPOOL_HIST_INT_STR));
7332 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
7333 if (!cb->internal)
7334 continue;
7335 (void) printf("%s ioctl %s\n", tbuf,
7336 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
7337 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
7338 (void) printf(" input:\n");
7339 dump_nvlist(fnvlist_lookup_nvlist(rec,
7340 ZPOOL_HIST_INPUT_NVL), 8);
7341 }
7342 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
7343 (void) printf(" output:\n");
7344 dump_nvlist(fnvlist_lookup_nvlist(rec,
7345 ZPOOL_HIST_OUTPUT_NVL), 8);
7346 }
7347 } else {
7348 if (!cb->internal)
7349 continue;
7350 (void) printf("%s unrecognized record:\n", tbuf);
7351 dump_nvlist(rec, 4);
34dc7c2f 7352 }
34dc7c2f
BB
7353
7354 if (!cb->longfmt) {
7355 (void) printf("\n");
7356 continue;
7357 }
7358 (void) printf(" [");
6f1ffb06
MA
7359 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
7360 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
7361 struct passwd *pwd = getpwuid(who);
7362 (void) printf("user %d ", (int)who);
7363 if (pwd != NULL)
7364 (void) printf("(%s) ", pwd->pw_name);
34dc7c2f 7365 }
6f1ffb06
MA
7366 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
7367 (void) printf("on %s",
7368 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
34dc7c2f 7369 }
6f1ffb06
MA
7370 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
7371 (void) printf(":%s",
7372 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
34dc7c2f
BB
7373 }
7374
7375 (void) printf("]");
7376 (void) printf("\n");
7377 }
7378 (void) printf("\n");
7379 nvlist_free(nvhis);
7380
7381 return (ret);
7382}
7383
7384/*
7385 * zpool history <pool>
7386 *
7387 * Displays the history of commands that modified pools.
7388 */
34dc7c2f
BB
7389int
7390zpool_do_history(int argc, char **argv)
7391{
7392 hist_cbdata_t cbdata = { 0 };
7393 int ret;
7394 int c;
7395
7396 cbdata.first = B_TRUE;
7397 /* check options */
7398 while ((c = getopt(argc, argv, "li")) != -1) {
7399 switch (c) {
7400 case 'l':
6f1ffb06 7401 cbdata.longfmt = B_TRUE;
34dc7c2f
BB
7402 break;
7403 case 'i':
6f1ffb06 7404 cbdata.internal = B_TRUE;
34dc7c2f
BB
7405 break;
7406 case '?':
7407 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7408 optopt);
7409 usage(B_FALSE);
7410 }
7411 }
7412 argc -= optind;
7413 argv += optind;
7414
7415 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
7416 &cbdata);
7417
7418 if (argc == 0 && cbdata.first == B_TRUE) {
42cb3819 7419 (void) fprintf(stderr, gettext("no pools available\n"));
34dc7c2f
BB
7420 return (0);
7421 }
7422
7423 return (ret);
7424}
7425
26685276
BB
7426typedef struct ev_opts {
7427 int verbose;
c5343ba7 7428 int scripted;
26685276
BB
7429 int follow;
7430 int clear;
88f9c939 7431 char poolname[ZFS_MAX_DATASET_NAME_LEN];
26685276
BB
7432} ev_opts_t;
7433
7434static void
1e1c3980 7435zpool_do_events_short(nvlist_t *nvl, ev_opts_t *opts)
26685276
BB
7436{
7437 char ctime_str[26], str[32], *ptr;
7438 int64_t *tv;
7439 uint_t n;
7440
7441 verify(nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0);
7442 memset(str, ' ', 32);
7443 (void) ctime_r((const time_t *)&tv[0], ctime_str);
d1d7e268
MK
7444 (void) strncpy(str, ctime_str+4, 6); /* 'Jun 30' */
7445 (void) strncpy(str+7, ctime_str+20, 4); /* '1993' */
7446 (void) strncpy(str+12, ctime_str+11, 8); /* '21:49:08' */
7447 (void) sprintf(str+20, ".%09lld", (longlong_t)tv[1]); /* '.123456789' */
1e1c3980
SH
7448 if (opts->scripted)
7449 (void) printf(gettext("%s\t"), str);
7450 else
7451 (void) printf(gettext("%s "), str);
26685276
BB
7452
7453 verify(nvlist_lookup_string(nvl, FM_CLASS, &ptr) == 0);
7454 (void) printf(gettext("%s\n"), ptr);
7455}
7456
7457static void
7458zpool_do_events_nvprint(nvlist_t *nvl, int depth)
7459{
7460 nvpair_t *nvp;
7461
7462 for (nvp = nvlist_next_nvpair(nvl, NULL);
7463 nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) {
7464
7465 data_type_t type = nvpair_type(nvp);
7466 const char *name = nvpair_name(nvp);
7467
7468 boolean_t b;
7469 uint8_t i8;
7470 uint16_t i16;
7471 uint32_t i32;
7472 uint64_t i64;
7473 char *str;
7474 nvlist_t *cnv;
7475
7476 printf(gettext("%*s%s = "), depth, "", name);
7477
7478 switch (type) {
7479 case DATA_TYPE_BOOLEAN:
7480 printf(gettext("%s"), "1");
7481 break;
7482
7483 case DATA_TYPE_BOOLEAN_VALUE:
7484 (void) nvpair_value_boolean_value(nvp, &b);
7485 printf(gettext("%s"), b ? "1" : "0");
7486 break;
7487
7488 case DATA_TYPE_BYTE:
7489 (void) nvpair_value_byte(nvp, &i8);
7490 printf(gettext("0x%x"), i8);
7491 break;
7492
7493 case DATA_TYPE_INT8:
7494 (void) nvpair_value_int8(nvp, (void *)&i8);
7495 printf(gettext("0x%x"), i8);
7496 break;
7497
7498 case DATA_TYPE_UINT8:
7499 (void) nvpair_value_uint8(nvp, &i8);
7500 printf(gettext("0x%x"), i8);
7501 break;
7502
7503 case DATA_TYPE_INT16:
7504 (void) nvpair_value_int16(nvp, (void *)&i16);
7505 printf(gettext("0x%x"), i16);
7506 break;
7507
7508 case DATA_TYPE_UINT16:
7509 (void) nvpair_value_uint16(nvp, &i16);
7510 printf(gettext("0x%x"), i16);
7511 break;
7512
7513 case DATA_TYPE_INT32:
7514 (void) nvpair_value_int32(nvp, (void *)&i32);
7515 printf(gettext("0x%x"), i32);
7516 break;
7517
7518 case DATA_TYPE_UINT32:
7519 (void) nvpair_value_uint32(nvp, &i32);
7520 printf(gettext("0x%x"), i32);
7521 break;
7522
7523 case DATA_TYPE_INT64:
7524 (void) nvpair_value_int64(nvp, (void *)&i64);
7525 printf(gettext("0x%llx"), (u_longlong_t)i64);
7526 break;
7527
7528 case DATA_TYPE_UINT64:
7529 (void) nvpair_value_uint64(nvp, &i64);
d02ca379
DB
7530 /*
7531 * translate vdev state values to readable
7532 * strings to aide zpool events consumers
7533 */
7534 if (strcmp(name,
7535 FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
7536 strcmp(name,
7537 FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
7538 printf(gettext("\"%s\" (0x%llx)"),
7539 zpool_state_to_name(i64, VDEV_AUX_NONE),
7540 (u_longlong_t)i64);
7541 } else {
7542 printf(gettext("0x%llx"), (u_longlong_t)i64);
7543 }
26685276
BB
7544 break;
7545
7546 case DATA_TYPE_HRTIME:
7547 (void) nvpair_value_hrtime(nvp, (void *)&i64);
7548 printf(gettext("0x%llx"), (u_longlong_t)i64);
7549 break;
7550
7551 case DATA_TYPE_STRING:
7552 (void) nvpair_value_string(nvp, &str);
7553 printf(gettext("\"%s\""), str ? str : "<NULL>");
7554 break;
7555
7556 case DATA_TYPE_NVLIST:
7557 printf(gettext("(embedded nvlist)\n"));
7558 (void) nvpair_value_nvlist(nvp, &cnv);
7559 zpool_do_events_nvprint(cnv, depth + 8);
c5343ba7 7560 printf(gettext("%*s(end %s)"), depth, "", name);
26685276
BB
7561 break;
7562
7563 case DATA_TYPE_NVLIST_ARRAY: {
7564 nvlist_t **val;
7565 uint_t i, nelem;
7566
7567 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
7568 printf(gettext("(%d embedded nvlists)\n"), nelem);
7569 for (i = 0; i < nelem; i++) {
7570 printf(gettext("%*s%s[%d] = %s\n"),
d1d7e268 7571 depth, "", name, i, "(embedded nvlist)");
26685276
BB
7572 zpool_do_events_nvprint(val[i], depth + 8);
7573 printf(gettext("%*s(end %s[%i])\n"),
d1d7e268 7574 depth, "", name, i);
26685276
BB
7575 }
7576 printf(gettext("%*s(end %s)\n"), depth, "", name);
7577 }
7578 break;
7579
7580 case DATA_TYPE_INT8_ARRAY: {
7581 int8_t *val;
7582 uint_t i, nelem;
7583
7584 (void) nvpair_value_int8_array(nvp, &val, &nelem);
7585 for (i = 0; i < nelem; i++)
7586 printf(gettext("0x%x "), val[i]);
7587
7588 break;
7589 }
7590
7591 case DATA_TYPE_UINT8_ARRAY: {
7592 uint8_t *val;
7593 uint_t i, nelem;
7594
7595 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
7596 for (i = 0; i < nelem; i++)
7597 printf(gettext("0x%x "), val[i]);
7598
7599 break;
7600 }
7601
7602 case DATA_TYPE_INT16_ARRAY: {
7603 int16_t *val;
7604 uint_t i, nelem;
7605
7606 (void) nvpair_value_int16_array(nvp, &val, &nelem);
7607 for (i = 0; i < nelem; i++)
7608 printf(gettext("0x%x "), val[i]);
7609
7610 break;
7611 }
7612
7613 case DATA_TYPE_UINT16_ARRAY: {
7614 uint16_t *val;
7615 uint_t i, nelem;
7616
7617 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
7618 for (i = 0; i < nelem; i++)
7619 printf(gettext("0x%x "), val[i]);
7620
7621 break;
7622 }
7623
7624 case DATA_TYPE_INT32_ARRAY: {
7625 int32_t *val;
7626 uint_t i, nelem;
7627
7628 (void) nvpair_value_int32_array(nvp, &val, &nelem);
7629 for (i = 0; i < nelem; i++)
7630 printf(gettext("0x%x "), val[i]);
7631
7632 break;
7633 }
7634
7635 case DATA_TYPE_UINT32_ARRAY: {
7636 uint32_t *val;
7637 uint_t i, nelem;
7638
7639 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
7640 for (i = 0; i < nelem; i++)
7641 printf(gettext("0x%x "), val[i]);
7642
7643 break;
7644 }
7645
7646 case DATA_TYPE_INT64_ARRAY: {
7647 int64_t *val;
7648 uint_t i, nelem;
7649
7650 (void) nvpair_value_int64_array(nvp, &val, &nelem);
7651 for (i = 0; i < nelem; i++)
d1d7e268
MK
7652 printf(gettext("0x%llx "),
7653 (u_longlong_t)val[i]);
26685276
BB
7654
7655 break;
7656 }
7657
7658 case DATA_TYPE_UINT64_ARRAY: {
7659 uint64_t *val;
7660 uint_t i, nelem;
7661
7662 (void) nvpair_value_uint64_array(nvp, &val, &nelem);
7663 for (i = 0; i < nelem; i++)
d1d7e268
MK
7664 printf(gettext("0x%llx "),
7665 (u_longlong_t)val[i]);
26685276
BB
7666
7667 break;
7668 }
7669
d21705ea
BB
7670 case DATA_TYPE_STRING_ARRAY: {
7671 char **str;
7672 uint_t i, nelem;
7673
7674 (void) nvpair_value_string_array(nvp, &str, &nelem);
7675 for (i = 0; i < nelem; i++)
7676 printf(gettext("\"%s\" "),
7677 str[i] ? str[i] : "<NULL>");
7678
7679 break;
7680 }
7681
26685276
BB
7682 case DATA_TYPE_BOOLEAN_ARRAY:
7683 case DATA_TYPE_BYTE_ARRAY:
7684 case DATA_TYPE_DOUBLE:
7685 case DATA_TYPE_UNKNOWN:
7686 printf(gettext("<unknown>"));
7687 break;
7688 }
7689
7690 printf(gettext("\n"));
7691 }
7692}
7693
7694static int
7695zpool_do_events_next(ev_opts_t *opts)
7696{
7697 nvlist_t *nvl;
9b101a73 7698 int zevent_fd, ret, dropped;
88f9c939 7699 char *pool;
26685276 7700
9b101a73
BB
7701 zevent_fd = open(ZFS_DEV, O_RDWR);
7702 VERIFY(zevent_fd >= 0);
26685276 7703
c5343ba7
BB
7704 if (!opts->scripted)
7705 (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS");
26685276
BB
7706
7707 while (1) {
7708 ret = zpool_events_next(g_zfs, &nvl, &dropped,
8c7aa0cf 7709 (opts->follow ? ZEVENT_NONE : ZEVENT_NONBLOCK), zevent_fd);
26685276
BB
7710 if (ret || nvl == NULL)
7711 break;
7712
7713 if (dropped > 0)
7714 (void) printf(gettext("dropped %d events\n"), dropped);
7715
88f9c939 7716 if (strlen(opts->poolname) > 0 &&
7717 nvlist_lookup_string(nvl, FM_FMRI_ZFS_POOL, &pool) == 0 &&
7718 strcmp(opts->poolname, pool) != 0)
7719 continue;
7720
1e1c3980 7721 zpool_do_events_short(nvl, opts);
26685276
BB
7722
7723 if (opts->verbose) {
7724 zpool_do_events_nvprint(nvl, 8);
7725 printf(gettext("\n"));
7726 }
50fe577d 7727 (void) fflush(stdout);
26685276
BB
7728
7729 nvlist_free(nvl);
7730 }
7731
9b101a73 7732 VERIFY(0 == close(zevent_fd));
26685276
BB
7733
7734 return (ret);
7735}
7736
7737static int
7738zpool_do_events_clear(ev_opts_t *opts)
7739{
7740 int count, ret;
7741
7742 ret = zpool_events_clear(g_zfs, &count);
7743 if (!ret)
7744 (void) printf(gettext("cleared %d events\n"), count);
7745
7746 return (ret);
7747}
7748
7749/*
88f9c939 7750 * zpool events [-vHf [pool] | -c]
26685276
BB
7751 *
7752 * Displays events logs by ZFS.
7753 */
7754int
7755zpool_do_events(int argc, char **argv)
7756{
7757 ev_opts_t opts = { 0 };
7758 int ret;
7759 int c;
7760
7761 /* check options */
c5343ba7 7762 while ((c = getopt(argc, argv, "vHfc")) != -1) {
26685276
BB
7763 switch (c) {
7764 case 'v':
7765 opts.verbose = 1;
c5343ba7
BB
7766 break;
7767 case 'H':
7768 opts.scripted = 1;
26685276
BB
7769 break;
7770 case 'f':
7771 opts.follow = 1;
7772 break;
7773 case 'c':
7774 opts.clear = 1;
7775 break;
7776 case '?':
7777 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7778 optopt);
7779 usage(B_FALSE);
7780 }
7781 }
7782 argc -= optind;
7783 argv += optind;
7784
88f9c939 7785 if (argc > 1) {
7786 (void) fprintf(stderr, gettext("too many arguments\n"));
7787 usage(B_FALSE);
7788 } else if (argc == 1) {
7789 (void) strlcpy(opts.poolname, argv[0], sizeof (opts.poolname));
7790 if (!zfs_name_valid(opts.poolname, ZFS_TYPE_POOL)) {
7791 (void) fprintf(stderr,
7792 gettext("invalid pool name '%s'\n"), opts.poolname);
7793 usage(B_FALSE);
7794 }
7795 }
7796
7797 if ((argc == 1 || opts.verbose || opts.scripted || opts.follow) &&
7798 opts.clear) {
7799 (void) fprintf(stderr,
7800 gettext("invalid options combined with -c\n"));
7801 usage(B_FALSE);
7802 }
7803
26685276
BB
7804 if (opts.clear)
7805 ret = zpool_do_events_clear(&opts);
7806 else
7807 ret = zpool_do_events_next(&opts);
7808
d1d7e268 7809 return (ret);
26685276
BB
7810}
7811
34dc7c2f
BB
7812static int
7813get_callback(zpool_handle_t *zhp, void *data)
7814{
7815 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
7816 char value[MAXNAMELEN];
7817 zprop_source_t srctype;
7818 zprop_list_t *pl;
7819
7820 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
7821
7822 /*
7823 * Skip the special fake placeholder. This will also skip
7824 * over the name property when 'all' is specified.
7825 */
7826 if (pl->pl_prop == ZPOOL_PROP_NAME &&
7827 pl == cbp->cb_proplist)
7828 continue;
7829
9ae529ec
CS
7830 if (pl->pl_prop == ZPROP_INVAL &&
7831 (zpool_prop_feature(pl->pl_user_prop) ||
7832 zpool_prop_unsupported(pl->pl_user_prop))) {
7833 srctype = ZPROP_SRC_LOCAL;
34dc7c2f 7834
9ae529ec
CS
7835 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
7836 value, sizeof (value)) == 0) {
7837 zprop_print_one_property(zpool_get_name(zhp),
7838 cbp, pl->pl_user_prop, value, srctype,
7839 NULL, NULL);
7840 }
7841 } else {
2a8b84b7 7842 if (zpool_get_prop(zhp, pl->pl_prop, value,
d65e7381 7843 sizeof (value), &srctype, cbp->cb_literal) != 0)
9ae529ec
CS
7844 continue;
7845
7846 zprop_print_one_property(zpool_get_name(zhp), cbp,
7847 zpool_prop_to_name(pl->pl_prop), value, srctype,
7848 NULL, NULL);
7849 }
34dc7c2f
BB
7850 }
7851 return (0);
7852}
7853
2a8b84b7
AS
7854/*
7855 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
7856 *
7857 * -H Scripted mode. Don't display headers, and separate properties
7858 * by a single tab.
7859 * -o List of columns to display. Defaults to
7860 * "name,property,value,source".
4e33ba4c 7861 * -p Display values in parsable (exact) format.
2a8b84b7
AS
7862 *
7863 * Get properties of pools in the system. Output space statistics
7864 * for each one as well as other attributes.
7865 */
34dc7c2f
BB
7866int
7867zpool_do_get(int argc, char **argv)
7868{
7869 zprop_get_cbdata_t cb = { 0 };
7870 zprop_list_t fake_name = { 0 };
2a8b84b7
AS
7871 int ret;
7872 int c, i;
7873 char *value;
7874
7875 cb.cb_first = B_TRUE;
7876
7877 /*
7878 * Set up default columns and sources.
7879 */
7880 cb.cb_sources = ZPROP_SRC_ALL;
7881 cb.cb_columns[0] = GET_COL_NAME;
7882 cb.cb_columns[1] = GET_COL_PROPERTY;
7883 cb.cb_columns[2] = GET_COL_VALUE;
7884 cb.cb_columns[3] = GET_COL_SOURCE;
7885 cb.cb_type = ZFS_TYPE_POOL;
34dc7c2f 7886
d65e7381 7887 /* check options */
2a8b84b7 7888 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
d65e7381
RE
7889 switch (c) {
7890 case 'p':
7891 cb.cb_literal = B_TRUE;
7892 break;
79eb71dc
TF
7893 case 'H':
7894 cb.cb_scripted = B_TRUE;
7895 break;
2a8b84b7
AS
7896 case 'o':
7897 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
7898 i = 0;
7899 while (*optarg != '\0') {
7900 static char *col_subopts[] =
7901 { "name", "property", "value", "source",
7902 "all", NULL };
7903
7904 if (i == ZFS_GET_NCOLS) {
7905 (void) fprintf(stderr, gettext("too "
7906 "many fields given to -o "
7907 "option\n"));
7908 usage(B_FALSE);
7909 }
79eb71dc 7910
2a8b84b7
AS
7911 switch (getsubopt(&optarg, col_subopts,
7912 &value)) {
7913 case 0:
7914 cb.cb_columns[i++] = GET_COL_NAME;
7915 break;
7916 case 1:
7917 cb.cb_columns[i++] = GET_COL_PROPERTY;
7918 break;
7919 case 2:
7920 cb.cb_columns[i++] = GET_COL_VALUE;
7921 break;
7922 case 3:
7923 cb.cb_columns[i++] = GET_COL_SOURCE;
7924 break;
7925 case 4:
7926 if (i > 0) {
7927 (void) fprintf(stderr,
7928 gettext("\"all\" conflicts "
7929 "with specific fields "
7930 "given to -o option\n"));
7931 usage(B_FALSE);
7932 }
7933 cb.cb_columns[0] = GET_COL_NAME;
7934 cb.cb_columns[1] = GET_COL_PROPERTY;
7935 cb.cb_columns[2] = GET_COL_VALUE;
7936 cb.cb_columns[3] = GET_COL_SOURCE;
7937 i = ZFS_GET_NCOLS;
7938 break;
7939 default:
7940 (void) fprintf(stderr,
7941 gettext("invalid column name "
7942 "'%s'\n"), value);
7943 usage(B_FALSE);
7944 }
7945 }
7946 break;
d65e7381
RE
7947 case '?':
7948 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7949 optopt);
7950 usage(B_FALSE);
7951 }
7952 }
7953
7954 argc -= optind;
7955 argv += optind;
7956
7957 if (argc < 1) {
9ae529ec
CS
7958 (void) fprintf(stderr, gettext("missing property "
7959 "argument\n"));
34dc7c2f 7960 usage(B_FALSE);
9ae529ec 7961 }
34dc7c2f 7962
2a8b84b7
AS
7963 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
7964 ZFS_TYPE_POOL) != 0)
34dc7c2f
BB
7965 usage(B_FALSE);
7966
d65e7381
RE
7967 argc--;
7968 argv++;
7969
34dc7c2f
BB
7970 if (cb.cb_proplist != NULL) {
7971 fake_name.pl_prop = ZPOOL_PROP_NAME;
7972 fake_name.pl_width = strlen(gettext("NAME"));
7973 fake_name.pl_next = cb.cb_proplist;
7974 cb.cb_proplist = &fake_name;
7975 }
7976
d65e7381 7977 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
34dc7c2f
BB
7978 get_callback, &cb);
7979
7980 if (cb.cb_proplist == &fake_name)
7981 zprop_free_list(fake_name.pl_next);
7982 else
7983 zprop_free_list(cb.cb_proplist);
7984
7985 return (ret);
7986}
7987
7988typedef struct set_cbdata {
7989 char *cb_propname;
7990 char *cb_value;
7991 boolean_t cb_any_successful;
7992} set_cbdata_t;
7993
7994int
7995set_callback(zpool_handle_t *zhp, void *data)
7996{
7997 int error;
7998 set_cbdata_t *cb = (set_cbdata_t *)data;
7999
8000 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
8001
8002 if (!error)
8003 cb->cb_any_successful = B_TRUE;
8004
8005 return (error);
8006}
8007
8008int
8009zpool_do_set(int argc, char **argv)
8010{
8011 set_cbdata_t cb = { 0 };
8012 int error;
8013
8014 if (argc > 1 && argv[1][0] == '-') {
8015 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8016 argv[1][1]);
8017 usage(B_FALSE);
8018 }
8019
8020 if (argc < 2) {
8021 (void) fprintf(stderr, gettext("missing property=value "
8022 "argument\n"));
8023 usage(B_FALSE);
8024 }
8025
8026 if (argc < 3) {
8027 (void) fprintf(stderr, gettext("missing pool name\n"));
8028 usage(B_FALSE);
8029 }
8030
8031 if (argc > 3) {
8032 (void) fprintf(stderr, gettext("too many pool names\n"));
8033 usage(B_FALSE);
8034 }
8035
8036 cb.cb_propname = argv[1];
8037 cb.cb_value = strchr(cb.cb_propname, '=');
8038 if (cb.cb_value == NULL) {
8039 (void) fprintf(stderr, gettext("missing value in "
8040 "property=value argument\n"));
8041 usage(B_FALSE);
8042 }
8043
8044 *(cb.cb_value) = '\0';
8045 cb.cb_value++;
8046
8047 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
8048 set_callback, &cb);
8049
8050 return (error);
8051}
8052
8053static int
8054find_command_idx(char *command, int *idx)
8055{
8056 int i;
8057
8058 for (i = 0; i < NCOMMAND; i++) {
8059 if (command_table[i].name == NULL)
8060 continue;
8061
8062 if (strcmp(command, command_table[i].name) == 0) {
8063 *idx = i;
8064 return (0);
8065 }
8066 }
8067 return (1);
8068}
8069
8070int
8071main(int argc, char **argv)
8072{
8e896579 8073 int ret = 0;
d4ed6673 8074 int i = 0;
34dc7c2f
BB
8075 char *cmdname;
8076
8077 (void) setlocale(LC_ALL, "");
8078 (void) textdomain(TEXT_DOMAIN);
5b4136bd 8079 srand(time(NULL));
34dc7c2f 8080
34dc7c2f
BB
8081 opterr = 0;
8082
8083 /*
8084 * Make sure the user has specified some command.
8085 */
8086 if (argc < 2) {
8087 (void) fprintf(stderr, gettext("missing command\n"));
8088 usage(B_FALSE);
8089 }
8090
8091 cmdname = argv[1];
8092
8093 /*
8094 * Special case '-?'
8095 */
d1d7e268 8096 if ((strcmp(cmdname, "-?") == 0) || strcmp(cmdname, "--help") == 0)
34dc7c2f
BB
8097 usage(B_TRUE);
8098
65037d9b
BB
8099 if ((g_zfs = libzfs_init()) == NULL) {
8100 (void) fprintf(stderr, "%s", libzfs_error_init(errno));
9b020fd9 8101 return (1);
65037d9b 8102 }
9b020fd9
BB
8103
8104 libzfs_print_on_error(g_zfs, B_TRUE);
8105
6f1ffb06 8106 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
34dc7c2f
BB
8107
8108 /*
8109 * Run the appropriate command.
8110 */
8111 if (find_command_idx(cmdname, &i) == 0) {
8112 current_command = &command_table[i];
8113 ret = command_table[i].func(argc - 1, argv + 1);
8114 } else if (strchr(cmdname, '=')) {
8115 verify(find_command_idx("set", &i) == 0);
8116 current_command = &command_table[i];
8117 ret = command_table[i].func(argc, argv);
8118 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
8119 /*
8120 * 'freeze' is a vile debugging abomination, so we treat
8121 * it as such.
8122 */
4807c0ba
TC
8123 zfs_cmd_t zc = {"\0"};
8124
8125 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
8126 ret = zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc);
8127 if (ret != 0) {
8128 (void) fprintf(stderr,
8129 gettext("failed to freeze pool: %d\n"), errno);
8130 ret = 1;
8131 }
8132
8133 log_history = 0;
34dc7c2f
BB
8134 } else {
8135 (void) fprintf(stderr, gettext("unrecognized "
8136 "command '%s'\n"), cmdname);
8137 usage(B_FALSE);
d4ed6673 8138 ret = 1;
34dc7c2f
BB
8139 }
8140
6f1ffb06
MA
8141 if (ret == 0 && log_history)
8142 (void) zpool_log_history(g_zfs, history_str);
8143
34dc7c2f
BB
8144 libzfs_fini(g_zfs);
8145
8146 /*
8147 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
8148 * for the purposes of running ::findleaks.
8149 */
8150 if (getenv("ZFS_ABORT") != NULL) {
8151 (void) printf("dumping core by request\n");
8152 abort();
8153 }
8154
8155 return (ret);
8156}