diff mbox series

[V2,1/1] null_blk: allow user to set QUEUE_FLAG_NOWAIT

Message ID 20230418042420.93629-2-kch@nvidia.com (mailing list archive)
State New, archived
Headers show
Series null_blk: allow user to set QUEUE_FLAG_NOWAIT | expand

Commit Message

Chaitanya Kulkarni April 18, 2023, 4:24 a.m. UTC
One of the default flags used to define QUEUE_FLAG_MQ_DEFAULT is
QUEUE_FLAG_NOWAIT. For null_blk QUEUE_FLAG_NOWAIT is set by default when
it is used with NULL_Q_MQ mode as a part of following call chain see
blk_mq_init_allocated_queue() :-

null_add_dev()
if (dev->queue_mode == NULL_Q_MQ) {
        blk_mq_alloc_disk()
          __blk_mq_alloc_disk()
	    blk_mq_init_queue_data()
              blk_mq_init_allocated_queue()
                q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;
}

But it is not set when null_blk is loaded with NULL_Q_BIO mode in following
code path like other bio drivers do e.g. nvme-multipath :-

if (dev->queue_mode == NULL_Q_BIO) {
        nullb->disk = blk_alloc_disk(nullb->dev->home_node);
        	blk_alloc_disk()
        	  blk_alloc_queue()
        	  __alloc_disk_nodw()
}

Add a new module parameter nowait and respective configfs attr that will
set or clear the QUEUE_FLAG_NOWAIT based on a value set by user in
null_add_dev() when queue_mode is set to NULL_Q_BIO, by default keep it
disabled to retain the original behaviour for the NULL_Q_BIO mode.

Only when queue_mode is NULL_Q_BIO, depending on nowait value use
GFP_NOWAIT or GFP_NOIO for the alloction in the null_alloc_page() for
alloc_pages() and in null_insert_page() for radix_tree_preload().

Observed performance difference with this patch for fio iouring with
configfs and non configfs null_blk when queue_mode=NULL_Q_BIO:-

* Configfs non-membacked mode:-

QUEUE_FLAG_NOWAIT disabled :-
---------------------------------------------
configfs-qmode-0-nowait-0-fio-1.log:  read: IOPS=1299k, BW=5076MiB/s
configfs-qmode-0-nowait-0-fio-2.log:  read: IOPS=1250k, BW=4884MiB/s
configfs-qmode-0-nowait-0-fio-3.log:  read: IOPS=1251k, BW=4888MiB/s


QUEUE_FLAG_NOWAIT enabled :-
---------------------------------------------
configfs-qmode-0-nowait-1-fio-1.log:  read: IOPS=5469k, BW=20.9GiB/s
configfs-qmode-0-nowait-1-fio-2.log:  read: IOPS=5525k, BW=21.1GiB/s
configfs-qmode-0-nowait-1-fio-3.log:  read: IOPS=5561k, BW=21.2GiB/s

* Non Configfs non-membacked mode:-

QUEUE_FLAG_NOWAIT disabled :-
---------------------------------------------
qmode-0-nowait-0-fio-1.log:  read: IOPS=1261k, BW=4924MiB/s
qmode-0-nowait-0-fio-2.log:  read: IOPS=1295k, BW=5060MiB/s
qmode-0-nowait-0-fio-3.log:  read: IOPS=1280k, BW=4999MiB/s

QUEUE_FLAG_NOWAIT enabled :-
---------------------------------------------
qmode-0-nowait-1-fio-1.log:  read: IOPS=5521k, BW=21.1GiB/s
qmode-0-nowait-1-fio-2.log:  read: IOPS=5524k, BW=21.1GiB/s
qmode-0-nowait-1-fio-3.log:  read: IOPS=5541k, BW=21.1GiB/s

Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com>
---
 drivers/block/null_blk/main.c     | 33 ++++++++++++++++++++++++++-----
 drivers/block/null_blk/null_blk.h |  1 +
 2 files changed, 29 insertions(+), 5 deletions(-)

Comments

Pankaj Raghav April 18, 2023, 11:45 a.m. UTC | #1
Ah, I think I replied to your v1 patches but the same comments are also
applicable here.
diff mbox series

Patch

diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index b195b8b9fe32..afffe48f5cb1 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -77,6 +77,10 @@  enum {
 	NULL_IRQ_TIMER		= 2,
 };
 
+static bool g_nowait = false;
+module_param_named(nowait, g_nowait, bool, 0444);
+MODULE_PARM_DESC(virt_boundary, "Set QUEUE_FLAG_NOWAIT for qmode=BIO. Default: False");
+
 static bool g_virt_boundary = false;
 module_param_named(virt_boundary, g_virt_boundary, bool, 0444);
 MODULE_PARM_DESC(virt_boundary, "Require a virtual boundary for the device. Default: False");
@@ -413,6 +417,7 @@  NULLB_DEVICE_ATTR(irqmode, uint, NULL);
 NULLB_DEVICE_ATTR(hw_queue_depth, uint, NULL);
 NULLB_DEVICE_ATTR(index, uint, NULL);
 NULLB_DEVICE_ATTR(blocking, bool, NULL);
+NULLB_DEVICE_ATTR(nowait, bool, NULL);
 NULLB_DEVICE_ATTR(use_per_node_hctx, bool, NULL);
 NULLB_DEVICE_ATTR(memory_backed, bool, NULL);
 NULLB_DEVICE_ATTR(discard, bool, NULL);
@@ -554,6 +559,7 @@  static struct configfs_attribute *nullb_device_attrs[] = {
 	&nullb_device_attr_hw_queue_depth,
 	&nullb_device_attr_index,
 	&nullb_device_attr_blocking,
+	&nullb_device_attr_nowait,
 	&nullb_device_attr_use_per_node_hctx,
 	&nullb_device_attr_power,
 	&nullb_device_attr_memory_backed,
@@ -650,7 +656,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,
-			"badblocks,blocking,blocksize,cache_size,"
+			"badblocks,blocking,nowait,blocksize,cache_size,"
 			"completion_nsec,discard,home_node,hw_queue_depth,"
 			"irqmode,max_sectors,mbps,memory_backed,no_sched,"
 			"poll_queues,power,queue_mode,shared_tag_bitmap,size,"
@@ -725,6 +731,7 @@  static struct nullb_device *null_alloc_dev(void)
 	dev->irqmode = g_irqmode;
 	dev->hw_queue_depth = g_hw_queue_depth;
 	dev->blocking = g_blocking;
+	dev->nowait = g_nowait;
 	dev->memory_backed = g_memory_backed;
 	dev->discard = g_discard;
 	dev->cache_size = g_cache_size;
@@ -859,7 +866,7 @@  static void null_complete_rq(struct request *rq)
 	end_cmd(blk_mq_rq_to_pdu(rq));
 }
 
-static struct nullb_page *null_alloc_page(void)
+static struct nullb_page *null_alloc_page(gfp_t gfp)
 {
 	struct nullb_page *t_page;
 
@@ -867,7 +874,7 @@  static struct nullb_page *null_alloc_page(void)
 	if (!t_page)
 		return NULL;
 
-	t_page->page = alloc_pages(GFP_NOIO, 0);
+	t_page->page = alloc_pages(gfp, 0);
 	if (!t_page->page) {
 		kfree(t_page);
 		return NULL;
@@ -1005,6 +1012,12 @@  static struct nullb_page *null_insert_page(struct nullb *nullb,
 {
 	u64 idx;
 	struct nullb_page *t_page;
+	gfp_t gfp;
+
+	if (nullb->dev->nowait && nullb->dev->queue_mode == NULL_Q_BIO)
+		gfp = GFP_NOWAIT;
+	else
+		gfp = GFP_NOIO;
 
 	t_page = null_lookup_page(nullb, sector, true, ignore_cache);
 	if (t_page)
@@ -1012,11 +1025,11 @@  static struct nullb_page *null_insert_page(struct nullb *nullb,
 
 	spin_unlock_irq(&nullb->lock);
 
-	t_page = null_alloc_page();
+	t_page = null_alloc_page(gfp);
 	if (!t_page)
 		goto out_lock;
 
-	if (radix_tree_preload(GFP_NOIO))
+	if (radix_tree_preload(gfp))
 		goto out_freepage;
 
 	spin_lock_irq(&nullb->lock);
@@ -2005,6 +2018,11 @@  static int null_validate_conf(struct nullb_device *dev)
 		return -EINVAL;
 	}
 
+	if (dev->nowait && dev->queue_mode != NULL_Q_BIO) {
+		pr_err("nowait is only allowed with queue_mode=BIO\n");
+		return -EINVAL;
+	}
+
 	dev->blocksize = round_down(dev->blocksize, 512);
 	dev->blocksize = clamp_t(unsigned int, dev->blocksize, 512, 4096);
 
@@ -2146,6 +2164,11 @@  static int null_add_dev(struct nullb_device *dev)
 	blk_queue_flag_set(QUEUE_FLAG_NONROT, nullb->q);
 	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, nullb->q);
 
+	if (dev->nowait)
+		blk_queue_flag_set(QUEUE_FLAG_NOWAIT, nullb->q);
+	else
+		blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, nullb->q);
+
 	mutex_lock(&lock);
 	rv = ida_simple_get(&nullb_indexes, 0, 0, GFP_KERNEL);
 	if (rv < 0) {
diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h
index 929f659dd255..c52aa018657b 100644
--- a/drivers/block/null_blk/null_blk.h
+++ b/drivers/block/null_blk/null_blk.h
@@ -112,6 +112,7 @@  struct nullb_device {
 	unsigned int index; /* index of the disk, only valid with a disk */
 	unsigned int mbps; /* Bandwidth throttle cap (in MB/s) */
 	bool blocking; /* blocking blk-mq device */
+	bool nowait; /* to set QUEUE_FLAG_NOWAIT on device queue */
 	bool use_per_node_hctx; /* use per-node allocation for hardware context */
 	bool power; /* power on/off the device */
 	bool memory_backed; /* if data is stored in memory */