Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 110537
b: refs/heads/master
c: 581d4e2
h: refs/heads/master
i:
  110535: 3923a2a
v: v3
  • Loading branch information
Jens Axboe committed Oct 9, 2008
1 parent b793917 commit 212dbea
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0a0d96b03a1f3bfd6bc3ea08008699e8e59fccd9
refs/heads/master: 581d4e28d9195aa8b2231383dbabc288988d615e
2 changes: 2 additions & 0 deletions trunk/block/blk-softirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ void __blk_complete_request(struct request *req)
**/
void blk_complete_request(struct request *req)
{
if (unlikely(blk_should_fake_timeout(req->q)))
return;
if (!blk_mark_rq_complete(req))
__blk_complete_request(req);
}
Expand Down
59 changes: 59 additions & 0 deletions trunk/block/blk-timeout.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,68 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/fault-inject.h>

#include "blk.h"

#ifdef CONFIG_FAIL_IO_TIMEOUT

static DECLARE_FAULT_ATTR(fail_io_timeout);

static int __init setup_fail_io_timeout(char *str)
{
return setup_fault_attr(&fail_io_timeout, str);
}
__setup("fail_io_timeout=", setup_fail_io_timeout);

int blk_should_fake_timeout(struct request_queue *q)
{
if (!test_bit(QUEUE_FLAG_FAIL_IO, &q->queue_flags))
return 0;

return should_fail(&fail_io_timeout, 1);
}

static int __init fail_io_timeout_debugfs(void)
{
return init_fault_attr_dentries(&fail_io_timeout, "fail_io_timeout");
}

late_initcall(fail_io_timeout_debugfs);

ssize_t part_timeout_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct gendisk *disk = dev_to_disk(dev);
int set = test_bit(QUEUE_FLAG_FAIL_IO, &disk->queue->queue_flags);

return sprintf(buf, "%d\n", set != 0);
}

ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct gendisk *disk = dev_to_disk(dev);
int val;

if (count) {
struct request_queue *q = disk->queue;
char *p = (char *) buf;

val = simple_strtoul(p, &p, 10);
spin_lock_irq(q->queue_lock);
if (val)
queue_flag_set(QUEUE_FLAG_FAIL_IO, q);
else
queue_flag_clear(QUEUE_FLAG_FAIL_IO, q);
spin_unlock_irq(q->queue_lock);
}

return count;
}

#endif /* CONFIG_FAIL_IO_TIMEOUT */

/*
* blk_delete_timer - Delete/cancel timer for a given function.
* @req: request that we are canceling timer for
Expand Down
12 changes: 12 additions & 0 deletions trunk/block/blk.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ static inline void blk_clear_rq_complete(struct request *rq)
clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
}

#ifdef CONFIG_FAIL_IO_TIMEOUT
int blk_should_fake_timeout(struct request_queue *);
ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
ssize_t part_timeout_store(struct device *, struct device_attribute *,
const char *, size_t);
#else
static inline int blk_should_fake_timeout(struct request_queue *q)
{
return 0;
}
#endif

struct io_context *current_io_context(gfp_t gfp_flags, int node);

int ll_back_merge_fn(struct request_queue *q, struct request *req,
Expand Down
8 changes: 8 additions & 0 deletions trunk/block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,11 @@ static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
static struct device_attribute dev_attr_fail =
__ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
#endif
#ifdef CONFIG_FAIL_IO_TIMEOUT
static struct device_attribute dev_attr_fail_timeout =
__ATTR(io-timeout-fail, S_IRUGO|S_IWUSR, part_timeout_show,
part_timeout_store);
#endif

static struct attribute *disk_attrs[] = {
&dev_attr_range.attr,
Expand All @@ -828,6 +833,9 @@ static struct attribute *disk_attrs[] = {
&dev_attr_stat.attr,
#ifdef CONFIG_FAIL_MAKE_REQUEST
&dev_attr_fail.attr,
#endif
#ifdef CONFIG_FAIL_IO_TIMEOUT
&dev_attr_fail_timeout.attr,
#endif
NULL
};
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ struct request_queue
#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */
#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */
#define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */

static inline int queue_is_locked(struct request_queue *q)
{
Expand Down
13 changes: 12 additions & 1 deletion trunk/lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -683,10 +683,21 @@ config FAIL_PAGE_ALLOC

config FAIL_MAKE_REQUEST
bool "Fault-injection capability for disk IO"
depends on FAULT_INJECTION
depends on FAULT_INJECTION && BLOCK
help
Provide fault-injection capability for disk IO.

config FAIL_IO_TIMEOUT
bool "Faul-injection capability for faking disk interrupts"
depends on FAULT_INJECTION && BLOCK
help
Provide fault-injection capability on end IO handling. This
will make the block layer "forget" an interrupt as configured,
thus exercising the error handling.

Only works with drivers that use the generic timeout handling,
for others it wont do anything.

config FAULT_INJECTION_DEBUG_FS
bool "Debugfs entries for fault-injection capabilities"
depends on FAULT_INJECTION && SYSFS && DEBUG_FS
Expand Down

0 comments on commit 212dbea

Please sign in to comment.