Lines Matching +full:n +full:- +full:mos

1 // SPDX-License-Identifier: CDDL-1.0
10 * or https://opensource.org/licenses/CDDL-1.0.
26 * Copyright (c) 2023-2025, Klara, Inc.
33 * from a user-visible object type and name to an internal representation.
39 * Errors can be injected into a particular vdev using the '-d' option. This
42 * ECHILD, and EILSEQ. These can be controlled through the '-e' option and the
47 * only apply to read operations (-T read) and will flip a bit after the device
50 * For label faults, the -L option must be specified. This allows faults
56 * zinject -d device [-e errno] [-L <uber | nvlist | pad1 | pad2>] pool
72 * The following MOS objects are special. Instead of injecting
76 * mos Any data in the MOS
99 * These types should be self-explanatory. This tuple is then passed to the
102 * is used when translating existing faults into a human-readable string.
108 * zinject <-a | -u pool>
109 * zinject -c <id|all>
110 * zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level]
111 * [-r range] <object>
112 * zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool
117 * The '-c' option will clear the given handler, or all handlers if 'all' is
120 * The '-e' option takes a string describing the errno to simulate. This must
122 * will result in the same behavior, but RAID-Z will produce a different set of
125 * The '-a', '-u', and '-m' flags toggle internal flush behavior. If '-a' is
126 * specified, then the ARC cache is flushed appropriately. If '-u' is
128 * specified independently of any other handlers. The '-m' flag automatically
132 * The '-f' flag controls the frequency of errors injected, expressed as a
141 * human-readable interface has been designed. It allows developers to specify
168 "mos",
209 return ("-"); in type_to_name()
235 return (-1); in str_to_err()
283 "usage:\n" in usage()
284 "\n" in usage()
285 "\tzinject\n" in usage()
286 "\n" in usage()
287 "\t\tList all active injection records.\n" in usage()
288 "\n" in usage()
289 "\tzinject -c <id|all>\n" in usage()
290 "\n" in usage()
291 "\t\tClear the particular record (if given a numeric ID), or\n" in usage()
292 "\t\tall records if 'all' is specified.\n" in usage()
293 "\n" in usage()
294 "\tzinject -p <function name> pool\n" in usage()
295 "\t\tInject a panic fault at the specified function. Only \n" in usage()
296 "\t\tfunctions which call spa_vdev_config_exit(), or \n" in usage()
297 "\t\tspa_vdev_exit() will trigger a panic.\n" in usage()
298 "\n" in usage()
299 "\tzinject -d device [-e errno] [-L <nvlist|uber|pad1|pad2>] [-F]\n" in usage()
300 "\t\t[-T <read|write|free|claim|flush|all>] [-f frequency] pool\n\n" in usage()
301 "\t\tInject a fault into a particular device or the device's\n" in usage()
302 "\t\tlabel. Label injection can either be 'nvlist', 'uber',\n " in usage()
303 "\t\t'pad1', or 'pad2'.\n" in usage()
304 "\t\t'errno' can be 'nxio' (the default), 'io', 'dtl',\n" in usage()
305 "\t\t'corrupt' (bit flip), or 'noop' (successfully do nothing).\n" in usage()
306 "\t\t'frequency' is a value between 0.0001 and 100.0 that limits\n" in usage()
307 "\t\tdevice error injection to a percentage of the IOs.\n" in usage()
308 "\n" in usage()
309 "\tzinject -d device -A <degrade|fault> -D <delay secs> pool\n" in usage()
310 "\t\tPerform a specific action on a particular device.\n" in usage()
311 "\n" in usage()
312 "\tzinject -d device -D latency:lanes pool\n" in usage()
313 "\n" in usage()
314 "\t\tAdd an artificial delay to IO requests on a particular\n" in usage()
315 "\t\tdevice, such that the requests take a minimum of 'latency'\n" in usage()
316 "\t\tmilliseconds to complete. Each delay has an associated\n" in usage()
317 "\t\tnumber of 'lanes' which defines the number of concurrent\n" in usage()
318 "\t\tIO requests that can be processed.\n" in usage()
319 "\n" in usage()
320 "\t\tFor example, with a single lane delay of 10 ms (-D 10:1),\n" in usage()
321 "\t\tthe device will only be able to service a single IO request\n" in usage()
322 "\t\tat a time with each request taking 10 ms to complete. So,\n" in usage()
323 "\t\tif only a single request is submitted every 10 ms, the\n" in usage()
324 "\t\taverage latency will be 10 ms; but if more than one request\n" in usage()
325 "\t\tis submitted every 10 ms, the average latency will be more\n" in usage()
326 "\t\tthan 10 ms.\n" in usage()
327 "\n" in usage()
328 "\t\tSimilarly, if a delay of 10 ms is specified to have two\n" in usage()
329 "\t\tlanes (-D 10:2), then the device will be able to service\n" in usage()
330 "\t\ttwo requests at a time, each with a minimum latency of\n" in usage()
331 "\t\t10 ms. So, if two requests are submitted every 10 ms, then\n" in usage()
332 "\t\tthe average latency will be 10 ms; but if more than two\n" in usage()
333 "\t\trequests are submitted every 10 ms, the average latency\n" in usage()
334 "\t\twill be more than 10 ms.\n" in usage()
335 "\n" in usage()
336 "\t\tAlso note, these delays are additive. So two invocations\n" in usage()
337 "\t\tof '-D 10:1', is roughly equivalent to a single invocation\n" in usage()
338 "\t\tof '-D 10:2'. This also means, one can specify multiple\n" in usage()
339 "\t\tlanes with differing target latencies. For example, an\n" in usage()
340 "\t\tinvocation of '-D 10:1' followed by '-D 25:2' will\n" in usage()
341 "\t\tcreate 3 lanes on the device; one lane with a latency\n" in usage()
342 "\t\tof 10 ms and two lanes with a 25 ms latency.\n" in usage()
343 "\n" in usage()
344 "\tzinject -P import|export -s <seconds> pool\n" in usage()
345 "\t\tAdd an artificial delay to a future pool import or export,\n" in usage()
346 "\t\tsuch that the operation takes a minimum of supplied seconds\n" in usage()
347 "\t\tto complete.\n" in usage()
348 "\n" in usage()
349 "\tzinject -I [-s <seconds> | -g <txgs>] pool\n" in usage()
350 "\t\tCause the pool to stop writing blocks yet not\n" in usage()
351 "\t\treport errors for a duration. Simulates buggy hardware\n" in usage()
352 "\t\tthat fails to honor cache flush requests.\n" in usage()
353 "\t\tDefault duration is 30 seconds. The machine is panicked\n" in usage()
354 "\t\tat the end of the duration.\n" in usage()
355 "\n" in usage()
356 "\tzinject -b objset:object:level:blkid pool\n" in usage()
357 "\n" in usage()
358 "\t\tInject an error into pool 'pool' with the numeric bookmark\n" in usage()
359 "\t\tspecified by the remaining tuple. Each number is in\n" in usage()
360 "\t\thexadecimal, and only one block can be specified.\n" in usage()
361 "\n" in usage()
362 "\tzinject [-q] <-t type> [-C dvas] [-e errno] [-l level]\n" in usage()
363 "\t\t[-r range] [-a] [-m] [-u] [-f freq] <object>\n" in usage()
364 "\n" in usage()
365 "\t\tInject an error into the object specified by the '-t' option\n" in usage()
366 "\t\tand the object descriptor. The 'object' parameter is\n" in usage()
367 "\t\tinterpreted depending on the '-t' option.\n" in usage()
368 "\n" in usage()
369 "\t\t-q\tQuiet mode. Only print out the handler number added.\n" in usage()
370 "\t\t-e\tInject a specific error. Must be one of 'io',\n" in usage()
371 "\t\t\t'checksum', 'decompress', or 'decrypt'. Default is 'io'.\n" in usage()
372 "\t\t-C\tInject the given error only into specific DVAs. The\n" in usage()
373 "\t\t\tDVAs should be specified as a list of 0-indexed DVAs\n" in usage()
374 "\t\t\tseparated by commas (ex. '0,2').\n" in usage()
375 "\t\t-l\tInject error at a particular block level. Default is " in usage()
376 "0.\n" in usage()
377 "\t\t-m\tAutomatically remount underlying filesystem.\n" in usage()
378 "\t\t-r\tInject error over a particular logical range of an\n" in usage()
379 "\t\t\tobject. Will be translated to the appropriate blkid\n" in usage()
380 "\t\t\trange according to the object's properties.\n" in usage()
381 "\t\t-a\tFlush the ARC cache. Can be specified without any\n" in usage()
382 "\t\t\tassociated object.\n" in usage()
383 "\t\t-u\tUnload the associated pool. Can be specified with only\n" in usage()
384 "\t\t\ta pool object.\n" in usage()
385 "\t\t-f\tOnly inject errors a fraction of the time. Expressed as\n" in usage()
386 "\t\t\ta percentage between 0.0001 and 100.\n" in usage()
387 "\n" in usage()
388 "\t-t data\t\tInject an error into the plain file contents of a\n" in usage()
389 "\t\t\tfile. The object must be specified as a complete path\n" in usage()
390 "\t\t\tto a file on a ZFS filesystem.\n" in usage()
391 "\n" in usage()
392 "\t-t dnode\tInject an error into the metadnode in the block\n" in usage()
393 "\t\t\tcorresponding to the dnode for a file or directory. The\n" in usage()
394 "\t\t\t'-r' option is incompatible with this mode. The object\n" in usage()
395 "\t\t\tis specified as a complete path to a file or directory\n" in usage()
396 "\t\t\ton a ZFS filesystem.\n" in usage()
397 "\n" in usage()
398 "\t-t <mos>\tInject errors into the MOS for objects of the given\n" in usage()
399 "\t\t\ttype. Valid types are: mos, mosdir, config, bpobj,\n" in usage()
400 "\t\t\tspacemap, metaslab, errlog. The only valid <object> is\n" in usage()
401 "\t\t\tthe poolname.\n"); in usage()
417 (void) fprintf(stderr, "Unable to list handlers: %s\n", in iter_handlers()
419 return (-1); in iter_handlers()
431 if (record->zi_guid != 0 || record->zi_func[0] != '\0' || in print_data_handler()
432 record->zi_duration != 0) { in print_data_handler()
437 (void) printf("%3s %-15s %-6s %-6s %-8s %3s %-4s " in print_data_handler()
438 "%-15s %-6s %-15s\n", "ID", "POOL", "OBJSET", "OBJECT", in print_data_handler()
440 (void) printf("--- --------------- ------ " in print_data_handler()
441 "------ -------- --- ---- --------------- " in print_data_handler()
442 "------ ------\n"); in print_data_handler()
448 if (record->zi_start == 0 && record->zi_end == -1ULL) in print_data_handler()
452 (u_longlong_t)record->zi_start, in print_data_handler()
453 (u_longlong_t)record->zi_end); in print_data_handler()
456 (void) printf("%3d %-15s %-6llu %-6llu %-8s %-3d 0x%02x %-15s " in print_data_handler()
457 "%6" PRIu64 " %6" PRIu64 "\n", id, pool, in print_data_handler()
458 (u_longlong_t)record->zi_objset, in print_data_handler()
459 (u_longlong_t)record->zi_object, type_to_name(record->zi_type), in print_data_handler()
460 record->zi_level, record->zi_dvas, rangebuf, in print_data_handler()
461 record->zi_match_count, record->zi_inject_count); in print_data_handler()
472 if (record->zi_guid == 0 || record->zi_func[0] != '\0') in print_device_handler()
475 if (record->zi_cmd == ZINJECT_DELAY_IO) in print_device_handler()
479 (void) printf("%3s %-15s %-16s %-5s %-10s %-9s " in print_device_handler()
480 "%-6s %-6s\n", in print_device_handler()
484 "--- --------------- ---------------- " in print_device_handler()
485 "----- ---------- --------- " in print_device_handler()
486 "------ ------\n"); in print_device_handler()
491 double freq = record->zi_freq == 0 ? 100.0f : in print_device_handler()
492 (((double)record->zi_freq) / ZI_PERCENTAGE_MAX) * 100.0f; in print_device_handler()
494 (void) printf("%3d %-15s %llx %-5s %-10s %8.4f%% " in print_device_handler()
495 "%6" PRIu64 " %6" PRIu64 "\n", id, pool, in print_device_handler()
496 (u_longlong_t)record->zi_guid, in print_device_handler()
497 iotype_to_str(record->zi_iotype), err_to_str(record->zi_error), in print_device_handler()
498 freq, record->zi_match_count, record->zi_inject_count); in print_device_handler()
509 if (record->zi_guid == 0 || record->zi_func[0] != '\0') in print_delay_handler()
512 if (record->zi_cmd != ZINJECT_DELAY_IO) in print_delay_handler()
516 (void) printf("%3s %-15s %-16s %-10s %-5s %-9s " in print_delay_handler()
517 "%-6s %-6s\n", in print_delay_handler()
520 (void) printf("--- --------------- ---------------- " in print_delay_handler()
521 "---------- ----- --------- " in print_delay_handler()
522 "------ ------\n"); in print_delay_handler()
527 double freq = record->zi_freq == 0 ? 100.0f : in print_delay_handler()
528 (((double)record->zi_freq) / ZI_PERCENTAGE_MAX) * 100.0f; in print_delay_handler()
530 (void) printf("%3d %-15s %llx %10llu %5llu %8.4f%% " in print_delay_handler()
531 "%6" PRIu64 " %6" PRIu64 "\n", id, pool, in print_delay_handler()
532 (u_longlong_t)record->zi_guid, in print_delay_handler()
533 (u_longlong_t)NSEC2MSEC(record->zi_timer), in print_delay_handler()
534 (u_longlong_t)record->zi_nlanes, in print_delay_handler()
535 freq, record->zi_match_count, record->zi_inject_count); in print_delay_handler()
546 if (record->zi_func[0] == '\0') in print_panic_handler()
550 (void) printf("%3s %-15s %s\n", "ID", "POOL", "FUNCTION"); in print_panic_handler()
551 (void) printf("--- --------------- ----------------\n"); in print_panic_handler()
556 (void) printf("%3d %-15s %s\n", id, pool, record->zi_func); in print_panic_handler()
567 if (record->zi_cmd != ZINJECT_DELAY_IMPORT && in print_pool_delay_handler()
568 record->zi_cmd != ZINJECT_DELAY_EXPORT) { in print_pool_delay_handler()
573 (void) printf("%3s %-19s %-11s %s\n", in print_pool_delay_handler()
575 (void) printf("--- ------------------- -----------" in print_pool_delay_handler()
576 " -------\n"); in print_pool_delay_handler()
581 (void) printf("%3d %-19s %-11llu %s\n", in print_pool_delay_handler()
582 id, pool, (u_longlong_t)record->zi_duration, in print_pool_delay_handler()
583 record->zi_cmd == ZINJECT_DELAY_IMPORT ? "import": "export"); in print_pool_delay_handler()
600 (void) printf("\n"); in print_all_handlers()
607 (void) printf("\n"); in print_all_handlers()
614 (void) printf("\n"); in print_all_handlers()
621 (void) printf("\n"); in print_all_handlers()
640 (void) fprintf(stderr, "failed to remove handler %d: %s\n", in cancel_one_handler()
657 (void) printf("removed all registered handlers\n"); in cancel_all_handlers()
673 (void) fprintf(stderr, "failed to remove handler %d: %s\n", in cancel_handler()
678 (void) printf("removed handler %d\n", id); in cancel_handler()
704 if (record->zi_cmd == ZINJECT_DELAY_IMPORT) in register_handler()
706 if (record->zi_cmd == ZINJECT_DELAY_EXPORT) in register_handler()
711 if (record->zi_cmd == ZINJECT_DELAY_IMPORT) in register_handler()
717 (void) fprintf(stderr, "failed to add handler: %s\n", errmsg); in register_handler()
725 (void) printf("%llu\n", (u_longlong_t)zc.zc_guid); in register_handler()
728 "properties:\n", (u_longlong_t)zc.zc_guid); in register_handler()
729 (void) printf(" pool: %s\n", pool); in register_handler()
730 if (record->zi_guid) { in register_handler()
731 (void) printf(" vdev: %llx\n", in register_handler()
732 (u_longlong_t)record->zi_guid); in register_handler()
733 } else if (record->zi_func[0] != '\0') { in register_handler()
734 (void) printf(" panic function: %s\n", in register_handler()
735 record->zi_func); in register_handler()
736 } else if (record->zi_duration > 0) { in register_handler()
737 (void) printf(" time: %lld seconds\n", in register_handler()
738 (u_longlong_t)record->zi_duration); in register_handler()
739 } else if (record->zi_duration < 0) { in register_handler()
740 (void) printf(" txgs: %lld \n", in register_handler()
741 (u_longlong_t)-record->zi_duration); in register_handler()
742 } else if (record->zi_timer > 0) { in register_handler()
743 (void) printf(" timer: %lld ms\n", in register_handler()
744 (u_longlong_t)NSEC2MSEC(record->zi_timer)); in register_handler()
746 (void) printf("objset: %llu\n", in register_handler()
747 (u_longlong_t)record->zi_objset); in register_handler()
748 (void) printf("object: %llu\n", in register_handler()
749 (u_longlong_t)record->zi_object); in register_handler()
750 (void) printf(" type: %llu\n", in register_handler()
751 (u_longlong_t)record->zi_type); in register_handler()
752 (void) printf(" level: %d\n", record->zi_level); in register_handler()
753 if (record->zi_start == 0 && in register_handler()
754 record->zi_end == -1ULL) in register_handler()
755 (void) printf(" range: all\n"); in register_handler()
757 (void) printf(" range: [%llu, %llu)\n", in register_handler()
758 (u_longlong_t)record->zi_start, in register_handler()
759 (u_longlong_t)record->zi_end); in register_handler()
760 (void) printf(" dvas: 0x%x\n", record->zi_dvas); in register_handler()
774 zc.zc_guid = record->zi_guid; in perform_action()
794 * off this value being non-zero in translate_device(), to in parse_delay()
837 * "1" -> 0b0010 (0x2)
838 * "0,1" -> 0b0011 (0x3)
839 * "0,1,2" -> 0b0111 (0x7)
862 if (mask & (1 << ((*c) - '0'))) in parse_dvas()
865 mask |= (1 << ((*c) - '0')); in parse_dvas()
915 (void) fprintf(stderr, "%s\n", libzfs_error_init(errno)); in main()
922 (void) fprintf(stderr, "failed to open ZFS device\n"); in main()
930 * available handlers, direct the user to '-h' for help in main()
934 (void) printf("No handlers registered.\n"); in main()
935 (void) printf("Run 'zinject -h' for usage " in main()
936 "information.\n"); in main()
943 ":aA:b:C:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:P:")) != -1) { in main()
955 "must be 'degrade' or 'fault'\n", optarg); in main()
972 "commas.\n", optarg); in main()
988 "value: '%s'\n", optarg); in main()
999 "decrypt nxio dtl corrupt noop\n", in main()
1010 "be in the range [0.0001, 100.0]\n", in main()
1025 "must be a positive integer\n", optarg); in main()
1031 record.zi_duration *= -1; in main()
1047 "must be an integer\n", optarg); in main()
1068 "must be 'import' or 'export'\n", optarg); in main()
1086 "must be a positive integer\n", optarg); in main()
1097 "'claim', 'flush' or 'all'\n", optarg); in main()
1106 (void) fprintf(stderr, "invalid type '%s'\n", in main()
1120 "'%s'\n", optarg); in main()
1127 (void) fprintf(stderr, "option -%c requires an " in main()
1128 "operand\n", optopt); in main()
1133 (void) fprintf(stderr, "invalid option '%c'\n", in main()
1141 argc -= optind; in main()
1149 * '-c' is invalid with any other options. in main()
1154 (void) fprintf(stderr, "cancel (-c) incompatible with " in main()
1155 "any other options\n"); in main()
1161 (void) fprintf(stderr, "extraneous argument to '-c'\n"); in main()
1173 " must be an integer or 'all'\n", cancel); in main()
1184 * Device (-d) injection uses a completely different mechanism in main()
1190 (void) fprintf(stderr, "device (-d) incompatible with " in main()
1191 "data error injection\n"); in main()
1198 (void) fprintf(stderr, "device (-d) injection requires " in main()
1199 "a single pool name\n"); in main()
1210 "'io', 'nxio' or 'corrupt'\n"); in main()
1218 "io type read and a frequency value\n"); in main()
1237 "must be 'read' or 'write'\n"); in main()
1254 (void) fprintf(stderr, "raw (-b) format with " in main()
1255 "any other options\n"); in main()
1262 (void) fprintf(stderr, "raw (-b) format expects a " in main()
1263 "single pool name\n"); in main()
1274 "'checksum' or 'io'\n"); in main()
1291 "options\n", "import|export delay (-P)"); in main()
1298 (void) fprintf(stderr, "panic (-p) injection requires " in main()
1299 "a single pool name and an optional id\n"); in main()
1315 "options\n", "import|export delay (-P)"); in main()
1322 (void) fprintf(stderr, "import|export delay (-P) " in main()
1323 "injection requires a duration (-s) and a single " in main()
1324 "pool name\n"); in main()
1334 (void) fprintf(stderr, "hardware failure (-I) " in main()
1335 "incompatible with other options\n"); in main()
1342 (void) fprintf(stderr, "-s or -g meaningless " in main()
1343 "without -I (ignore writes)\n"); in main()
1349 "in seconds (-s) or a number of txgs (-g) " in main()
1350 "but not both\n"); in main()
1355 (void) fprintf(stderr, "ignore writes (-I) " in main()
1356 "injection requires a single pool name\n"); in main()
1366 (void) fprintf(stderr, "at least one of '-b', '-d', " in main()
1367 "'-t', '-a', '-p', '-I' or '-u' " in main()
1368 "must be specified\n"); in main()
1379 "'-f'\n"); in main()
1388 (void) fprintf(stderr, "missing object\n"); in main()
1396 "'checksum' or 'io'\n"); in main()
1403 (void) fprintf(stderr, "the '-C' option may " in main()
1405 "'decrypt' and 'decompress'\n"); in main()
1416 "may only be injected for 'data' types\n"); in main()
1442 * If this is pool-wide metadata, unmount everything. The ioctl() will in main()
1443 * unload the pool, so that we trigger spa-wide reopen of metadata next in main()