@@ -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);
}
@@ -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)
@@ -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;
}
@@ -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 */