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