1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * ZFS Fault Injector 27 * 28 * This userland component takes a set of options and uses libzpool to translate 29 * from a user-visible object type and name to an internal representation. 30 * There are two basic types of faults: device faults and data faults. 31 * 32 * 33 * DEVICE FAULTS 34 * 35 * Errors can be injected into a particular vdev using the '-d' option. This 36 * option takes a path or vdev GUID to uniquely identify the device within a 37 * pool. There are two types of errors that can be injected, EIO and ENXIO, 38 * that can be controlled through the '-e' option. The default is ENXIO. For 39 * EIO failures, any attempt to read data from the device will return EIO, but 40 * subsequent attempt to reopen the device will succeed. For ENXIO failures, 41 * any attempt to read from the device will return EIO, but any attempt to 42 * reopen the device will also return ENXIO. 43 * For label faults, the -L option must be specified. This allows faults 44 * to be injected into either the nvlist, uberblock, pad1, or pad2 region 45 * of all the labels for the specified device. 46 * 47 * This form of the command looks like: 48 * 49 * zinject -d device [-e errno] [-L <uber | nvlist | pad1 | pad2>] pool 50 * 51 * 52 * DATA FAULTS 53 * 54 * We begin with a tuple of the form: 55 * 56 * <type,level,range,object> 57 * 58 * type A string describing the type of data to target. Each type 59 * implicitly describes how to interpret 'object'. Currently, 60 * the following values are supported: 61 * 62 * data User data for a file 63 * dnode Dnode for a file or directory 64 * 65 * The following MOS objects are special. Instead of injecting 66 * errors on a particular object or blkid, we inject errors across 67 * all objects of the given type. 68 * 69 * mos Any data in the MOS 70 * mosdir object directory 71 * config pool configuration 72 * bpobj blkptr list 73 * spacemap spacemap 74 * metaslab metaslab 75 * errlog persistent error log 76 * 77 * level Object level. Defaults to '0', not applicable to all types. If 78 * a range is given, this corresponds to the indirect block 79 * corresponding to the specific range. 80 * 81 * range A numerical range [start,end) within the object. Defaults to 82 * the full size of the file. 83 * 84 * object A string describing the logical location of the object. For 85 * files and directories (currently the only supported types), 86 * this is the path of the object on disk. 87 * 88 * This is translated, via libzpool, into the following internal representation: 89 * 90 * <type,objset,object,level,range> 91 * 92 * These types should be self-explanatory. This tuple is then passed to the 93 * kernel via a special ioctl() to initiate fault injection for the given 94 * object. Note that 'type' is not strictly necessary for fault injection, but 95 * is used when translating existing faults into a human-readable string. 96 * 97 * 98 * The command itself takes one of the forms: 99 * 100 * zinject 101 * zinject <-a | -u pool> 102 * zinject -c <id|all> 103 * zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level] 104 * [-r range] <object> 105 * zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool 106 * 107 * With no arguments, the command prints all currently registered injection 108 * handlers, with their numeric identifiers. 109 * 110 * The '-c' option will clear the given handler, or all handlers if 'all' is 111 * specified. 112 * 113 * The '-e' option takes a string describing the errno to simulate. This must 114 * be either 'io' or 'checksum'. In most cases this will result in the same 115 * behavior, but RAID-Z will produce a different set of ereports for this 116 * situation. 117 * 118 * The '-a', '-u', and '-m' flags toggle internal flush behavior. If '-a' is 119 * specified, then the ARC cache is flushed appropriately. If '-u' is 120 * specified, then the underlying SPA is unloaded. Either of these flags can be 121 * specified independently of any other handlers. The '-m' flag automatically 122 * does an unmount and remount of the underlying dataset to aid in flushing the 123 * cache. 124 * 125 * The '-f' flag controls the frequency of errors injected, expressed as a 126 * integer percentage between 1 and 100. The default is 100. 127 * 128 * The this form is responsible for actually injecting the handler into the 129 * framework. It takes the arguments described above, translates them to the 130 * internal tuple using libzpool, and then issues an ioctl() to register the 131 * handler. 132 * 133 * The final form can target a specific bookmark, regardless of whether a 134 * human-readable interface has been designed. It allows developers to specify 135 * a particular block by number. 136 */ 137 138 #include <errno.h> 139 #include <fcntl.h> 140 #include <stdio.h> 141 #include <stdlib.h> 142 #include <strings.h> 143 #include <unistd.h> 144 145 #include <sys/fs/zfs.h> 146 #include <sys/mount.h> 147 148 #include <libzfs.h> 149 150 #undef verify /* both libzfs.h and zfs_context.h want to define this */ 151 152 #include "zinject.h" 153 154 libzfs_handle_t *g_zfs; 155 int zfs_fd; 156 157 #define ECKSUM EBADE 158 159 static const char *errtable[TYPE_INVAL] = { 160 "data", 161 "dnode", 162 "mos", 163 "mosdir", 164 "metaslab", 165 "config", 166 "bpobj", 167 "spacemap", 168 "errlog", 169 "uber", 170 "nvlist", 171 "pad1", 172 "pad2" 173 }; 174 175 static err_type_t 176 name_to_type(const char *arg) 177 { 178 int i; 179 for (i = 0; i < TYPE_INVAL; i++) 180 if (strcmp(errtable[i], arg) == 0) 181 return (i); 182 183 return (TYPE_INVAL); 184 } 185 186 static const char * 187 type_to_name(uint64_t type) 188 { 189 switch (type) { 190 case DMU_OT_OBJECT_DIRECTORY: 191 return ("mosdir"); 192 case DMU_OT_OBJECT_ARRAY: 193 return ("metaslab"); 194 case DMU_OT_PACKED_NVLIST: 195 return ("config"); 196 case DMU_OT_BPOBJ: 197 return ("bpobj"); 198 case DMU_OT_SPACE_MAP: 199 return ("spacemap"); 200 case DMU_OT_ERROR_LOG: 201 return ("errlog"); 202 default: 203 return ("-"); 204 } 205 } 206 207 208 /* 209 * Print usage message. 210 */ 211 void 212 usage(void) 213 { 214 (void) printf( 215 "usage:\n" 216 "\n" 217 "\tzinject\n" 218 "\n" 219 "\t\tList all active injection records.\n" 220 "\n" 221 "\tzinject -c <id|all>\n" 222 "\n" 223 "\t\tClear the particular record (if given a numeric ID), or\n" 224 "\t\tall records if 'all' is specificed.\n" 225 "\n" 226 "\tzinject -p <function name> pool\n" 227 "\t\tInject a panic fault at the specified function. Only \n" 228 "\t\tfunctions which call spa_vdev_config_exit(), or \n" 229 "\t\tspa_vdev_exit() will trigger a panic.\n" 230 "\n" 231 "\tzinject -d device [-e errno] [-L <nvlist|uber|pad1|pad2>] [-F]\n" 232 "\t [-T <read|write|free|claim|all> pool\n" 233 "\t\tInject a fault into a particular device or the device's\n" 234 "\t\tlabel. Label injection can either be 'nvlist', 'uber',\n " 235 "\t\t'pad1', or 'pad2'.\n" 236 "\t\t'errno' can be 'nxio' (the default), 'io', or 'dtl'.\n" 237 "\n" 238 "\tzinject -d device -A <degrade|fault> pool\n" 239 "\t\tPerform a specific action on a particular device\n" 240 "\n" 241 "\tzinject -I [-s <seconds> | -g <txgs>] pool\n" 242 "\t\tCause the pool to stop writing blocks yet not\n" 243 "\t\treport errors for a duration. Simulates buggy hardware\n" 244 "\t\tthat fails to honor cache flush requests.\n" 245 "\t\tDefault duration is 30 seconds. The machine is panicked\n" 246 "\t\tat the end of the duration.\n" 247 "\n" 248 "\tzinject -b objset:object:level:blkid pool\n" 249 "\n" 250 "\t\tInject an error into pool 'pool' with the numeric bookmark\n" 251 "\t\tspecified by the remaining tuple. Each number is in\n" 252 "\t\thexidecimal, and only one block can be specified.\n" 253 "\n" 254 "\tzinject [-q] <-t type> [-e errno] [-l level] [-r range]\n" 255 "\t [-a] [-m] [-u] [-f freq] <object>\n" 256 "\n" 257 "\t\tInject an error into the object specified by the '-t' option\n" 258 "\t\tand the object descriptor. The 'object' parameter is\n" 259 "\t\tinterperted depending on the '-t' option.\n" 260 "\n" 261 "\t\t-q\tQuiet mode. Only print out the handler number added.\n" 262 "\t\t-e\tInject a specific error. Must be either 'io' or\n" 263 "\t\t\t'checksum'. Default is 'io'.\n" 264 "\t\t-l\tInject error at a particular block level. Default is " 265 "0.\n" 266 "\t\t-m\tAutomatically remount underlying filesystem.\n" 267 "\t\t-r\tInject error over a particular logical range of an\n" 268 "\t\t\tobject. Will be translated to the appropriate blkid\n" 269 "\t\t\trange according to the object's properties.\n" 270 "\t\t-a\tFlush the ARC cache. Can be specified without any\n" 271 "\t\t\tassociated object.\n" 272 "\t\t-u\tUnload the associated pool. Can be specified with only\n" 273 "\t\t\ta pool object.\n" 274 "\t\t-f\tOnly inject errors a fraction of the time. Expressed as\n" 275 "\t\t\ta percentage between 1 and 100.\n" 276 "\n" 277 "\t-t data\t\tInject an error into the plain file contents of a\n" 278 "\t\t\tfile. The object must be specified as a complete path\n" 279 "\t\t\tto a file on a ZFS filesystem.\n" 280 "\n" 281 "\t-t dnode\tInject an error into the metadnode in the block\n" 282 "\t\t\tcorresponding to the dnode for a file or directory. The\n" 283 "\t\t\t'-r' option is incompatible with this mode. The object\n" 284 "\t\t\tis specified as a complete path to a file or directory\n" 285 "\t\t\ton a ZFS filesystem.\n" 286 "\n" 287 "\t-t <mos>\tInject errors into the MOS for objects of the given\n" 288 "\t\t\ttype. Valid types are: mos, mosdir, config, bpobj,\n" 289 "\t\t\tspacemap, metaslab, errlog. The only valid <object> is\n" 290 "\t\t\tthe poolname.\n"); 291 } 292 293 static int 294 iter_handlers(int (*func)(int, const char *, zinject_record_t *, void *), 295 void *data) 296 { 297 zfs_cmd_t zc = { 0 }; 298 int ret; 299 300 while (ioctl(zfs_fd, ZFS_IOC_INJECT_LIST_NEXT, &zc) == 0) 301 if ((ret = func((int)zc.zc_guid, zc.zc_name, 302 &zc.zc_inject_record, data)) != 0) 303 return (ret); 304 305 if (errno != ENOENT) { 306 (void) fprintf(stderr, "Unable to list handlers: %s\n", 307 strerror(errno)); 308 return (-1); 309 } 310 311 return (0); 312 } 313 314 static int 315 print_data_handler(int id, const char *pool, zinject_record_t *record, 316 void *data) 317 { 318 int *count = data; 319 320 if (record->zi_guid != 0 || record->zi_func[0] != '\0') 321 return (0); 322 323 if (*count == 0) { 324 (void) printf("%3s %-15s %-6s %-6s %-8s %3s %-15s\n", 325 "ID", "POOL", "OBJSET", "OBJECT", "TYPE", "LVL", "RANGE"); 326 (void) printf("--- --------------- ------ " 327 "------ -------- --- ---------------\n"); 328 } 329 330 *count += 1; 331 332 (void) printf("%3d %-15s %-6llu %-6llu %-8s %3d ", id, pool, 333 (u_longlong_t)record->zi_objset, (u_longlong_t)record->zi_object, 334 type_to_name(record->zi_type), record->zi_level); 335 336 if (record->zi_start == 0 && 337 record->zi_end == -1ULL) 338 (void) printf("all\n"); 339 else 340 (void) printf("[%llu, %llu]\n", (u_longlong_t)record->zi_start, 341 (u_longlong_t)record->zi_end); 342 343 return (0); 344 } 345 346 static int 347 print_device_handler(int id, const char *pool, zinject_record_t *record, 348 void *data) 349 { 350 int *count = data; 351 352 if (record->zi_guid == 0 || record->zi_func[0] != '\0') 353 return (0); 354 355 if (*count == 0) { 356 (void) printf("%3s %-15s %s\n", "ID", "POOL", "GUID"); 357 (void) printf("--- --------------- ----------------\n"); 358 } 359 360 *count += 1; 361 362 (void) printf("%3d %-15s %llx\n", id, pool, 363 (u_longlong_t)record->zi_guid); 364 365 return (0); 366 } 367 368 static int 369 print_panic_handler(int id, const char *pool, zinject_record_t *record, 370 void *data) 371 { 372 int *count = data; 373 374 if (record->zi_func[0] == '\0') 375 return (0); 376 377 if (*count == 0) { 378 (void) printf("%3s %-15s %s\n", "ID", "POOL", "FUNCTION"); 379 (void) printf("--- --------------- ----------------\n"); 380 } 381 382 *count += 1; 383 384 (void) printf("%3d %-15s %s\n", id, pool, record->zi_func); 385 386 return (0); 387 } 388 389 /* 390 * Print all registered error handlers. Returns the number of handlers 391 * registered. 392 */ 393 static int 394 print_all_handlers(void) 395 { 396 int count = 0, total = 0; 397 398 (void) iter_handlers(print_device_handler, &count); 399 if (count > 0) { 400 total += count; 401 (void) printf("\n"); 402 count = 0; 403 } 404 405 (void) iter_handlers(print_data_handler, &count); 406 if (count > 0) { 407 total += count; 408 (void) printf("\n"); 409 count = 0; 410 } 411 412 (void) iter_handlers(print_panic_handler, &count); 413 414 return (count + total); 415 } 416 417 /* ARGSUSED */ 418 static int 419 cancel_one_handler(int id, const char *pool, zinject_record_t *record, 420 void *data) 421 { 422 zfs_cmd_t zc = { 0 }; 423 424 zc.zc_guid = (uint64_t)id; 425 426 if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) { 427 (void) fprintf(stderr, "failed to remove handler %d: %s\n", 428 id, strerror(errno)); 429 return (1); 430 } 431 432 return (0); 433 } 434 435 /* 436 * Remove all fault injection handlers. 437 */ 438 static int 439 cancel_all_handlers(void) 440 { 441 int ret = iter_handlers(cancel_one_handler, NULL); 442 443 if (ret == 0) 444 (void) printf("removed all registered handlers\n"); 445 446 return (ret); 447 } 448 449 /* 450 * Remove a specific fault injection handler. 451 */ 452 static int 453 cancel_handler(int id) 454 { 455 zfs_cmd_t zc = { 0 }; 456 457 zc.zc_guid = (uint64_t)id; 458 459 if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) { 460 (void) fprintf(stderr, "failed to remove handler %d: %s\n", 461 id, strerror(errno)); 462 return (1); 463 } 464 465 (void) printf("removed handler %d\n", id); 466 467 return (0); 468 } 469 470 /* 471 * Register a new fault injection handler. 472 */ 473 static int 474 register_handler(const char *pool, int flags, zinject_record_t *record, 475 int quiet) 476 { 477 zfs_cmd_t zc = { 0 }; 478 479 (void) strcpy(zc.zc_name, pool); 480 zc.zc_inject_record = *record; 481 zc.zc_guid = flags; 482 483 if (ioctl(zfs_fd, ZFS_IOC_INJECT_FAULT, &zc) != 0) { 484 (void) fprintf(stderr, "failed to add handler: %s\n", 485 strerror(errno)); 486 return (1); 487 } 488 489 if (flags & ZINJECT_NULL) 490 return (0); 491 492 if (quiet) { 493 (void) printf("%llu\n", (u_longlong_t)zc.zc_guid); 494 } else { 495 (void) printf("Added handler %llu with the following " 496 "properties:\n", (u_longlong_t)zc.zc_guid); 497 (void) printf(" pool: %s\n", pool); 498 if (record->zi_guid) { 499 (void) printf(" vdev: %llx\n", 500 (u_longlong_t)record->zi_guid); 501 } else if (record->zi_func[0] != '\0') { 502 (void) printf(" panic function: %s\n", 503 record->zi_func); 504 } else if (record->zi_duration > 0) { 505 (void) printf(" time: %lld seconds\n", 506 (u_longlong_t)record->zi_duration); 507 } else if (record->zi_duration < 0) { 508 (void) printf(" txgs: %lld \n", 509 (u_longlong_t)-record->zi_duration); 510 } else { 511 (void) printf("objset: %llu\n", 512 (u_longlong_t)record->zi_objset); 513 (void) printf("object: %llu\n", 514 (u_longlong_t)record->zi_object); 515 (void) printf(" type: %llu\n", 516 (u_longlong_t)record->zi_type); 517 (void) printf(" level: %d\n", record->zi_level); 518 if (record->zi_start == 0 && 519 record->zi_end == -1ULL) 520 (void) printf(" range: all\n"); 521 else 522 (void) printf(" range: [%llu, %llu)\n", 523 (u_longlong_t)record->zi_start, 524 (u_longlong_t)record->zi_end); 525 } 526 } 527 528 return (0); 529 } 530 531 int 532 perform_action(const char *pool, zinject_record_t *record, int cmd) 533 { 534 zfs_cmd_t zc = { 0 }; 535 536 ASSERT(cmd == VDEV_STATE_DEGRADED || cmd == VDEV_STATE_FAULTED); 537 (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); 538 zc.zc_guid = record->zi_guid; 539 zc.zc_cookie = cmd; 540 541 if (ioctl(zfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0) 542 return (0); 543 544 return (1); 545 } 546 547 int 548 main(int argc, char **argv) 549 { 550 int c; 551 char *range = NULL; 552 char *cancel = NULL; 553 char *end; 554 char *raw = NULL; 555 char *device = NULL; 556 int level = 0; 557 int quiet = 0; 558 int error = 0; 559 int domount = 0; 560 int io_type = ZIO_TYPES; 561 int action = VDEV_STATE_UNKNOWN; 562 err_type_t type = TYPE_INVAL; 563 err_type_t label = TYPE_INVAL; 564 zinject_record_t record = { 0 }; 565 char pool[MAXNAMELEN]; 566 char dataset[MAXNAMELEN]; 567 zfs_handle_t *zhp; 568 int nowrites = 0; 569 int dur_txg = 0; 570 int dur_secs = 0; 571 int ret; 572 int flags = 0; 573 574 if ((g_zfs = libzfs_init()) == NULL) { 575 (void) fprintf(stderr, "internal error: failed to " 576 "initialize ZFS library\n"); 577 return (1); 578 } 579 580 libzfs_print_on_error(g_zfs, B_TRUE); 581 582 if ((zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { 583 (void) fprintf(stderr, "failed to open ZFS device\n"); 584 return (1); 585 } 586 587 if (argc == 1) { 588 /* 589 * No arguments. Print the available handlers. If there are no 590 * available handlers, direct the user to '-h' for help 591 * information. 592 */ 593 if (print_all_handlers() == 0) { 594 (void) printf("No handlers registered.\n"); 595 (void) printf("Run 'zinject -h' for usage " 596 "information.\n"); 597 } 598 599 return (0); 600 } 601 602 while ((c = getopt(argc, argv, 603 ":aA:b:d:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) { 604 switch (c) { 605 case 'a': 606 flags |= ZINJECT_FLUSH_ARC; 607 break; 608 case 'A': 609 if (strcasecmp(optarg, "degrade") == 0) { 610 action = VDEV_STATE_DEGRADED; 611 } else if (strcasecmp(optarg, "fault") == 0) { 612 action = VDEV_STATE_FAULTED; 613 } else { 614 (void) fprintf(stderr, "invalid action '%s': " 615 "must be 'degrade' or 'fault'\n", optarg); 616 usage(); 617 return (1); 618 } 619 break; 620 case 'b': 621 raw = optarg; 622 break; 623 case 'c': 624 cancel = optarg; 625 break; 626 case 'd': 627 device = optarg; 628 break; 629 case 'e': 630 if (strcasecmp(optarg, "io") == 0) { 631 error = EIO; 632 } else if (strcasecmp(optarg, "checksum") == 0) { 633 error = ECKSUM; 634 } else if (strcasecmp(optarg, "nxio") == 0) { 635 error = ENXIO; 636 } else if (strcasecmp(optarg, "dtl") == 0) { 637 error = ECHILD; 638 } else { 639 (void) fprintf(stderr, "invalid error type " 640 "'%s': must be 'io', 'checksum' or " 641 "'nxio'\n", optarg); 642 usage(); 643 return (1); 644 } 645 break; 646 case 'f': 647 record.zi_freq = atoi(optarg); 648 if (record.zi_freq < 1 || record.zi_freq > 100) { 649 (void) fprintf(stderr, "frequency range must " 650 "be in the range (0, 100]\n"); 651 return (1); 652 } 653 break; 654 case 'F': 655 record.zi_failfast = B_TRUE; 656 break; 657 case 'g': 658 dur_txg = 1; 659 record.zi_duration = (int)strtol(optarg, &end, 10); 660 if (record.zi_duration <= 0 || *end != '\0') { 661 (void) fprintf(stderr, "invalid duration '%s': " 662 "must be a positive integer\n", optarg); 663 usage(); 664 return (1); 665 } 666 /* store duration of txgs as its negative */ 667 record.zi_duration *= -1; 668 break; 669 case 'h': 670 usage(); 671 return (0); 672 case 'I': 673 /* default duration, if one hasn't yet been defined */ 674 nowrites = 1; 675 if (dur_secs == 0 && dur_txg == 0) 676 record.zi_duration = 30; 677 break; 678 case 'l': 679 level = (int)strtol(optarg, &end, 10); 680 if (*end != '\0') { 681 (void) fprintf(stderr, "invalid level '%s': " 682 "must be an integer\n", optarg); 683 usage(); 684 return (1); 685 } 686 break; 687 case 'm': 688 domount = 1; 689 break; 690 case 'p': 691 (void) strlcpy(record.zi_func, optarg, 692 sizeof (record.zi_func)); 693 break; 694 case 'q': 695 quiet = 1; 696 break; 697 case 'r': 698 range = optarg; 699 break; 700 case 's': 701 dur_secs = 1; 702 record.zi_duration = (int)strtol(optarg, &end, 10); 703 if (record.zi_duration <= 0 || *end != '\0') { 704 (void) fprintf(stderr, "invalid duration '%s': " 705 "must be a positive integer\n", optarg); 706 usage(); 707 return (1); 708 } 709 break; 710 case 'T': 711 if (strcasecmp(optarg, "read") == 0) { 712 io_type = ZIO_TYPE_READ; 713 } else if (strcasecmp(optarg, "write") == 0) { 714 io_type = ZIO_TYPE_WRITE; 715 } else if (strcasecmp(optarg, "free") == 0) { 716 io_type = ZIO_TYPE_FREE; 717 } else if (strcasecmp(optarg, "claim") == 0) { 718 io_type = ZIO_TYPE_CLAIM; 719 } else if (strcasecmp(optarg, "all") == 0) { 720 io_type = ZIO_TYPES; 721 } else { 722 (void) fprintf(stderr, "invalid I/O type " 723 "'%s': must be 'read', 'write', 'free', " 724 "'claim' or 'all'\n", optarg); 725 usage(); 726 return (1); 727 } 728 break; 729 case 't': 730 if ((type = name_to_type(optarg)) == TYPE_INVAL && 731 !MOS_TYPE(type)) { 732 (void) fprintf(stderr, "invalid type '%s'\n", 733 optarg); 734 usage(); 735 return (1); 736 } 737 break; 738 case 'u': 739 flags |= ZINJECT_UNLOAD_SPA; 740 break; 741 case 'L': 742 if ((label = name_to_type(optarg)) == TYPE_INVAL && 743 !LABEL_TYPE(type)) { 744 (void) fprintf(stderr, "invalid label type " 745 "'%s'\n", optarg); 746 usage(); 747 return (1); 748 } 749 break; 750 case ':': 751 (void) fprintf(stderr, "option -%c requires an " 752 "operand\n", optopt); 753 usage(); 754 return (1); 755 case '?': 756 (void) fprintf(stderr, "invalid option '%c'\n", 757 optopt); 758 usage(); 759 return (2); 760 } 761 } 762 763 argc -= optind; 764 argv += optind; 765 766 if (cancel != NULL) { 767 /* 768 * '-c' is invalid with any other options. 769 */ 770 if (raw != NULL || range != NULL || type != TYPE_INVAL || 771 level != 0 || record.zi_func[0] != '\0' || 772 record.zi_duration != 0) { 773 (void) fprintf(stderr, "cancel (-c) incompatible with " 774 "any other options\n"); 775 usage(); 776 return (2); 777 } 778 if (argc != 0) { 779 (void) fprintf(stderr, "extraneous argument to '-c'\n"); 780 usage(); 781 return (2); 782 } 783 784 if (strcmp(cancel, "all") == 0) { 785 return (cancel_all_handlers()); 786 } else { 787 int id = (int)strtol(cancel, &end, 10); 788 if (*end != '\0') { 789 (void) fprintf(stderr, "invalid handle id '%s':" 790 " must be an integer or 'all'\n", cancel); 791 usage(); 792 return (1); 793 } 794 return (cancel_handler(id)); 795 } 796 } 797 798 if (device != NULL) { 799 /* 800 * Device (-d) injection uses a completely different mechanism 801 * for doing injection, so handle it separately here. 802 */ 803 if (raw != NULL || range != NULL || type != TYPE_INVAL || 804 level != 0 || record.zi_func[0] != '\0' || 805 record.zi_duration != 0) { 806 (void) fprintf(stderr, "device (-d) incompatible with " 807 "data error injection\n"); 808 usage(); 809 return (2); 810 } 811 812 if (argc != 1) { 813 (void) fprintf(stderr, "device (-d) injection requires " 814 "a single pool name\n"); 815 usage(); 816 return (2); 817 } 818 819 (void) strcpy(pool, argv[0]); 820 dataset[0] = '\0'; 821 822 if (error == ECKSUM) { 823 (void) fprintf(stderr, "device error type must be " 824 "'io' or 'nxio'\n"); 825 return (1); 826 } 827 828 record.zi_iotype = io_type; 829 if (translate_device(pool, device, label, &record) != 0) 830 return (1); 831 if (!error) 832 error = ENXIO; 833 834 if (action != VDEV_STATE_UNKNOWN) 835 return (perform_action(pool, &record, action)); 836 837 } else if (raw != NULL) { 838 if (range != NULL || type != TYPE_INVAL || level != 0 || 839 record.zi_func[0] != '\0' || record.zi_duration != 0) { 840 (void) fprintf(stderr, "raw (-b) format with " 841 "any other options\n"); 842 usage(); 843 return (2); 844 } 845 846 if (argc != 1) { 847 (void) fprintf(stderr, "raw (-b) format expects a " 848 "single pool name\n"); 849 usage(); 850 return (2); 851 } 852 853 (void) strcpy(pool, argv[0]); 854 dataset[0] = '\0'; 855 856 if (error == ENXIO) { 857 (void) fprintf(stderr, "data error type must be " 858 "'checksum' or 'io'\n"); 859 return (1); 860 } 861 862 if (translate_raw(raw, &record) != 0) 863 return (1); 864 if (!error) 865 error = EIO; 866 } else if (record.zi_func[0] != '\0') { 867 if (raw != NULL || range != NULL || type != TYPE_INVAL || 868 level != 0 || device != NULL || record.zi_duration != 0) { 869 (void) fprintf(stderr, "panic (-p) incompatible with " 870 "other options\n"); 871 usage(); 872 return (2); 873 } 874 875 if (argc < 1 || argc > 2) { 876 (void) fprintf(stderr, "panic (-p) injection requires " 877 "a single pool name and an optional id\n"); 878 usage(); 879 return (2); 880 } 881 882 (void) strcpy(pool, argv[0]); 883 if (argv[1] != NULL) 884 record.zi_type = atoi(argv[1]); 885 dataset[0] = '\0'; 886 } else if (record.zi_duration != 0) { 887 if (nowrites == 0) { 888 (void) fprintf(stderr, "-s or -g meaningless " 889 "without -I (ignore writes)\n"); 890 usage(); 891 return (2); 892 } else if (dur_secs && dur_txg) { 893 (void) fprintf(stderr, "choose a duration either " 894 "in seconds (-s) or a number of txgs (-g) " 895 "but not both\n"); 896 usage(); 897 return (2); 898 } else if (argc != 1) { 899 (void) fprintf(stderr, "ignore writes (-I) " 900 "injection requires a single pool name\n"); 901 usage(); 902 return (2); 903 } 904 905 (void) strcpy(pool, argv[0]); 906 dataset[0] = '\0'; 907 } else if (type == TYPE_INVAL) { 908 if (flags == 0) { 909 (void) fprintf(stderr, "at least one of '-b', '-d', " 910 "'-t', '-a', '-p', '-I' or '-u' " 911 "must be specified\n"); 912 usage(); 913 return (2); 914 } 915 916 if (argc == 1 && (flags & ZINJECT_UNLOAD_SPA)) { 917 (void) strcpy(pool, argv[0]); 918 dataset[0] = '\0'; 919 } else if (argc != 0) { 920 (void) fprintf(stderr, "extraneous argument for " 921 "'-f'\n"); 922 usage(); 923 return (2); 924 } 925 926 flags |= ZINJECT_NULL; 927 } else { 928 if (argc != 1) { 929 (void) fprintf(stderr, "missing object\n"); 930 usage(); 931 return (2); 932 } 933 934 if (error == ENXIO) { 935 (void) fprintf(stderr, "data error type must be " 936 "'checksum' or 'io'\n"); 937 return (1); 938 } 939 940 if (translate_record(type, argv[0], range, level, &record, pool, 941 dataset) != 0) 942 return (1); 943 if (!error) 944 error = EIO; 945 } 946 947 /* 948 * If this is pool-wide metadata, unmount everything. The ioctl() will 949 * unload the pool, so that we trigger spa-wide reopen of metadata next 950 * time we access the pool. 951 */ 952 if (dataset[0] != '\0' && domount) { 953 if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL) 954 return (1); 955 956 if (zfs_unmount(zhp, NULL, 0) != 0) 957 return (1); 958 } 959 960 record.zi_error = error; 961 962 ret = register_handler(pool, flags, &record, quiet); 963 964 if (dataset[0] != '\0' && domount) 965 ret = (zfs_mount(zhp, NULL, 0) != 0); 966 967 libzfs_fini(g_zfs); 968 969 return (ret); 970 } 971