History

block: add fault injection mechanism for faking request timeouts

Only works for the generic request timer handling. Allows one to sporadically ignore request completions, thus exercising the timeout handling.

Jens Axboe committed 18 years ago

Commit 581d4e21 parent 0a0d96b6 files · +94 −1Browse files

Unified · Split

6 files
  1. block/blk-softirq.c +2 −0
  2. block/blk-timeout.c +59 −0
  3. block/blk.h +12 −0
  4. block/genhd.c +8 −0
  5. include/linux/blkdev.h +1 −0
  6. lib/Kconfig.debug +12 −1
block/blk-softirq.c+2−0
@@ -154,6 +154,8 @@ do_local: · 153 unmodified lines
154 **/154 **/
155void blk_complete_request(struct request *req)155void blk_complete_request(struct request *req)
156{156{
157 if (unlikely(blk_should_fake_timeout(req->q)))
158 return;
157 if (!blk_mark_rq_complete(req))159 if (!blk_mark_rq_complete(req))
158 __blk_complete_request(req);160 __blk_complete_request(req);
159}161}
block/blk-timeout.c+59−0
@@ -4,9 +4,68 @@ · 3 unmodified lines
4#include <linux/kernel.h>4#include <linux/kernel.h>
5#include <linux/module.h>5#include <linux/module.h>
6#include <linux/blkdev.h>6#include <linux/blkdev.h>
7#include <linux/fault-inject.h>
7 8
8#include "blk.h"9#include "blk.h"
9 10
11#ifdef CONFIG_FAIL_IO_TIMEOUT
12
13static DECLARE_FAULT_ATTR(fail_io_timeout);
14
15static int __init setup_fail_io_timeout(char *str)
16{
17 return setup_fault_attr(&fail_io_timeout, str);
18}
19__setup("fail_io_timeout=", setup_fail_io_timeout);
20
21int blk_should_fake_timeout(struct request_queue *q)
22{
23 if (!test_bit(QUEUE_FLAG_FAIL_IO, &q->queue_flags))
24 return 0;
25
26 return should_fail(&fail_io_timeout, 1);
27}
28
29static int __init fail_io_timeout_debugfs(void)
30{
31 return init_fault_attr_dentries(&fail_io_timeout, "fail_io_timeout");
32}
33
34late_initcall(fail_io_timeout_debugfs);
35
36ssize_t part_timeout_show(struct device *dev, struct device_attribute *attr,
37 char *buf)
38{
39 struct gendisk *disk = dev_to_disk(dev);
40 int set = test_bit(QUEUE_FLAG_FAIL_IO, &disk->queue->queue_flags);
41
42 return sprintf(buf, "%d\n", set != 0);
43}
44
45ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr,
46 const char *buf, size_t count)
47{
48 struct gendisk *disk = dev_to_disk(dev);
49 int val;
50
51 if (count) {
52 struct request_queue *q = disk->queue;
53 char *p = (char *) buf;
54
55 val = simple_strtoul(p, &p, 10);
56 spin_lock_irq(q->queue_lock);
57 if (val)
58 queue_flag_set(QUEUE_FLAG_FAIL_IO, q);
59 else
60 queue_flag_clear(QUEUE_FLAG_FAIL_IO, q);
61 spin_unlock_irq(q->queue_lock);
62 }
63
64 return count;
65}
66
67#endif /* CONFIG_FAIL_IO_TIMEOUT */
68
10/*69/*
11 * blk_delete_timer - Delete/cancel timer for a given function.70 * blk_delete_timer - Delete/cancel timer for a given function.
12 * @req: request that we are canceling timer for71 * @req: request that we are canceling timer for
block/blk.h+12−0
@@ -42,6 +42,18 @@ static inline void blk_clear_rq_complete(struct request *rq) · 41 unmodified lines
42 clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);42 clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
43}43}
44 44
45#ifdef CONFIG_FAIL_IO_TIMEOUT
46int blk_should_fake_timeout(struct request_queue *);
47ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
48ssize_t part_timeout_store(struct device *, struct device_attribute *,
49 const char *, size_t);
50#else
51static inline int blk_should_fake_timeout(struct request_queue *q)
52{
53 return 0;
54}
55#endif
56
45struct io_context *current_io_context(gfp_t gfp_flags, int node);57struct io_context *current_io_context(gfp_t gfp_flags, int node);
46 58
47int ll_back_merge_fn(struct request_queue *q, struct request *req,59int ll_back_merge_fn(struct request_queue *q, struct request *req,
block/genhd.c+8−0
@@ -817,6 +817,11 @@ static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); · 816 unmodified lines
817static struct device_attribute dev_attr_fail =817static struct device_attribute dev_attr_fail =
818 __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);818 __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
819#endif819#endif
820#ifdef CONFIG_FAIL_IO_TIMEOUT
821static struct device_attribute dev_attr_fail_timeout =
822 __ATTR(io-timeout-fail, S_IRUGO|S_IWUSR, part_timeout_show,
823 part_timeout_store);
824#endif
820 825
821static struct attribute *disk_attrs[] = {826static struct attribute *disk_attrs[] = {
822 &dev_attr_range.attr,827 &dev_attr_range.attr,
@@ -828,6 +833,9 @@ static struct attribute *disk_attrs[] = { · 5 unmodified lines
828 &dev_attr_stat.attr,833 &dev_attr_stat.attr,
829#ifdef CONFIG_FAIL_MAKE_REQUEST834#ifdef CONFIG_FAIL_MAKE_REQUEST
830 &dev_attr_fail.attr,835 &dev_attr_fail.attr,
836#endif
837#ifdef CONFIG_FAIL_IO_TIMEOUT
838 &dev_attr_fail_timeout.attr,
831#endif839#endif
832 NULL840 NULL
833};841};
include/linux/blkdev.h+1−0
@@ -440,6 +440,7 @@ struct request_queue · 439 unmodified lines
440#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */440#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
441#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */441#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */
442#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */442#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */
443#define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */
443 444
444static inline int queue_is_locked(struct request_queue *q)445static inline int queue_is_locked(struct request_queue *q)
445{446{
lib/Kconfig.debug+12−1
@@ -683,10 +683,21 @@ config FAIL_PAGE_ALLOC · 682 unmodified lines
683 683
684config FAIL_MAKE_REQUEST684config FAIL_MAKE_REQUEST
685 bool "Fault-injection capability for disk IO"685 bool "Fault-injection capability for disk IO"
686 depends on FAULT_INJECTION686 depends on FAULT_INJECTION && BLOCK
687 help687 help
688 Provide fault-injection capability for disk IO.688 Provide fault-injection capability for disk IO.
689 689
690config FAIL_IO_TIMEOUT
691 bool "Faul-injection capability for faking disk interrupts"
692 depends on FAULT_INJECTION && BLOCK
693 help
694 Provide fault-injection capability on end IO handling. This
695 will make the block layer "forget" an interrupt as configured,
696 thus exercising the error handling.
697
698 Only works with drivers that use the generic timeout handling,
699 for others it wont do anything.
700
690config FAULT_INJECTION_DEBUG_FS701config FAULT_INJECTION_DEBUG_FS
691 bool "Debugfs entries for fault-injection capabilities"702 bool "Debugfs entries for fault-injection capabilities"
692 depends on FAULT_INJECTION && SYSFS && DEBUG_FS703 depends on FAULT_INJECTION && SYSFS && DEBUG_FS