diff options
author | mm <mm@FreeBSD.org> | 2013-02-25 12:33:31 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2013-02-25 12:33:31 +0000 |
commit | 935fd1194aa4a1bf2f3e80315a915faa331dc729 (patch) | |
tree | ec42bfc38bb1575d8989dd9b950b2a8672bdf3cd /cddl | |
parent | 75d62de01add614d86b5cf30bd3b8157f26d2812 (diff) | |
download | FreeBSD-src-935fd1194aa4a1bf2f3e80315a915faa331dc729.zip FreeBSD-src-935fd1194aa4a1bf2f3e80315a915faa331dc729.tar.gz |
MFV v242732:
Merge the ZFS I/O deadman thread from vendor (illumos).
This feature panics the system on hanging ZFS I/O, helps debugging
and resumes failed service.
The panic behavior can be controlled with the loader-only tunables:
vfs.zfs.deadman_enabled (enable or disable panic on stalled ZFS I/O)
vfs.zfs.deadman_synctime (expiration time for stalled ZFS I/O)
By default, ZFS I/O deadman is enabled by default on amd64 and i386
excluding virtual guest machines.
Illumos ZFS issues:
3246 ZFS I/O deadman thread
References:
https://www.illumos.org/issues/3246
MFC after: 2 weeks
Diffstat (limited to 'cddl')
4 files changed, 100 insertions, 9 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zinject/translate.c b/cddl/contrib/opensolaris/cmd/zinject/translate.c index 442f220..af25d3c 100644 --- a/cddl/contrib/opensolaris/cmd/zinject/translate.c +++ b/cddl/contrib/opensolaris/cmd/zinject/translate.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <libzfs.h> @@ -455,6 +456,20 @@ translate_device(const char *pool, const char *device, err_type_t label_type, &record->zi_guid) == 0); } + /* + * Device faults can take on three different forms: + * 1). delayed or hanging I/O + * 2). zfs label faults + * 3). generic disk faults + */ + if (record->zi_timer != 0) { + record->zi_cmd = ZINJECT_DELAY_IO; + } else if (label_type != TYPE_INVAL) { + record->zi_cmd = ZINJECT_LABEL_FAULT; + } else { + record->zi_cmd = ZINJECT_DEVICE_FAULT; + } + switch (label_type) { case TYPE_LABEL_UBERBLOCK: record->zi_start = offsetof(vdev_label_t, vl_uberblock[0]); diff --git a/cddl/contrib/opensolaris/cmd/zinject/zinject.c b/cddl/contrib/opensolaris/cmd/zinject/zinject.c index d17ed53..994d687 100644 --- a/cddl/contrib/opensolaris/cmd/zinject/zinject.c +++ b/cddl/contrib/opensolaris/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. */ /* @@ -603,7 +604,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; @@ -629,6 +630,15 @@ main(int argc, char **argv) case 'd': device = optarg; break; + case 'D': + 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; @@ -693,6 +703,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; @@ -766,13 +777,15 @@ main(int argc, char **argv) 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(); @@ -804,8 +817,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(); @@ -839,7 +851,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(); @@ -862,13 +874,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(); @@ -886,7 +899,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"); @@ -940,6 +953,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); diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c b/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c index 56bf718..25dc520 100644 --- a/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c +++ b/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c @@ -45,6 +45,9 @@ int aok; uint64_t physmem; vnode_t *rootdir = (vnode_t *)0xabcd1234; char hw_serial[HW_HOSTID_LEN]; +#ifdef illumos +kmutex_t cpu_lock; +#endif struct utsname utsname = { "userland", "libzpool", "1", "1", "na" @@ -842,6 +845,28 @@ ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) return (0); } +#ifdef illumos +/* ARGSUSED */ +cyclic_id_t +cyclic_add(cyc_handler_t *hdlr, cyc_time_t *when) +{ + return (1); +} + +/* ARGSUSED */ +void +cyclic_remove(cyclic_id_t id) +{ +} + +/* ARGSUSED */ +int +cyclic_reprogram(cyclic_id_t id, hrtime_t expiration) +{ + return (1); +} +#endif + /* * ========================================================================= * kernel emulation setup & teardown @@ -875,6 +900,10 @@ kernel_init(int mode) system_taskq_init(); +#ifdef illumos + mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL); +#endif + spa_init(mode); } diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h index 11fb681..469c59f 100644 --- a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h +++ b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h @@ -457,6 +457,9 @@ extern vnode_t *rootdir; extern void delay(clock_t ticks); +#define SEC_TO_TICK(sec) ((sec) * hz) +#define NSEC_TO_TICK(usec) ((usec) / (NANOSEC / hz)) + #define gethrestime_sec() time(NULL) #define gethrestime(t) \ do {\ @@ -624,6 +627,36 @@ typedef uint32_t idmap_rid_t; #define ERESTART (-1) #endif +#ifdef illumos +/* + * Cyclic information + */ +extern kmutex_t cpu_lock; + +typedef uintptr_t cyclic_id_t; +typedef uint16_t cyc_level_t; +typedef void (*cyc_func_t)(void *); + +#define CY_LOW_LEVEL 0 +#define CY_INFINITY INT64_MAX +#define CYCLIC_NONE ((cyclic_id_t)0) + +typedef struct cyc_time { + hrtime_t cyt_when; + hrtime_t cyt_interval; +} cyc_time_t; + +typedef struct cyc_handler { + cyc_func_t cyh_func; + void *cyh_arg; + cyc_level_t cyh_level; +} cyc_handler_t; + +extern cyclic_id_t cyclic_add(cyc_handler_t *, cyc_time_t *); +extern void cyclic_remove(cyclic_id_t); +extern int cyclic_reprogram(cyclic_id_t, hrtime_t); +#endif /* illumos */ + #ifdef __cplusplus } #endif |