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