diff options
Diffstat (limited to 'block/elevator.c')
-rw-r--r-- | block/elevator.c | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/block/elevator.c b/block/elevator.c index 7ae50eb2732b..77856bf29568 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -83,12 +83,15 @@ bool elv_bio_merge_ok(struct request *rq, struct bio *bio) | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL(elv_bio_merge_ok); | 84 | EXPORT_SYMBOL(elv_bio_merge_ok); |
85 | 85 | ||
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) | ||
87 | { | 90 | { |
88 | struct elevator_type *e; | 91 | struct elevator_type *e; |
89 | 92 | ||
90 | list_for_each_entry(e, &elv_list, list) { | 93 | 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)) |
92 | return e; | 95 | return e; |
93 | } | 96 | } |
94 | 97 | ||
@@ -100,25 +103,25 @@ static void elevator_put(struct elevator_type *e) | |||
100 | module_put(e->elevator_owner); | 103 | module_put(e->elevator_owner); |
101 | } | 104 | } |
102 | 105 | ||
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) | ||
104 | { | 108 | { |
105 | struct elevator_type *e; | 109 | struct elevator_type *e; |
106 | 110 | ||
107 | spin_lock(&elv_list_lock); | 111 | spin_lock(&elv_list_lock); |
108 | 112 | ||
109 | e = elevator_find(name); | 113 | e = elevator_find(name, q->mq_ops != NULL); |
110 | if (!e && try_loading) { | 114 | if (!e && try_loading) { |
111 | spin_unlock(&elv_list_lock); | 115 | spin_unlock(&elv_list_lock); |
112 | request_module("%s-iosched", name); | 116 | request_module("%s-iosched", name); |
113 | spin_lock(&elv_list_lock); | 117 | spin_lock(&elv_list_lock); |
114 | e = elevator_find(name); | 118 | e = elevator_find(name, q->mq_ops != NULL); |
115 | } | 119 | } |
116 | 120 | ||
117 | if (e && !try_module_get(e->elevator_owner)) | 121 | if (e && !try_module_get(e->elevator_owner)) |
118 | e = NULL; | 122 | e = NULL; |
119 | 123 | ||
120 | spin_unlock(&elv_list_lock); | 124 | spin_unlock(&elv_list_lock); |
121 | |||
122 | return e; | 125 | return e; |
123 | } | 126 | } |
124 | 127 | ||
@@ -144,8 +147,12 @@ void __init load_default_elevator_module(void) | |||
144 | if (!chosen_elevator[0]) | 147 | if (!chosen_elevator[0]) |
145 | return; | 148 | return; |
146 | 149 | ||
150 | /* | ||
151 | * Boot parameter is deprecated, we haven't supported that for MQ. | ||
152 | * Only look for non-mq schedulers from here. | ||
153 | */ | ||
147 | spin_lock(&elv_list_lock); | 154 | spin_lock(&elv_list_lock); |
148 | e = elevator_find(chosen_elevator); | 155 | e = elevator_find(chosen_elevator, false); |
149 | spin_unlock(&elv_list_lock); | 156 | spin_unlock(&elv_list_lock); |
150 | 157 | ||
151 | if (!e) | 158 | if (!e) |
@@ -202,7 +209,7 @@ int elevator_init(struct request_queue *q, char *name) | |||
202 | q->boundary_rq = NULL; | 209 | q->boundary_rq = NULL; |
203 | 210 | ||
204 | if (name) { | 211 | if (name) { |
205 | e = elevator_get(name, true); | 212 | e = elevator_get(q, name, true); |
206 | if (!e) | 213 | if (!e) |
207 | return -EINVAL; | 214 | return -EINVAL; |
208 | } | 215 | } |
@@ -214,7 +221,7 @@ int elevator_init(struct request_queue *q, char *name) | |||
214 | * allowed from async. | 221 | * allowed from async. |
215 | */ | 222 | */ |
216 | if (!e && !q->mq_ops && *chosen_elevator) { | 223 | if (!e && !q->mq_ops && *chosen_elevator) { |
217 | e = elevator_get(chosen_elevator, false); | 224 | e = elevator_get(q, chosen_elevator, false); |
218 | if (!e) | 225 | if (!e) |
219 | printk(KERN_ERR "I/O scheduler %s not found\n", | 226 | printk(KERN_ERR "I/O scheduler %s not found\n", |
220 | chosen_elevator); | 227 | chosen_elevator); |
@@ -229,17 +236,17 @@ int elevator_init(struct request_queue *q, char *name) | |||
229 | */ | 236 | */ |
230 | if (q->mq_ops) { | 237 | if (q->mq_ops) { |
231 | if (q->nr_hw_queues == 1) | 238 | if (q->nr_hw_queues == 1) |
232 | e = elevator_get("mq-deadline", false); | 239 | e = elevator_get(q, "mq-deadline", false); |
233 | if (!e) | 240 | if (!e) |
234 | return 0; | 241 | return 0; |
235 | } else | 242 | } else |
236 | e = elevator_get(CONFIG_DEFAULT_IOSCHED, false); | 243 | e = elevator_get(q, CONFIG_DEFAULT_IOSCHED, false); |
237 | 244 | ||
238 | if (!e) { | 245 | if (!e) { |
239 | printk(KERN_ERR | 246 | printk(KERN_ERR |
240 | "Default I/O scheduler not found. " \ | 247 | "Default I/O scheduler not found. " \ |
241 | "Using noop.\n"); | 248 | "Using noop.\n"); |
242 | e = elevator_get("noop", false); | 249 | e = elevator_get(q, "noop", false); |
243 | } | 250 | } |
244 | } | 251 | } |
245 | 252 | ||
@@ -905,7 +912,7 @@ int elv_register(struct elevator_type *e) | |||
905 | 912 | ||
906 | /* register, don't allow duplicate names */ | 913 | /* register, don't allow duplicate names */ |
907 | spin_lock(&elv_list_lock); | 914 | spin_lock(&elv_list_lock); |
908 | if (elevator_find(e->elevator_name)) { | 915 | if (elevator_find(e->elevator_name, e->uses_mq)) { |
909 | spin_unlock(&elv_list_lock); | 916 | spin_unlock(&elv_list_lock); |
910 | if (e->icq_cache) | 917 | if (e->icq_cache) |
911 | kmem_cache_destroy(e->icq_cache); | 918 | kmem_cache_destroy(e->icq_cache); |
@@ -1066,7 +1073,7 @@ static int __elevator_change(struct request_queue *q, const char *name) | |||
1066 | return elevator_switch(q, NULL); | 1073 | return elevator_switch(q, NULL); |
1067 | 1074 | ||
1068 | strlcpy(elevator_name, name, sizeof(elevator_name)); | 1075 | strlcpy(elevator_name, name, sizeof(elevator_name)); |
1069 | e = elevator_get(strstrip(elevator_name), true); | 1076 | e = elevator_get(q, strstrip(elevator_name), true); |
1070 | if (!e) | 1077 | if (!e) |
1071 | return -EINVAL; | 1078 | return -EINVAL; |
1072 | 1079 | ||
@@ -1076,15 +1083,6 @@ static int __elevator_change(struct request_queue *q, const char *name) | |||
1076 | return 0; | 1083 | return 0; |
1077 | } | 1084 | } |
1078 | 1085 | ||
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 | |||
1088 | return elevator_switch(q, e); | 1086 | return elevator_switch(q, e); |
1089 | } | 1087 | } |
1090 | 1088 | ||