summaryrefslogtreecommitdiffstats
path: root/cmd/zinject/zinject.c
diff options
context:
space:
mode:
authorGeorge.Wilson <[email protected]>2013-04-29 15:49:23 -0700
committerBrian Behlendorf <[email protected]>2013-05-01 17:05:52 -0700
commitcc92e9d0c3e67a7e66c844466f85696a087bf60a (patch)
tree97f27cdfb4a662dee0de0d916e7c92cc0e03a605 /cmd/zinject/zinject.c
parent57f5a2008e2e6acf58934cf43c5fdca0faffa73e (diff)
3246 ZFS I/O deadman thread
Reviewed by: Matt Ahrens <[email protected]> Reviewed by: Eric Schrock <[email protected]> Reviewed by: Christopher Siden <[email protected]> Approved by: Garrett D'Amore <[email protected]> NOTES: This patch has been reworked from the original in the following ways to accomidate Linux ZFS implementation *) Usage of the cyclic interface was replaced by the delayed taskq interface. This avoids the need to implement new compatibility code and allows us to rely on the existing taskq implementation. *) An extern for zfs_txg_synctime_ms was added to sys/dsl_pool.h because declaring externs in source files as was done in the original patch is just plain wrong. *) Instead of panicing the system when the deadman triggers a zevent describing the blocked vdev and the first pending I/O is posted. If the panic behavior is desired Linux provides other generic methods to panic the system when threads are observed to hang. *) For reference, to delay zios by 30 seconds for testing you can use zinject as follows: 'zinject -d <vdev> -D30 <pool>' References: illumos/illumos-gate@283b84606b6fc326692c03273de1774e8c122f9a https://www.illumos.org/issues/3246 Ported-by: Brian Behlendorf <[email protected]> Closes #1396
Diffstat (limited to 'cmd/zinject/zinject.c')
-rw-r--r--cmd/zinject/zinject.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/cmd/zinject/zinject.c b/cmd/zinject/zinject.c
index d584eadd8..9ae3f9ddc 100644
--- a/cmd/zinject/zinject.c
+++ b/cmd/zinject/zinject.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -235,8 +236,8 @@ usage(void)
"\t\t'pad1', or 'pad2'.\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"
@@ -589,7 +590,7 @@ main(int argc, char **argv)
}
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;
@@ -615,6 +616,16 @@ main(int argc, char **argv)
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;
@@ -679,6 +690,7 @@ main(int argc, char **argv)
case 'p':
(void) strlcpy(record.zi_func, optarg,
sizeof (record.zi_func));
+ record.zi_cmd = ZINJECT_PANIC;
break;
case 'q':
quiet = 1;
@@ -762,13 +774,15 @@ main(int argc, char **argv)
return (1);
}
+ 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();
@@ -800,8 +814,7 @@ main(int argc, char **argv)
* 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();
@@ -835,7 +848,7 @@ main(int argc, char **argv)
} 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();
@@ -858,13 +871,14 @@ main(int argc, char **argv)
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();
@@ -882,7 +896,7 @@ main(int argc, char **argv)
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");
@@ -936,6 +950,7 @@ main(int argc, char **argv)
return (1);
}
+ record.zi_cmd = ZINJECT_DATA_FAULT;
if (translate_record(type, argv[0], range, level, &record, pool,
dataset) != 0)
return (1);