diff mbox series

[RFC] blk-mq: set the default elevator type to none if nr_hw_queues > 1

Message ID 20190917125631.11161-1-xiubli@redhat.com (mailing list archive)
State New, archived
Headers show
Series [RFC] blk-mq: set the default elevator type to none if nr_hw_queues > 1 | expand

Commit Message

Xiubo Li Sept. 17, 2019, 12:56 p.m. UTC
From: Xiubo Li <xiubli@redhat.com>

For the nbd device, firstly it will be initialized as single hardware
queue, and then in add_disk() the elevator will set to mq-deadline.

But if there more than one socket connections, then the hardware
queus will be increased and will equal to the socket connection
numners. In this case shouldn't we set it back to none as default ?

If the user space daemon has changed the elevator type or the drivers
has specified the elevator feature, we will set it back anyway.

Signed-off-by: Xiubo Li <xiubli@redhat.com>
---
 block/blk-mq.c         | 19 +++++++++++++++++--
 block/blk.h            |  1 +
 block/elevator.c       |  6 ++++--
 include/linux/blkdev.h |  2 ++
 4 files changed, 24 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 8cdc747d5c4d..1be9e416bfd8 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3242,7 +3242,7 @@  static void blk_mq_elv_switch_back(struct list_head *head,
 		struct request_queue *q)
 {
 	struct blk_mq_qe_pair *qe;
-	struct elevator_type *t = NULL;
+	struct elevator_type *t = NULL, *e;
 
 	list_for_each_entry(qe, head, node)
 		if (qe->q == q) {
@@ -3257,7 +3257,22 @@  static void blk_mq_elv_switch_back(struct list_head *head,
 	kfree(qe);
 
 	mutex_lock(&q->sysfs_lock);
-	elevator_switch_mq(q, t);
+	/*
+	 * If the elevator type has been touched by user space daemon
+	 * we will switch it back to the previous one anyway.
+	 *
+	 * Or will set it as default depending on the new hw queue number,
+	 * if will keep the elv type to none then we need to put the moudle.
+	 */
+	if (q->elv_user_touched || q->required_elevator_features) {
+		elevator_switch_mq(q, t);
+	} else {
+		e = elevator_get_default(q);
+		if (e)
+			elevator_switch_mq(q, e);
+		else
+			module_put(t->elevator_owner);
+	}
 	mutex_unlock(&q->sysfs_lock);
 }
 
diff --git a/block/blk.h b/block/blk.h
index ed347f7a97b1..43021b87b953 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -190,6 +190,7 @@  int elevator_switch_mq(struct request_queue *q,
 void __elevator_exit(struct request_queue *, struct elevator_queue *);
 int elv_register_queue(struct request_queue *q, bool uevent);
 void elv_unregister_queue(struct request_queue *q);
+struct elevator_type *elevator_get_default(struct request_queue *q);
 
 static inline void elevator_exit(struct request_queue *q,
 		struct elevator_queue *e)
diff --git a/block/elevator.c b/block/elevator.c
index bba10e83478a..14bfcb1b19b3 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -654,7 +654,7 @@  static inline bool elv_support_iosched(struct request_queue *q)
  * For single queue devices, default to using mq-deadline. If we have multiple
  * queues or mq-deadline is not available, default to "none".
  */
-static struct elevator_type *elevator_get_default(struct request_queue *q)
+struct elevator_type *elevator_get_default(struct request_queue *q)
 {
 	if (q->nr_hw_queues != 1)
 		return NULL;
@@ -796,8 +796,10 @@  ssize_t elv_iosched_store(struct request_queue *q, const char *name,
 		return count;
 
 	ret = __elevator_change(q, name);
-	if (!ret)
+	if (!ret) {
+		q->elv_user_touched = true;
 		return count;
+	}
 
 	return ret;
 }
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b196124e3240..a03b8ea5916d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -587,6 +587,8 @@  struct request_queue {
 
 #define BLK_MAX_WRITE_HINTS	5
 	u64			write_hints[BLK_MAX_WRITE_HINTS];
+
+	bool			elv_user_touched;
 };
 
 #define QUEUE_FLAG_STOPPED	0	/* queue is stopped */