null_blk: Allow controlling max_hw_sectors limit
authorDamien Le Moal <damien.lemoal@wdc.com>
Fri, 20 Nov 2020 01:55:18 +0000 (10:55 +0900)
committerJens Axboe <axboe@kernel.dk>
Tue, 8 Dec 2020 00:36:04 +0000 (17:36 -0700)
Add the module option and configfs attribute max_sectors to allow
configuring the maximum size of a command issued to a null_blk device.
This allows exercising the block layer BIO splitting with different
limits than the default BLK_SAFE_MAX_SECTORS. This is also useful for
testing the zone append write path of file systems as the max_hw_sectors
limit value is also used for the max_zone_append_sectors limit.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/null_blk.h
drivers/block/null_blk_main.c

index 63000ae..83504f3 100644 (file)
@@ -85,6 +85,7 @@ struct nullb_device {
        unsigned int home_node; /* home node for the device */
        unsigned int queue_mode; /* block interface */
        unsigned int blocksize; /* block size */
+       unsigned int max_sectors; /* Max sectors per command */
        unsigned int irqmode; /* IRQ completion handler */
        unsigned int hw_queue_depth; /* queue depth */
        unsigned int index; /* index of the disk, only valid with a disk */
index b758b93..5357c3a 100644 (file)
@@ -152,6 +152,10 @@ static int g_bs = 512;
 module_param_named(bs, g_bs, int, 0444);
 MODULE_PARM_DESC(bs, "Block size (in bytes)");
 
+static int g_max_sectors;
+module_param_named(max_sectors, g_max_sectors, int, 0444);
+MODULE_PARM_DESC(max_sectors, "Maximum size of a command (in 512B sectors)");
+
 static unsigned int nr_devices = 1;
 module_param(nr_devices, uint, 0444);
 MODULE_PARM_DESC(nr_devices, "Number of devices to register");
@@ -346,6 +350,7 @@ NULLB_DEVICE_ATTR(submit_queues, uint, nullb_apply_submit_queues);
 NULLB_DEVICE_ATTR(home_node, uint, NULL);
 NULLB_DEVICE_ATTR(queue_mode, uint, NULL);
 NULLB_DEVICE_ATTR(blocksize, uint, NULL);
+NULLB_DEVICE_ATTR(max_sectors, uint, NULL);
 NULLB_DEVICE_ATTR(irqmode, uint, NULL);
 NULLB_DEVICE_ATTR(hw_queue_depth, uint, NULL);
 NULLB_DEVICE_ATTR(index, uint, NULL);
@@ -463,6 +468,7 @@ static struct configfs_attribute *nullb_device_attrs[] = {
        &nullb_device_attr_home_node,
        &nullb_device_attr_queue_mode,
        &nullb_device_attr_blocksize,
+       &nullb_device_attr_max_sectors,
        &nullb_device_attr_irqmode,
        &nullb_device_attr_hw_queue_depth,
        &nullb_device_attr_index,
@@ -533,7 +539,7 @@ nullb_group_drop_item(struct config_group *group, struct config_item *item)
 static ssize_t memb_group_features_show(struct config_item *item, char *page)
 {
        return snprintf(page, PAGE_SIZE,
-                       "memory_backed,discard,bandwidth,cache,badblocks,zoned,zone_size,zone_capacity,zone_nr_conv,zone_max_open,zone_max_active\n");
+                       "memory_backed,discard,bandwidth,cache,badblocks,zoned,zone_size,zone_capacity,zone_nr_conv,zone_max_open,zone_max_active,blocksize,max_sectors\n");
 }
 
 CONFIGFS_ATTR_RO(memb_group_, features);
@@ -588,6 +594,7 @@ static struct nullb_device *null_alloc_dev(void)
        dev->home_node = g_home_node;
        dev->queue_mode = g_queue_mode;
        dev->blocksize = g_bs;
+       dev->max_sectors = g_max_sectors;
        dev->irqmode = g_irqmode;
        dev->hw_queue_depth = g_hw_queue_depth;
        dev->blocking = g_blocking;
@@ -1867,6 +1874,11 @@ static int null_add_dev(struct nullb_device *dev)
 
        blk_queue_logical_block_size(nullb->q, dev->blocksize);
        blk_queue_physical_block_size(nullb->q, dev->blocksize);
+       if (!dev->max_sectors)
+               dev->max_sectors = queue_max_hw_sectors(nullb->q);
+       dev->max_sectors = min_t(unsigned int, dev->max_sectors,
+                                BLK_DEF_MAX_SECTORS);
+       blk_queue_max_hw_sectors(nullb->q, dev->max_sectors);
 
        null_config_discard(nullb);
 
@@ -1910,6 +1922,12 @@ static int __init null_init(void)
                g_bs = PAGE_SIZE;
        }
 
+       if (g_max_sectors > BLK_DEF_MAX_SECTORS) {
+               pr_warn("invalid max sectors\n");
+               pr_warn("defaults max sectors to %u\n", BLK_DEF_MAX_SECTORS);
+               g_max_sectors = BLK_DEF_MAX_SECTORS;
+       }
+
        if (g_home_node != NUMA_NO_NODE && g_home_node >= nr_online_nodes) {
                pr_err("invalid home_node value\n");
                g_home_node = NUMA_NO_NODE;