Skip to content

Commit bb4c19e

Browse files
mitaaxboe
authored andcommitted
block: null_blk: make fault-injection dynamically configurable per device
The null_blk driver has multiple driver-specific fault injection mechanisms. Each fault injection configuration can only be specified by a module parameter and cannot be reconfigured without reloading the driver. Also, each configuration is common to all devices and is initialized every time a new device is added. This change adds the following subdirectories for each null_blk device. /sys/kernel/config/nullb/<disk>/timeout_inject /sys/kernel/config/nullb/<disk>/requeue_inject /sys/kernel/config/nullb/<disk>/init_hctx_fault_inject Each fault injection attribute can be dynamically set per device by a corresponding file in these directories. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Link: https://lore.kernel.org/r/20230327143733.14599-3-akinobu.mita@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 4668c7a commit bb4c19e

File tree

4 files changed

+87
-23
lines changed

4 files changed

+87
-23
lines changed

Documentation/fault-injection/fault-injection.rst

+8
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ Available fault injection capabilities
5252
status code is NVME_SC_INVALID_OPCODE with no retry. The status code and
5353
retry flag can be set via the debugfs.
5454

55+
- Null test block driver fault injection
56+
57+
inject IO timeouts by setting config items under
58+
/sys/kernel/config/nullb/<disk>/timeout_inject,
59+
inject requeue requests by setting config items under
60+
/sys/kernel/config/nullb/<disk>/requeue_inject, and
61+
inject init_hctx() errors by setting config items under
62+
/sys/kernel/config/nullb/<disk>/init_hctx_fault_inject.
5563

5664
Configure fault-injection capabilities behavior
5765
-----------------------------------------------

drivers/block/null_blk/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ config BLK_DEV_NULL_BLK
99

1010
config BLK_DEV_NULL_BLK_FAULT_INJECTION
1111
bool "Support fault injection for Null test block driver"
12-
depends on BLK_DEV_NULL_BLK && FAULT_INJECTION
12+
depends on BLK_DEV_NULL_BLK && FAULT_INJECTION_CONFIGFS

drivers/block/null_blk/main.c

+72-21
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ static void null_free_device_storage(struct nullb_device *dev, bool is_cache);
250250

251251
static inline struct nullb_device *to_nullb_device(struct config_item *item)
252252
{
253-
return item ? container_of(item, struct nullb_device, item) : NULL;
253+
return item ? container_of(to_config_group(item), struct nullb_device, group) : NULL;
254254
}
255255

256256
static inline ssize_t nullb_device_uint_attr_show(unsigned int val, char *page)
@@ -593,8 +593,29 @@ static const struct config_item_type nullb_device_type = {
593593
.ct_owner = THIS_MODULE,
594594
};
595595

596+
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
597+
598+
static void nullb_add_fault_config(struct nullb_device *dev)
599+
{
600+
fault_config_init(&dev->timeout_config, "timeout_inject");
601+
fault_config_init(&dev->requeue_config, "requeue_inject");
602+
fault_config_init(&dev->init_hctx_fault_config, "init_hctx_fault_inject");
603+
604+
configfs_add_default_group(&dev->timeout_config.group, &dev->group);
605+
configfs_add_default_group(&dev->requeue_config.group, &dev->group);
606+
configfs_add_default_group(&dev->init_hctx_fault_config.group, &dev->group);
607+
}
608+
609+
#else
610+
611+
static void nullb_add_fault_config(struct nullb_device *dev)
612+
{
613+
}
614+
615+
#endif
616+
596617
static struct
597-
config_item *nullb_group_make_item(struct config_group *group, const char *name)
618+
config_group *nullb_group_make_group(struct config_group *group, const char *name)
598619
{
599620
struct nullb_device *dev;
600621

@@ -605,9 +626,10 @@ config_item *nullb_group_make_item(struct config_group *group, const char *name)
605626
if (!dev)
606627
return ERR_PTR(-ENOMEM);
607628

608-
config_item_init_type_name(&dev->item, name, &nullb_device_type);
629+
config_group_init_type_name(&dev->group, name, &nullb_device_type);
630+
nullb_add_fault_config(dev);
609631

610-
return &dev->item;
632+
return &dev->group;
611633
}
612634

613635
static void
@@ -645,7 +667,7 @@ static struct configfs_attribute *nullb_group_attrs[] = {
645667
};
646668

647669
static struct configfs_group_operations nullb_group_ops = {
648-
.make_item = nullb_group_make_item,
670+
.make_group = nullb_group_make_group,
649671
.drop_item = nullb_group_drop_item,
650672
};
651673

@@ -676,6 +698,13 @@ static struct nullb_device *null_alloc_dev(void)
676698
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
677699
if (!dev)
678700
return NULL;
701+
702+
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
703+
dev->timeout_config.attr = null_timeout_attr;
704+
dev->requeue_config.attr = null_requeue_attr;
705+
dev->init_hctx_fault_config.attr = null_init_hctx_attr;
706+
#endif
707+
679708
INIT_RADIX_TREE(&dev->data, GFP_ATOMIC);
680709
INIT_RADIX_TREE(&dev->cache, GFP_ATOMIC);
681710
if (badblocks_init(&dev->badblocks, 0)) {
@@ -1515,24 +1544,48 @@ static void null_submit_bio(struct bio *bio)
15151544
null_handle_cmd(alloc_cmd(nq, bio), sector, nr_sectors, bio_op(bio));
15161545
}
15171546

1547+
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
1548+
1549+
static bool should_timeout_request(struct request *rq)
1550+
{
1551+
struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq);
1552+
struct nullb_device *dev = cmd->nq->dev;
1553+
1554+
return should_fail(&dev->timeout_config.attr, 1);
1555+
}
1556+
1557+
static bool should_requeue_request(struct request *rq)
1558+
{
1559+
struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq);
1560+
struct nullb_device *dev = cmd->nq->dev;
1561+
1562+
return should_fail(&dev->requeue_config.attr, 1);
1563+
}
1564+
1565+
static bool should_init_hctx_fail(struct nullb_device *dev)
1566+
{
1567+
return should_fail(&dev->init_hctx_fault_config.attr, 1);
1568+
}
1569+
1570+
#else
1571+
15181572
static bool should_timeout_request(struct request *rq)
15191573
{
1520-
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
1521-
if (g_timeout_str[0])
1522-
return should_fail(&null_timeout_attr, 1);
1523-
#endif
15241574
return false;
15251575
}
15261576

15271577
static bool should_requeue_request(struct request *rq)
15281578
{
1529-
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
1530-
if (g_requeue_str[0])
1531-
return should_fail(&null_requeue_attr, 1);
1532-
#endif
15331579
return false;
15341580
}
15351581

1582+
static bool should_init_hctx_fail(struct nullb_device *dev)
1583+
{
1584+
return false;
1585+
}
1586+
1587+
#endif
1588+
15361589
static void null_map_queues(struct blk_mq_tag_set *set)
15371590
{
15381591
struct nullb *nullb = set->driver_data;
@@ -1729,10 +1782,8 @@ static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *driver_data,
17291782
struct nullb *nullb = hctx->queue->queuedata;
17301783
struct nullb_queue *nq;
17311784

1732-
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
1733-
if (g_init_hctx_str[0] && should_fail(&null_init_hctx_attr, 1))
1785+
if (should_init_hctx_fail(nullb->dev))
17341786
return -EFAULT;
1735-
#endif
17361787

17371788
nq = &nullb->queues[hctx_idx];
17381789
hctx->driver_data = nq;
@@ -2052,9 +2103,6 @@ static int null_add_dev(struct nullb_device *dev)
20522103
if (rv)
20532104
goto out_cleanup_queues;
20542105

2055-
if (!null_setup_fault())
2056-
goto out_cleanup_tags;
2057-
20582106
nullb->tag_set->timeout = 5 * HZ;
20592107
nullb->disk = blk_mq_alloc_disk(nullb->tag_set, nullb);
20602108
if (IS_ERR(nullb->disk)) {
@@ -2116,10 +2164,10 @@ static int null_add_dev(struct nullb_device *dev)
21162164

21172165
null_config_discard(nullb);
21182166

2119-
if (config_item_name(&dev->item)) {
2167+
if (config_item_name(&dev->group.cg_item)) {
21202168
/* Use configfs dir name as the device name */
21212169
snprintf(nullb->disk_name, sizeof(nullb->disk_name),
2122-
"%s", config_item_name(&dev->item));
2170+
"%s", config_item_name(&dev->group.cg_item));
21232171
} else {
21242172
sprintf(nullb->disk_name, "nullb%d", nullb->index);
21252173
}
@@ -2219,6 +2267,9 @@ static int __init null_init(void)
22192267
g_home_node = NUMA_NO_NODE;
22202268
}
22212269

2270+
if (!null_setup_fault())
2271+
return -EINVAL;
2272+
22222273
if (g_queue_mode == NULL_Q_RQ) {
22232274
pr_err("legacy IO path is no longer available\n");
22242275
return -EINVAL;

drivers/block/null_blk/null_blk.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ enum {
6969

7070
struct nullb_device {
7171
struct nullb *nullb;
72-
struct config_item item;
72+
struct config_group group;
73+
#ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
74+
struct fault_config timeout_config;
75+
struct fault_config requeue_config;
76+
struct fault_config init_hctx_fault_config;
77+
#endif
7378
struct radix_tree_root data; /* data stored in the disk */
7479
struct radix_tree_root cache; /* disk cache data */
7580
unsigned long flags; /* device flags */

0 commit comments

Comments
 (0)