Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * blk-mq scheduling framework
4 : : *
5 : : * Copyright (C) 2016 Jens Axboe
6 : : */
7 : : #include <linux/kernel.h>
8 : : #include <linux/module.h>
9 : : #include <linux/blk-mq.h>
10 : :
11 : : #include <trace/events/block.h>
12 : :
13 : : #include "blk.h"
14 : : #include "blk-mq.h"
15 : : #include "blk-mq-debugfs.h"
16 : : #include "blk-mq-sched.h"
17 : : #include "blk-mq-tag.h"
18 : : #include "blk-wbt.h"
19 : :
20 : 0 : void blk_mq_sched_free_hctx_data(struct request_queue *q,
21 : : void (*exit)(struct blk_mq_hw_ctx *))
22 : : {
23 : 0 : struct blk_mq_hw_ctx *hctx;
24 : 0 : int i;
25 : :
26 [ # # ]: 0 : queue_for_each_hw_ctx(q, hctx, i) {
27 [ # # # # ]: 0 : if (exit && hctx->sched_data)
28 : 0 : exit(hctx);
29 : 0 : kfree(hctx->sched_data);
30 : 0 : hctx->sched_data = NULL;
31 : : }
32 : 0 : }
33 : : EXPORT_SYMBOL_GPL(blk_mq_sched_free_hctx_data);
34 : :
35 : 0 : void blk_mq_sched_assign_ioc(struct request *rq)
36 : : {
37 : 0 : struct request_queue *q = rq->q;
38 : 0 : struct io_context *ioc;
39 : 0 : struct io_cq *icq;
40 : :
41 : : /*
42 : : * May not have an IO context if it's a passthrough request
43 : : */
44 [ # # ]: 0 : ioc = current->io_context;
45 [ # # ]: 0 : if (!ioc)
46 : : return;
47 : :
48 : 0 : spin_lock_irq(&q->queue_lock);
49 : 0 : icq = ioc_lookup_icq(ioc, q);
50 : 0 : spin_unlock_irq(&q->queue_lock);
51 : :
52 [ # # ]: 0 : if (!icq) {
53 : 0 : icq = ioc_create_icq(ioc, q, GFP_ATOMIC);
54 [ # # ]: 0 : if (!icq)
55 : : return;
56 : : }
57 : 0 : get_io_context(icq->ioc);
58 : 0 : rq->elv.icq = icq;
59 : : }
60 : :
61 : : /*
62 : : * Mark a hardware queue as needing a restart. For shared queues, maintain
63 : : * a count of how many hardware queues are marked for restart.
64 : : */
65 : 6298 : void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
66 : : {
67 [ + + ]: 6298 : if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
68 : : return;
69 : :
70 : 5303 : set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
71 : : }
72 : : EXPORT_SYMBOL_GPL(blk_mq_sched_mark_restart_hctx);
73 : :
74 : 34732 : void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx)
75 : : {
76 [ + + ]: 34732 : if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
77 : : return;
78 : 5303 : clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
79 : :
80 : 5303 : blk_mq_run_hw_queue(hctx, true);
81 : : }
82 : :
83 : : /*
84 : : * Only SCSI implements .get_budget and .put_budget, and SCSI restarts
85 : : * its queue by itself in its completion handler, so we don't need to
86 : : * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE.
87 : : */
88 : 36076 : static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
89 : : {
90 : 36076 : struct request_queue *q = hctx->queue;
91 : 36076 : struct elevator_queue *e = q->elevator;
92 : 36076 : LIST_HEAD(rq_list);
93 : :
94 : 65150 : do {
95 : 65150 : struct request *rq;
96 : :
97 [ + - + + ]: 65150 : if (e->type->ops.has_work && !e->type->ops.has_work(hctx))
98 : : break;
99 : :
100 [ + - + + ]: 64428 : if (!blk_mq_get_dispatch_budget(hctx))
101 : : break;
102 : :
103 : 29749 : rq = e->type->ops.dispatch_request(hctx);
104 [ - + ]: 29749 : if (!rq) {
105 [ # # ]: 0 : blk_mq_put_dispatch_budget(hctx);
106 : : break;
107 : : }
108 : :
109 : : /*
110 : : * Now this rq owns the budget which has to be released
111 : : * if this rq won't be queued to driver via .queue_rq()
112 : : * in blk_mq_dispatch_rq_list().
113 : : */
114 : 29749 : list_add(&rq->queuelist, &rq_list);
115 [ + + ]: 29749 : } while (blk_mq_dispatch_rq_list(q, &rq_list, true));
116 : 36076 : }
117 : :
118 : 0 : static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx,
119 : : struct blk_mq_ctx *ctx)
120 : : {
121 : 0 : unsigned short idx = ctx->index_hw[hctx->type];
122 : :
123 : 0 : if (++idx == hctx->nr_ctx)
124 : 0 : idx = 0;
125 : :
126 : 0 : return hctx->ctxs[idx];
127 : : }
128 : :
129 : : /*
130 : : * Only SCSI implements .get_budget and .put_budget, and SCSI restarts
131 : : * its queue by itself in its completion handler, so we don't need to
132 : : * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE.
133 : : */
134 : 1500 : static void blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
135 : : {
136 : 1500 : struct request_queue *q = hctx->queue;
137 : 1500 : LIST_HEAD(rq_list);
138 : 1500 : struct blk_mq_ctx *ctx = READ_ONCE(hctx->dispatch_from);
139 : :
140 : 1500 : do {
141 : 1500 : struct request *rq;
142 : :
143 [ - + ]: 1500 : if (!sbitmap_any_bit_set(&hctx->ctx_map))
144 : : break;
145 : :
146 [ # # # # ]: 0 : if (!blk_mq_get_dispatch_budget(hctx))
147 : : break;
148 : :
149 : 0 : rq = blk_mq_dequeue_from_ctx(hctx, ctx);
150 [ # # ]: 0 : if (!rq) {
151 [ # # ]: 0 : blk_mq_put_dispatch_budget(hctx);
152 : : break;
153 : : }
154 : :
155 : : /*
156 : : * Now this rq owns the budget which has to be released
157 : : * if this rq won't be queued to driver via .queue_rq()
158 : : * in blk_mq_dispatch_rq_list().
159 : : */
160 [ # # ]: 0 : list_add(&rq->queuelist, &rq_list);
161 : :
162 : : /* round robin for fair dispatch */
163 [ # # ]: 0 : ctx = blk_mq_next_ctx(hctx, rq->mq_ctx);
164 : :
165 [ # # ]: 0 : } while (blk_mq_dispatch_rq_list(q, &rq_list, true));
166 : :
167 : 1500 : WRITE_ONCE(hctx->dispatch_from, ctx);
168 : 1500 : }
169 : :
170 : 38317 : void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
171 : : {
172 : 38317 : struct request_queue *q = hctx->queue;
173 : 38317 : struct elevator_queue *e = q->elevator;
174 [ + + - + ]: 38317 : const bool has_sched_dispatch = e && e->type->ops.dispatch_request;
175 : 38317 : LIST_HEAD(rq_list);
176 : :
177 : : /* RCU or SRCU read lock is needed before checking quiesced flag */
178 [ + - - + ]: 38317 : if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(q)))
179 : 0 : return;
180 : :
181 : 38317 : hctx->run++;
182 : :
183 : : /*
184 : : * If we have previous entries on our dispatch list, grab them first for
185 : : * more fair dispatch.
186 : : */
187 [ + + ]: 38317 : if (!list_empty_careful(&hctx->dispatch)) {
188 : 6262 : spin_lock(&hctx->lock);
189 [ + - ]: 6262 : if (!list_empty(&hctx->dispatch))
190 [ + - ]: 6262 : list_splice_init(&hctx->dispatch, &rq_list);
191 : 6262 : spin_unlock(&hctx->lock);
192 : : }
193 : :
194 : : /*
195 : : * Only ask the scheduler for requests, if we didn't have residual
196 : : * requests from the dispatch list. This is to avoid the case where
197 : : * we only ever dispatch a fraction of the requests available because
198 : : * of low device queue depth. Once we pull requests out of the IO
199 : : * scheduler, we can no longer merge or sort them. So it's best to
200 : : * leave them there for as long as we can. Mark the hw queue as
201 : : * needing a restart in that case.
202 : : *
203 : : * We want to dispatch from the scheduler if there was nothing
204 : : * on the dispatch list or we were able to dispatch from the
205 : : * dispatch list.
206 : : */
207 [ + + ]: 38317 : if (!list_empty(&rq_list)) {
208 : 6262 : blk_mq_sched_mark_restart_hctx(hctx);
209 [ + + ]: 6262 : if (blk_mq_dispatch_rq_list(q, &rq_list, false)) {
210 [ + + ]: 5521 : if (has_sched_dispatch)
211 : 4021 : blk_mq_do_dispatch_sched(hctx);
212 : : else
213 : 1500 : blk_mq_do_dispatch_ctx(hctx);
214 : : }
215 [ + - ]: 32055 : } else if (has_sched_dispatch) {
216 : 32055 : blk_mq_do_dispatch_sched(hctx);
217 [ # # ]: 0 : } else if (hctx->dispatch_busy) {
218 : : /* dequeue request one by one from sw queue if queue is busy */
219 : 0 : blk_mq_do_dispatch_ctx(hctx);
220 : : } else {
221 : 0 : blk_mq_flush_busy_ctxs(hctx, &rq_list);
222 : 0 : blk_mq_dispatch_rq_list(q, &rq_list, false);
223 : : }
224 : : }
225 : :
226 : 30108 : bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio,
227 : : unsigned int nr_segs, struct request **merged_request)
228 : : {
229 : 30108 : struct request *rq;
230 : :
231 [ + - - + ]: 30108 : switch (elv_merge(q, &rq, bio)) {
232 : 1 : case ELEVATOR_BACK_MERGE:
233 [ + - - - ]: 1 : if (!blk_mq_sched_allow_merge(q, rq, bio))
234 : : return false;
235 [ + - ]: 1 : if (!bio_attempt_back_merge(rq, bio, nr_segs))
236 : : return false;
237 : 1 : *merged_request = attempt_back_merge(q, rq);
238 [ + - ]: 1 : if (!*merged_request)
239 : 1 : elv_merged_request(q, rq, ELEVATOR_BACK_MERGE);
240 : : return true;
241 : 0 : case ELEVATOR_FRONT_MERGE:
242 [ # # # # ]: 0 : if (!blk_mq_sched_allow_merge(q, rq, bio))
243 : : return false;
244 [ # # ]: 0 : if (!bio_attempt_front_merge(rq, bio, nr_segs))
245 : : return false;
246 : 0 : *merged_request = attempt_front_merge(q, rq);
247 [ # # ]: 0 : if (!*merged_request)
248 : 0 : elv_merged_request(q, rq, ELEVATOR_FRONT_MERGE);
249 : : return true;
250 : 0 : case ELEVATOR_DISCARD_MERGE:
251 : 0 : return bio_attempt_discard_merge(q, rq, bio);
252 : : default:
253 : : return false;
254 : : }
255 : : }
256 : : EXPORT_SYMBOL_GPL(blk_mq_sched_try_merge);
257 : :
258 : : /*
259 : : * Iterate list of requests and see if we can merge this bio with any
260 : : * of them.
261 : : */
262 : 0 : bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list,
263 : : struct bio *bio, unsigned int nr_segs)
264 : : {
265 : 0 : struct request *rq;
266 : 0 : int checked = 8;
267 : :
268 [ # # ]: 0 : list_for_each_entry_reverse(rq, list, queuelist) {
269 : 0 : bool merged = false;
270 : :
271 [ # # ]: 0 : if (!checked--)
272 : : break;
273 : :
274 [ # # ]: 0 : if (!blk_rq_merge_ok(rq, bio))
275 : 0 : continue;
276 : :
277 [ # # # # ]: 0 : switch (blk_try_merge(rq, bio)) {
278 : : case ELEVATOR_BACK_MERGE:
279 [ # # # # ]: 0 : if (blk_mq_sched_allow_merge(q, rq, bio))
280 : 0 : merged = bio_attempt_back_merge(rq, bio,
281 : : nr_segs);
282 : : break;
283 : : case ELEVATOR_FRONT_MERGE:
284 [ # # # # ]: 0 : if (blk_mq_sched_allow_merge(q, rq, bio))
285 : 0 : merged = bio_attempt_front_merge(rq, bio,
286 : : nr_segs);
287 : : break;
288 : 0 : case ELEVATOR_DISCARD_MERGE:
289 : 0 : merged = bio_attempt_discard_merge(q, rq, bio);
290 : 0 : break;
291 : 0 : default:
292 : 0 : continue;
293 : : }
294 : :
295 : : return merged;
296 : : }
297 : :
298 : : return false;
299 : : }
300 : : EXPORT_SYMBOL_GPL(blk_mq_bio_list_merge);
301 : :
302 : : /*
303 : : * Reverse check our software queue for entries that we could potentially
304 : : * merge with. Currently includes a hand-wavy stop count of 8, to not spend
305 : : * too much time checking for merges.
306 : : */
307 : 0 : static bool blk_mq_attempt_merge(struct request_queue *q,
308 : : struct blk_mq_hw_ctx *hctx,
309 : : struct blk_mq_ctx *ctx, struct bio *bio,
310 : : unsigned int nr_segs)
311 : : {
312 : 0 : enum hctx_type type = hctx->type;
313 : :
314 : 0 : lockdep_assert_held(&ctx->lock);
315 : :
316 [ # # ]: 0 : if (blk_mq_bio_list_merge(q, &ctx->rq_lists[type], bio, nr_segs)) {
317 : 0 : ctx->rq_merged++;
318 : 0 : return true;
319 : : }
320 : :
321 : : return false;
322 : : }
323 : :
324 : 30108 : bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio,
325 : : unsigned int nr_segs)
326 : : {
327 : 30108 : struct elevator_queue *e = q->elevator;
328 : 30108 : struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
329 [ + - ]: 30108 : struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
330 : 30108 : bool ret = false;
331 : 30108 : enum hctx_type type;
332 : :
333 [ + - + - ]: 30108 : if (e && e->type->ops.bio_merge)
334 : 30108 : return e->type->ops.bio_merge(hctx, bio, nr_segs);
335 : :
336 : 0 : type = hctx->type;
337 [ # # ]: 0 : if ((hctx->flags & BLK_MQ_F_SHOULD_MERGE) &&
338 [ # # ]: 0 : !list_empty_careful(&ctx->rq_lists[type])) {
339 : : /* default per sw-queue merge */
340 : 0 : spin_lock(&ctx->lock);
341 : 0 : ret = blk_mq_attempt_merge(q, hctx, ctx, bio, nr_segs);
342 : 0 : spin_unlock(&ctx->lock);
343 : : }
344 : :
345 : : return ret;
346 : : }
347 : :
348 : 30108 : bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq)
349 : : {
350 [ + + + + ]: 30108 : return rq_mergeable(rq) && elv_attempt_insert_merge(q, rq);
351 : : }
352 : : EXPORT_SYMBOL_GPL(blk_mq_sched_try_insert_merge);
353 : :
354 : 29749 : void blk_mq_sched_request_inserted(struct request *rq)
355 : : {
356 : 29749 : trace_block_rq_insert(rq->q, rq);
357 : 29749 : }
358 : : EXPORT_SYMBOL_GPL(blk_mq_sched_request_inserted);
359 : :
360 : 8596 : static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
361 : : bool has_sched,
362 : : struct request *rq)
363 : : {
364 : : /*
365 : : * dispatch flush and passthrough rq directly
366 : : *
367 : : * passthrough request has to be added to hctx->dispatch directly.
368 : : * For some reason, device may be in one situation which can't
369 : : * handle FS request, so STS_RESOURCE is always returned and the
370 : : * FS request will be added to hctx->dispatch. However passthrough
371 : : * request may be required at that time for fixing the problem. If
372 : : * passthrough request is added to scheduler queue, there isn't any
373 : : * chance to dispatch it given we prioritize requests in hctx->dispatch.
374 : : */
375 [ + + ]: 7810 : if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq))
376 : : return true;
377 : :
378 [ + - ]: 3750 : if (has_sched)
379 : 3750 : rq->rq_flags |= RQF_SORTED;
380 : :
381 : : return false;
382 : : }
383 : :
384 : 8596 : void blk_mq_sched_insert_request(struct request *rq, bool at_head,
385 : : bool run_queue, bool async)
386 : : {
387 : 8596 : struct request_queue *q = rq->q;
388 : 8596 : struct elevator_queue *e = q->elevator;
389 : 8596 : struct blk_mq_ctx *ctx = rq->mq_ctx;
390 : 8596 : struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
391 : :
392 : : /* flush rq in flush machinery need to be dispatched directly */
393 [ + + - + ]: 8596 : if (!(rq->rq_flags & RQF_FLUSH_SEQ) && op_is_flush(rq->cmd_flags)) {
394 : 0 : blk_insert_flush(rq);
395 : 0 : goto run;
396 : : }
397 : :
398 [ + + + - : 17192 : WARN_ON(e && (rq->tag != -1));
- + ]
399 : :
400 [ + + ]: 8596 : if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) {
401 : : /*
402 : : * Firstly normal IO request is inserted to scheduler queue or
403 : : * sw queue, meantime we add flush request to dispatch queue(
404 : : * hctx->dispatch) directly and there is at most one in-flight
405 : : * flush request for each hw queue, so it doesn't matter to add
406 : : * flush request to tail or front of the dispatch queue.
407 : : *
408 : : * Secondly in case of NCQ, flush request belongs to non-NCQ
409 : : * command, and queueing it will fail when there is any
410 : : * in-flight normal IO request(NCQ command). When adding flush
411 : : * rq to the front of hctx->dispatch, it is easier to introduce
412 : : * extra time to flush rq's latency because of S_SCHED_RESTART
413 : : * compared with adding to the tail of dispatch queue, then
414 : : * chance of flush merge is increased, and less flush requests
415 : : * will be issued to controller. It is observed that ~10% time
416 : : * is saved in blktests block/004 on disk attached to AHCI/NCQ
417 : : * drive when adding flush rq to the front of hctx->dispatch.
418 : : *
419 : : * Simply queue flush rq to the front of hctx->dispatch so that
420 : : * intensive flush workloads can benefit in case of NCQ HW.
421 : : */
422 [ + + + + ]: 4846 : at_head = (rq->rq_flags & RQF_FLUSH_SEQ) ? true : at_head;
423 : 4846 : blk_mq_request_bypass_insert(rq, at_head, false);
424 : 4846 : goto run;
425 : : }
426 : :
427 [ + - + - ]: 7500 : if (e && e->type->ops.insert_requests) {
428 : 3750 : LIST_HEAD(list);
429 : :
430 : 3750 : list_add(&rq->queuelist, &list);
431 : 3750 : e->type->ops.insert_requests(hctx, &list, at_head);
432 : : } else {
433 : 0 : spin_lock(&ctx->lock);
434 : 0 : __blk_mq_insert_request(hctx, rq, at_head);
435 : 0 : spin_unlock(&ctx->lock);
436 : : }
437 : :
438 : 8596 : run:
439 [ + + ]: 8596 : if (run_queue)
440 : 7810 : blk_mq_run_hw_queue(hctx, async);
441 : 8596 : }
442 : :
443 : 25879 : void blk_mq_sched_insert_requests(struct blk_mq_hw_ctx *hctx,
444 : : struct blk_mq_ctx *ctx,
445 : : struct list_head *list, bool run_queue_async)
446 : : {
447 : 25879 : struct elevator_queue *e;
448 : 25879 : struct request_queue *q = hctx->queue;
449 : :
450 : : /*
451 : : * blk_mq_sched_insert_requests() is called from flush plug
452 : : * context only, and hold one usage counter to prevent queue
453 : : * from being released.
454 : : */
455 : 25879 : percpu_ref_get(&q->q_usage_counter);
456 : :
457 : 25879 : e = hctx->queue->elevator;
458 [ + - + - ]: 25879 : if (e && e->type->ops.insert_requests)
459 : 25879 : e->type->ops.insert_requests(hctx, list, false);
460 : : else {
461 : : /*
462 : : * try to issue requests directly if the hw queue isn't
463 : : * busy in case of 'none' scheduler, and this way may save
464 : : * us one extra enqueue & dequeue to sw queue.
465 : : */
466 [ # # # # ]: 0 : if (!hctx->dispatch_busy && !e && !run_queue_async) {
467 : 0 : blk_mq_try_issue_list_directly(hctx, list);
468 [ # # ]: 0 : if (list_empty(list))
469 : 0 : goto out;
470 : : }
471 : 0 : blk_mq_insert_requests(hctx, ctx, list);
472 : : }
473 : :
474 : 25879 : blk_mq_run_hw_queue(hctx, run_queue_async);
475 : 25879 : out:
476 : 25879 : percpu_ref_put(&q->q_usage_counter);
477 : 25879 : }
478 : :
479 : : static void blk_mq_sched_free_tags(struct blk_mq_tag_set *set,
480 : : struct blk_mq_hw_ctx *hctx,
481 : : unsigned int hctx_idx)
482 : : {
483 : : if (hctx->sched_tags) {
484 : : blk_mq_free_rqs(set, hctx->sched_tags, hctx_idx);
485 : : blk_mq_free_rq_map(hctx->sched_tags);
486 : : hctx->sched_tags = NULL;
487 : : }
488 : : }
489 : :
490 : : static int blk_mq_sched_alloc_tags(struct request_queue *q,
491 : : struct blk_mq_hw_ctx *hctx,
492 : : unsigned int hctx_idx)
493 : : {
494 : : struct blk_mq_tag_set *set = q->tag_set;
495 : : int ret;
496 : :
497 : : hctx->sched_tags = blk_mq_alloc_rq_map(set, hctx_idx, q->nr_requests,
498 : : set->reserved_tags);
499 : : if (!hctx->sched_tags)
500 : : return -ENOMEM;
501 : :
502 : : ret = blk_mq_alloc_rqs(set, hctx->sched_tags, hctx_idx, q->nr_requests);
503 : : if (ret)
504 : : blk_mq_sched_free_tags(set, hctx, hctx_idx);
505 : :
506 : : return ret;
507 : : }
508 : :
509 : : /* called in queue's release handler, tagset has gone away */
510 : : static void blk_mq_sched_tags_teardown(struct request_queue *q)
511 : : {
512 : : struct blk_mq_hw_ctx *hctx;
513 : : int i;
514 : :
515 : : queue_for_each_hw_ctx(q, hctx, i) {
516 : : if (hctx->sched_tags) {
517 : : blk_mq_free_rq_map(hctx->sched_tags);
518 : : hctx->sched_tags = NULL;
519 : : }
520 : : }
521 : : }
522 : :
523 : 330 : int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
524 : : {
525 : 330 : struct blk_mq_hw_ctx *hctx;
526 : 330 : struct elevator_queue *eq;
527 : 330 : unsigned int i;
528 : 330 : int ret;
529 : :
530 [ - + ]: 330 : if (!e) {
531 : 0 : q->elevator = NULL;
532 : 0 : q->nr_requests = q->tag_set->queue_depth;
533 : 0 : return 0;
534 : : }
535 : :
536 : : /*
537 : : * Default to double of smaller one between hw queue_depth and 128,
538 : : * since we don't split into sync/async like the old code did.
539 : : * Additionally, this is a per-hw queue depth.
540 : : */
541 : 330 : q->nr_requests = 2 * min_t(unsigned int, q->tag_set->queue_depth,
542 : : BLKDEV_MAX_RQ);
543 : :
544 [ + + ]: 660 : queue_for_each_hw_ctx(q, hctx, i) {
545 : 330 : ret = blk_mq_sched_alloc_tags(q, hctx, i);
546 [ - + ]: 330 : if (ret)
547 : 0 : goto err;
548 : : }
549 : :
550 : 330 : ret = e->ops.init_sched(q, e);
551 [ - + ]: 330 : if (ret)
552 : 0 : goto err;
553 : :
554 : 330 : blk_mq_debugfs_register_sched(q);
555 : :
556 [ + + ]: 990 : queue_for_each_hw_ctx(q, hctx, i) {
557 [ - + ]: 330 : if (e->ops.init_hctx) {
558 : 0 : ret = e->ops.init_hctx(hctx, i);
559 [ # # ]: 0 : if (ret) {
560 : 0 : eq = q->elevator;
561 : 0 : blk_mq_sched_free_requests(q);
562 : 0 : blk_mq_exit_sched(q, eq);
563 : 0 : kobject_put(&eq->kobj);
564 : 0 : return ret;
565 : : }
566 : : }
567 : 330 : blk_mq_debugfs_register_sched_hctx(q, hctx);
568 : : }
569 : :
570 : : return 0;
571 : :
572 : 0 : err:
573 : 0 : blk_mq_sched_free_requests(q);
574 : 0 : blk_mq_sched_tags_teardown(q);
575 : 0 : q->elevator = NULL;
576 : 0 : return ret;
577 : : }
578 : :
579 : : /*
580 : : * called in either blk_queue_cleanup or elevator_switch, tagset
581 : : * is required for freeing requests
582 : : */
583 : 0 : void blk_mq_sched_free_requests(struct request_queue *q)
584 : : {
585 : 0 : struct blk_mq_hw_ctx *hctx;
586 : 0 : int i;
587 : :
588 [ # # ]: 0 : queue_for_each_hw_ctx(q, hctx, i) {
589 [ # # ]: 0 : if (hctx->sched_tags)
590 : 0 : blk_mq_free_rqs(q->tag_set, hctx->sched_tags, i);
591 : : }
592 : 0 : }
593 : :
594 : 0 : void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e)
595 : : {
596 : 0 : struct blk_mq_hw_ctx *hctx;
597 : 0 : unsigned int i;
598 : :
599 [ # # ]: 0 : queue_for_each_hw_ctx(q, hctx, i) {
600 : 0 : blk_mq_debugfs_unregister_sched_hctx(hctx);
601 [ # # # # ]: 0 : if (e->type->ops.exit_hctx && hctx->sched_data) {
602 : 0 : e->type->ops.exit_hctx(hctx, i);
603 : 0 : hctx->sched_data = NULL;
604 : : }
605 : : }
606 : 0 : blk_mq_debugfs_unregister_sched(q);
607 [ # # ]: 0 : if (e->type->ops.exit_sched)
608 : 0 : e->type->ops.exit_sched(e);
609 : 0 : blk_mq_sched_tags_teardown(q);
610 : 0 : q->elevator = NULL;
611 : 0 : }
|