Skip to content

Commit 2a35d21

Browse files
axboegregkh
authored andcommitted
elevator: lookup mq vs non-mq elevators
[ Upstream commit 2527d99 ] If an IO scheduler is selected via elevator= and it doesn't match the driver in question wrt blk-mq support, then we fail to boot. The elevator= parameter is deprecated and only supported for non-mq devices. Augment the elevator lookup API so that we pass in if we're looking for an mq capable scheduler or not, so that we only ever return a valid type for the queue in question. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=196695 Reviewed-by: Omar Sandoval <[email protected]> Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 5d01e06 commit 2a35d21

File tree

1 file changed

+21
-23
lines changed

1 file changed

+21
-23
lines changed

block/elevator.c

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,15 @@ bool elv_bio_merge_ok(struct request *rq, struct bio *bio)
8383
}
8484
EXPORT_SYMBOL(elv_bio_merge_ok);
8585

86-
static struct elevator_type *elevator_find(const char *name)
86+
/*
87+
* Return scheduler with name 'name' and with matching 'mq capability
88+
*/
89+
static struct elevator_type *elevator_find(const char *name, bool mq)
8790
{
8891
struct elevator_type *e;
8992

9093
list_for_each_entry(e, &elv_list, list) {
91-
if (!strcmp(e->elevator_name, name))
94+
if (!strcmp(e->elevator_name, name) && (mq == e->uses_mq))
9295
return e;
9396
}
9497

@@ -100,25 +103,25 @@ static void elevator_put(struct elevator_type *e)
100103
module_put(e->elevator_owner);
101104
}
102105

103-
static struct elevator_type *elevator_get(const char *name, bool try_loading)
106+
static struct elevator_type *elevator_get(struct request_queue *q,
107+
const char *name, bool try_loading)
104108
{
105109
struct elevator_type *e;
106110

107111
spin_lock(&elv_list_lock);
108112

109-
e = elevator_find(name);
113+
e = elevator_find(name, q->mq_ops != NULL);
110114
if (!e && try_loading) {
111115
spin_unlock(&elv_list_lock);
112116
request_module("%s-iosched", name);
113117
spin_lock(&elv_list_lock);
114-
e = elevator_find(name);
118+
e = elevator_find(name, q->mq_ops != NULL);
115119
}
116120

117121
if (e && !try_module_get(e->elevator_owner))
118122
e = NULL;
119123

120124
spin_unlock(&elv_list_lock);
121-
122125
return e;
123126
}
124127

@@ -144,8 +147,12 @@ void __init load_default_elevator_module(void)
144147
if (!chosen_elevator[0])
145148
return;
146149

150+
/*
151+
* Boot parameter is deprecated, we haven't supported that for MQ.
152+
* Only look for non-mq schedulers from here.
153+
*/
147154
spin_lock(&elv_list_lock);
148-
e = elevator_find(chosen_elevator);
155+
e = elevator_find(chosen_elevator, false);
149156
spin_unlock(&elv_list_lock);
150157

151158
if (!e)
@@ -202,7 +209,7 @@ int elevator_init(struct request_queue *q, char *name)
202209
q->boundary_rq = NULL;
203210

204211
if (name) {
205-
e = elevator_get(name, true);
212+
e = elevator_get(q, name, true);
206213
if (!e)
207214
return -EINVAL;
208215
}
@@ -214,7 +221,7 @@ int elevator_init(struct request_queue *q, char *name)
214221
* allowed from async.
215222
*/
216223
if (!e && !q->mq_ops && *chosen_elevator) {
217-
e = elevator_get(chosen_elevator, false);
224+
e = elevator_get(q, chosen_elevator, false);
218225
if (!e)
219226
printk(KERN_ERR "I/O scheduler %s not found\n",
220227
chosen_elevator);
@@ -229,17 +236,17 @@ int elevator_init(struct request_queue *q, char *name)
229236
*/
230237
if (q->mq_ops) {
231238
if (q->nr_hw_queues == 1)
232-
e = elevator_get("mq-deadline", false);
239+
e = elevator_get(q, "mq-deadline", false);
233240
if (!e)
234241
return 0;
235242
} else
236-
e = elevator_get(CONFIG_DEFAULT_IOSCHED, false);
243+
e = elevator_get(q, CONFIG_DEFAULT_IOSCHED, false);
237244

238245
if (!e) {
239246
printk(KERN_ERR
240247
"Default I/O scheduler not found. " \
241248
"Using noop.\n");
242-
e = elevator_get("noop", false);
249+
e = elevator_get(q, "noop", false);
243250
}
244251
}
245252

@@ -905,7 +912,7 @@ int elv_register(struct elevator_type *e)
905912

906913
/* register, don't allow duplicate names */
907914
spin_lock(&elv_list_lock);
908-
if (elevator_find(e->elevator_name)) {
915+
if (elevator_find(e->elevator_name, e->uses_mq)) {
909916
spin_unlock(&elv_list_lock);
910917
if (e->icq_cache)
911918
kmem_cache_destroy(e->icq_cache);
@@ -1066,7 +1073,7 @@ static int __elevator_change(struct request_queue *q, const char *name)
10661073
return elevator_switch(q, NULL);
10671074

10681075
strlcpy(elevator_name, name, sizeof(elevator_name));
1069-
e = elevator_get(strstrip(elevator_name), true);
1076+
e = elevator_get(q, strstrip(elevator_name), true);
10701077
if (!e)
10711078
return -EINVAL;
10721079

@@ -1076,15 +1083,6 @@ static int __elevator_change(struct request_queue *q, const char *name)
10761083
return 0;
10771084
}
10781085

1079-
if (!e->uses_mq && q->mq_ops) {
1080-
elevator_put(e);
1081-
return -EINVAL;
1082-
}
1083-
if (e->uses_mq && !q->mq_ops) {
1084-
elevator_put(e);
1085-
return -EINVAL;
1086-
}
1087-
10881086
return elevator_switch(q, e);
10891087
}
10901088

0 commit comments

Comments
 (0)