aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2006-12-08 05:39:46 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:29:02 -0500
commitc17bb4951752d3e0f49cd1ea9d2e868422f9e0d6 (patch)
treedcd23ef706ba09edae462528dc11a507b1d17af6
parent933e312e73f8fc39652bd4d216a5393cc3a014b9 (diff)
[PATCH] fault-injection capability for disk IO
This patch provides fault-injection capability for disk IO. Boot option: fail_make_request=<probability>,<interval>,<space>,<times> <interval> -- specifies the interval of failures. <probability> -- specifies how often it should fail in percent. <space> -- specifies the size of free space where disk IO can be issued safely in bytes. <times> -- specifies how many times failures may happen at most. Debugfs: /debug/fail_make_request/interval /debug/fail_make_request/probability /debug/fail_make_request/specifies /debug/fail_make_request/times Example: fail_make_request=10,100,0,-1 echo 1 > /sys/blocks/hda/hda1/make-it-fail generic_make_request() on /dev/hda1 fails once per 10 times. Cc: Jens Axboe <axboe@suse.de> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--block/genhd.c31
-rw-r--r--block/ll_rw_blk.c40
-rw-r--r--fs/partitions/check.c27
-rw-r--r--include/linux/genhd.h4
-rw-r--r--lib/Kconfig.debug7
5 files changed, 109 insertions, 0 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 653919d50cd4..457fdac4c17d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -417,6 +417,34 @@ static struct disk_attribute disk_attr_stat = {
417 .show = disk_stats_read 417 .show = disk_stats_read
418}; 418};
419 419
420#ifdef CONFIG_FAIL_MAKE_REQUEST
421
422static ssize_t disk_fail_store(struct gendisk * disk,
423 const char *buf, size_t count)
424{
425 int i;
426
427 if (count > 0 && sscanf(buf, "%d", &i) > 0) {
428 if (i == 0)
429 disk->flags &= ~GENHD_FL_FAIL;
430 else
431 disk->flags |= GENHD_FL_FAIL;
432 }
433
434 return count;
435}
436static ssize_t disk_fail_read(struct gendisk * disk, char *page)
437{
438 return sprintf(page, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
439}
440static struct disk_attribute disk_attr_fail = {
441 .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
442 .store = disk_fail_store,
443 .show = disk_fail_read
444};
445
446#endif
447
420static struct attribute * default_attrs[] = { 448static struct attribute * default_attrs[] = {
421 &disk_attr_uevent.attr, 449 &disk_attr_uevent.attr,
422 &disk_attr_dev.attr, 450 &disk_attr_dev.attr,
@@ -424,6 +452,9 @@ static struct attribute * default_attrs[] = {
424 &disk_attr_removable.attr, 452 &disk_attr_removable.attr,
425 &disk_attr_size.attr, 453 &disk_attr_size.attr,
426 &disk_attr_stat.attr, 454 &disk_attr_stat.attr,
455#ifdef CONFIG_FAIL_MAKE_REQUEST
456 &disk_attr_fail.attr,
457#endif
427 NULL, 458 NULL,
428}; 459};
429 460
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 31512cd9f3ad..4f83fd922377 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -28,6 +28,7 @@
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/cpu.h> 29#include <linux/cpu.h>
30#include <linux/blktrace_api.h> 30#include <linux/blktrace_api.h>
31#include <linux/fault-inject.h>
31 32
32/* 33/*
33 * for max sense size 34 * for max sense size
@@ -3056,6 +3057,42 @@ static void handle_bad_sector(struct bio *bio)
3056 set_bit(BIO_EOF, &bio->bi_flags); 3057 set_bit(BIO_EOF, &bio->bi_flags);
3057} 3058}
3058 3059
3060#ifdef CONFIG_FAIL_MAKE_REQUEST
3061
3062static DECLARE_FAULT_ATTR(fail_make_request);
3063
3064static int __init setup_fail_make_request(char *str)
3065{
3066 return setup_fault_attr(&fail_make_request, str);
3067}
3068__setup("fail_make_request=", setup_fail_make_request);
3069
3070static int should_fail_request(struct bio *bio)
3071{
3072 if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) ||
3073 (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail))
3074 return should_fail(&fail_make_request, bio->bi_size);
3075
3076 return 0;
3077}
3078
3079static int __init fail_make_request_debugfs(void)
3080{
3081 return init_fault_attr_dentries(&fail_make_request,
3082 "fail_make_request");
3083}
3084
3085late_initcall(fail_make_request_debugfs);
3086
3087#else /* CONFIG_FAIL_MAKE_REQUEST */
3088
3089static inline int should_fail_request(struct bio *bio)
3090{
3091 return 0;
3092}
3093
3094#endif /* CONFIG_FAIL_MAKE_REQUEST */
3095
3059/** 3096/**
3060 * generic_make_request: hand a buffer to its device driver for I/O 3097 * generic_make_request: hand a buffer to its device driver for I/O
3061 * @bio: The bio describing the location in memory and on the device. 3098 * @bio: The bio describing the location in memory and on the device.
@@ -3141,6 +3178,9 @@ end_io:
3141 if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) 3178 if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
3142 goto end_io; 3179 goto end_io;
3143 3180
3181 if (should_fail_request(bio))
3182 goto end_io;
3183
3144 /* 3184 /*
3145 * If this device has partitions, remap block n 3185 * If this device has partitions, remap block n
3146 * of partition p to block n+start(p) of the disk. 3186 * of partition p to block n+start(p) of the disk.
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 1901137f4eca..3d73d94d93a7 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -276,12 +276,39 @@ static struct part_attribute part_attr_stat = {
276 .show = part_stat_read 276 .show = part_stat_read
277}; 277};
278 278
279#ifdef CONFIG_FAIL_MAKE_REQUEST
280
281static ssize_t part_fail_store(struct hd_struct * p,
282 const char *buf, size_t count)
283{
284 int i;
285
286 if (count > 0 && sscanf(buf, "%d", &i) > 0)
287 p->make_it_fail = (i == 0) ? 0 : 1;
288
289 return count;
290}
291static ssize_t part_fail_read(struct hd_struct * p, char *page)
292{
293 return sprintf(page, "%d\n", p->make_it_fail);
294}
295static struct part_attribute part_attr_fail = {
296 .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
297 .store = part_fail_store,
298 .show = part_fail_read
299};
300
301#endif
302
279static struct attribute * default_attrs[] = { 303static struct attribute * default_attrs[] = {
280 &part_attr_uevent.attr, 304 &part_attr_uevent.attr,
281 &part_attr_dev.attr, 305 &part_attr_dev.attr,
282 &part_attr_start.attr, 306 &part_attr_start.attr,
283 &part_attr_size.attr, 307 &part_attr_size.attr,
284 &part_attr_stat.attr, 308 &part_attr_stat.attr,
309#ifdef CONFIG_FAIL_MAKE_REQUEST
310 &part_attr_fail.attr,
311#endif
285 NULL, 312 NULL,
286}; 313};
287 314
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 41f276fdd185..0a022b2f63fc 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -83,6 +83,9 @@ struct hd_struct {
83 struct kobject *holder_dir; 83 struct kobject *holder_dir;
84 unsigned ios[2], sectors[2]; /* READs and WRITEs */ 84 unsigned ios[2], sectors[2]; /* READs and WRITEs */
85 int policy, partno; 85 int policy, partno;
86#ifdef CONFIG_FAIL_MAKE_REQUEST
87 int make_it_fail;
88#endif
86}; 89};
87 90
88#define GENHD_FL_REMOVABLE 1 91#define GENHD_FL_REMOVABLE 1
@@ -90,6 +93,7 @@ struct hd_struct {
90#define GENHD_FL_CD 8 93#define GENHD_FL_CD 8
91#define GENHD_FL_UP 16 94#define GENHD_FL_UP 16
92#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 95#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
96#define GENHD_FL_FAIL 64
93 97
94struct disk_stats { 98struct disk_stats {
95 unsigned long sectors[2]; /* READs and WRITEs */ 99 unsigned long sectors[2]; /* READs and WRITEs */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index c66b7b400c9f..336241bf0ced 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -431,6 +431,13 @@ config FAIL_PAGE_ALLOC
431 help 431 help
432 This option provides fault-injection capabilitiy for alloc_pages(). 432 This option provides fault-injection capabilitiy for alloc_pages().
433 433
434config FAIL_MAKE_REQUEST
435 bool "Fault-injection capabilitiy for disk IO"
436 depends on DEBUG_KERNEL
437 select FAULT_INJECTION
438 help
439 This option provides fault-injection capabilitiy to disk IO.
440
434config FAULT_INJECTION_DEBUG_FS 441config FAULT_INJECTION_DEBUG_FS
435 bool "Debugfs entries for fault-injection capabilities" 442 bool "Debugfs entries for fault-injection capabilities"
436 depends on FAULT_INJECTION && SYSFS 443 depends on FAULT_INJECTION && SYSFS