Skip to content

Commit e8dcf2d

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: add configurable error injection
Add a new block error injection interface that allows to inject specific status code for specific ranges. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@kernel.org> Reviewed-by: Md Haris Iqbal <haris.iqbal@linux.dev> Link: https://patch.msgid.link/20260611140703.2401204-5-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent d39a63e commit e8dcf2d

10 files changed

Lines changed: 424 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
============================
4+
Configurable Error Injection
5+
============================
6+
7+
Overview
8+
--------
9+
10+
Configurable error injection allows injecting specific block layer status codes
11+
for sector ranges of a block device. Errors can be injected unconditionally, or
12+
with a given probability.
13+
14+
To use configurable error injection, CONFIG_BLK_ERROR_INJECTION must be enabled.
15+
16+
The only interface is the error_injection debugfs file, which is created for
17+
each registered gendisk. Writes to this file are used to create or delete rules
18+
and reads return a list of the current error injection sites.
19+
20+
Options
21+
-------
22+
23+
The following options specify the operations:
24+
25+
=================== =======================================================
26+
add add a new rule
27+
removeall remove all existing rules
28+
=================== =======================================================
29+
30+
The following options specify the details of the rule for the add operation:
31+
32+
=================== =======================================================
33+
op=<string> block layer operation this rule applies to. This uses
34+
the XYZ for each REQ_OP_XYZ operation, e.g. READ, WRITE
35+
or DISCARD. Mandatory.
36+
status=<string> Status to return. This uses XYZ for each BLK_STS_XYZ
37+
code, e.g. IOERR or MEDIUM. Mandatory.
38+
start=<number> First block layer sector the rule applies to.
39+
Optional, defaults to 0.
40+
nr_sectors=<number> Number of sectors this rule applies.
41+
Optional, defaults to the remainder of the device.
42+
chance=<number> Only return a failure with a likelihood of 1/chance.
43+
Optional, defaults to 1 (always).
44+
=================== =======================================================
45+
46+
Example
47+
-------
48+
49+
Return BLK_STS_IOERR for one in 10 reads of sector 0 of /dev/nvme0n1:
50+
51+
$ echo 'add,op=READ,start=0,status=IOERR,chance=10' > /sys/kernel/debug/block/nvme0n1/error_injection
52+
53+
Return BLK_STS_MEDIUM for every write to /dev/nvme0n1:
54+
55+
$ echo 'add,op=WRITE,start=0,status=MEDIUM' > /sys/kernel/debug/block/nvme0n1/error_injection
56+
57+
Remove all rules for /dev/nvme0n1:
58+
59+
$ echo 'removeall' > /sys/kernel/debug/block/nvme0n1/error_injection

Documentation/block/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ Block
2222
switching-sched
2323
writeback_cache_control
2424
ublk
25+
error-injection

block/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@ config BLOCK_HOLDER_DEPRECATED
221221
config BLK_MQ_STACKING
222222
bool
223223

224+
config BLK_ERROR_INJECTION
225+
bool "Enable block layer error injection"
226+
select JUMP_LABEL if HAVE_ARCH_JUMP_LABEL
227+
help
228+
Enable inserting arbitrary block errors through a debugfs interface.
229+
230+
See Documentation/block/error-injection.rst for details.
231+
224232
source "block/Kconfig.iosched"
225233

226234
endif # BLOCK

block/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ obj-y := bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \
1313
genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \
1414
disk-events.o blk-ia-ranges.o early-lookup.o
1515

16+
obj-$(CONFIG_BLK_ERROR_INJECTION) += error-injection.o
1617
obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o
1718
obj-$(CONFIG_BLK_DEV_BSGLIB) += bsg-lib.o
1819
obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o

block/blk-core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "blk-cgroup.h"
5151
#include "blk-throttle.h"
5252
#include "blk-ioprio.h"
53+
#include "error-injection.h"
5354

5455
struct dentry *blk_debugfs_root;
5556

@@ -767,6 +768,9 @@ static void __submit_bio_noacct_mq(struct bio *bio)
767768

768769
void submit_bio_noacct_nocheck(struct bio *bio, bool split)
769770
{
771+
if (unlikely(blk_error_inject(bio)))
772+
return;
773+
770774
blk_cgroup_bio_start(bio);
771775

772776
if (!bio_flagged(bio, BIO_TRACE_COMPLETION)) {

block/blk-sysfs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "blk-wbt.h"
2020
#include "blk-cgroup.h"
2121
#include "blk-throttle.h"
22+
#include "error-injection.h"
2223

2324
struct queue_sysfs_entry {
2425
struct attribute attr;
@@ -933,6 +934,8 @@ static void blk_debugfs_remove(struct gendisk *disk)
933934

934935
blk_debugfs_lock_nomemsave(q);
935936
blk_trace_shutdown(q);
937+
if (IS_ENABLED(CONFIG_BLK_ERROR_INJECTION))
938+
blk_error_injection_exit(disk);
936939
debugfs_remove_recursive(q->debugfs_dir);
937940
q->debugfs_dir = NULL;
938941
q->sched_debugfs_dir = NULL;
@@ -963,6 +966,8 @@ int blk_register_queue(struct gendisk *disk)
963966

964967
memflags = blk_debugfs_lock(q);
965968
q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root);
969+
if (IS_ENABLED(CONFIG_BLK_ERROR_INJECTION))
970+
blk_error_injection_init(disk);
966971
if (queue_is_mq(q))
967972
blk_mq_debugfs_register(q);
968973
blk_debugfs_unlock(q, memflags);

0 commit comments

Comments
 (0)