*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
"\t\tInject a fault into a particular device or the device's\n"
"\t\tlabel. Label injection can either be 'nvlist', 'uber',\n "
"\t\t'pad1', or 'pad2'.\n"
- "\t\t'errno' can either be 'nxio' (the default) or 'io'.\n"
+ "\t\t'errno' can be 'nxio' (the default), 'io', or 'dtl'.\n"
"\n"
- "\tzinject -d device -A <degrade|fault> pool\n"
- "\t\tPerform a specific action on a particular device\n"
+ "\tzinject -d device -A <degrade|fault> -D <delay secs> pool\n"
+ "\t\tPerform a specific action on a particular device.\n"
"\n"
"\tzinject -I [-s <seconds> | -g <txgs>] pool\n"
"\t\tCause the pool to stop writing blocks yet not\n"
static int
print_all_handlers(void)
{
- int count = 0;
+ int count = 0, total = 0;
(void) iter_handlers(print_device_handler, &count);
- (void) printf("\n");
- count = 0;
+ if (count > 0) {
+ total += count;
+ (void) printf("\n");
+ count = 0;
+ }
+
(void) iter_handlers(print_data_handler, &count);
- (void) printf("\n");
- count = 0;
+ if (count > 0) {
+ total += count;
+ (void) printf("\n");
+ count = 0;
+ }
+
(void) iter_handlers(print_panic_handler, &count);
- return (count);
+ return (count + total);
}
/* ARGSUSED */
zinject_record_t record = { 0 };
char pool[MAXNAMELEN];
char dataset[MAXNAMELEN];
- zfs_handle_t *zhp;
+ zfs_handle_t *zhp = NULL;
int nowrites = 0;
int dur_txg = 0;
int dur_secs = 0;
int ret;
int flags = 0;
- if ((g_zfs = libzfs_init()) == NULL) {
- (void) fprintf(stderr, "internal error: failed to "
- "initialize ZFS library\n");
+ if ((g_zfs = libzfs_init()) == NULL)
return (1);
- }
libzfs_print_on_error(g_zfs, B_TRUE);
}
while ((c = getopt(argc, argv,
- ":aA:b:d:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
+ ":aA:b:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
switch (c) {
case 'a':
flags |= ZINJECT_FLUSH_ARC;
case 'd':
device = optarg;
break;
+ case 'D':
+ errno = 0;
+ record.zi_timer = strtoull(optarg, &end, 10);
+ if (errno != 0 || *end != '\0') {
+ (void) fprintf(stderr, "invalid i/o delay "
+ "value: '%s'\n", optarg);
+ usage();
+ return (1);
+ }
+ break;
case 'e':
if (strcasecmp(optarg, "io") == 0) {
error = EIO;
error = ECKSUM;
} else if (strcasecmp(optarg, "nxio") == 0) {
error = ENXIO;
+ } else if (strcasecmp(optarg, "dtl") == 0) {
+ error = ECHILD;
} else {
(void) fprintf(stderr, "invalid error type "
"'%s': must be 'io', 'checksum' or "
case 'p':
(void) strlcpy(record.zi_func, optarg,
sizeof (record.zi_func));
+ record.zi_cmd = ZINJECT_PANIC;
break;
case 'q':
quiet = 1;
argc -= optind;
argv += optind;
+ if (record.zi_duration != 0)
+ record.zi_cmd = ZINJECT_IGNORED_WRITES;
+
if (cancel != NULL) {
/*
* '-c' is invalid with any other options.
*/
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
- level != 0 || record.zi_func[0] != '\0' ||
- record.zi_duration != 0) {
+ level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) {
(void) fprintf(stderr, "cancel (-c) incompatible with "
"any other options\n");
usage();
* for doing injection, so handle it separately here.
*/
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
- level != 0 || record.zi_func[0] != '\0' ||
- record.zi_duration != 0) {
+ level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) {
(void) fprintf(stderr, "device (-d) incompatible with "
"data error injection\n");
usage();
} else if (raw != NULL) {
if (range != NULL || type != TYPE_INVAL || level != 0 ||
- record.zi_func[0] != '\0' || record.zi_duration != 0) {
+ record.zi_cmd != ZINJECT_UNINITIALIZED) {
(void) fprintf(stderr, "raw (-b) format with "
"any other options\n");
usage();
return (1);
}
+ record.zi_cmd = ZINJECT_DATA_FAULT;
if (translate_raw(raw, &record) != 0)
return (1);
if (!error)
error = EIO;
- } else if (record.zi_func[0] != '\0') {
+ } else if (record.zi_cmd == ZINJECT_PANIC) {
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
- level != 0 || device != NULL || record.zi_duration != 0) {
+ level != 0 || device != NULL) {
(void) fprintf(stderr, "panic (-p) incompatible with "
"other options\n");
usage();
if (argv[1] != NULL)
record.zi_type = atoi(argv[1]);
dataset[0] = '\0';
- } else if (record.zi_duration != 0) {
+ } else if (record.zi_cmd == ZINJECT_IGNORED_WRITES) {
if (nowrites == 0) {
(void) fprintf(stderr, "-s or -g meaningless "
"without -I (ignore writes)\n");
return (1);
}
+ record.zi_cmd = ZINJECT_DATA_FAULT;
if (translate_record(type, argv[0], range, level, &record, pool,
dataset) != 0)
return (1);
if (dataset[0] != '\0' && domount) {
if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
return (1);
-
if (zfs_unmount(zhp, NULL, 0) != 0)
return (1);
}