Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: only call ->request_fn when the queue is not stopped

Callers should use either blk_run_queue/__blk_run_queue, or
blk_start_queueing() to invoke request handling instead of calling
->request_fn() directly as that does not take the queue stopped
flag into account.

Also add appropriate comments on the above functions to detail
their usage.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

+20 -6
+17 -2
block/blk-core.c
··· 325 325 326 326 static void blk_invoke_request_fn(struct request_queue *q) 327 327 { 328 + if (unlikely(blk_queue_stopped(q))) 329 + return; 330 + 328 331 /* 329 332 * one level of recursion is ok and is much faster than kicking 330 333 * the unplug handling ··· 402 399 EXPORT_SYMBOL(blk_sync_queue); 403 400 404 401 /** 405 - * blk_run_queue - run a single device queue 402 + * __blk_run_queue - run a single device queue 406 403 * @q: The queue to run 404 + * 405 + * Description: 406 + * See @blk_run_queue. This variant must be called with the queue lock 407 + * held and interrupts disabled. 408 + * 407 409 */ 408 410 void __blk_run_queue(struct request_queue *q) 409 411 { ··· 426 418 /** 427 419 * blk_run_queue - run a single device queue 428 420 * @q: The queue to run 421 + * 422 + * Description: 423 + * Invoke request handling on this queue, if it has pending work to do. 424 + * May be used to restart queueing when a request has completed. Also 425 + * See @blk_start_queueing. 426 + * 429 427 */ 430 428 void blk_run_queue(struct request_queue *q) 431 429 { ··· 898 884 * 899 885 * This is basically a helper to remove the need to know whether a queue 900 886 * is plugged or not if someone just wants to initiate dispatch of requests 901 - * for this queue. 887 + * for this queue. Should be used to start queueing on a device outside 888 + * of ->request_fn() context. Also see @blk_run_queue. 902 889 * 903 890 * The queue lock must be held with interrupts disabled. 904 891 */
+3 -4
block/elevator.c
··· 612 612 * processing. 613 613 */ 614 614 blk_remove_plug(q); 615 - q->request_fn(q); 615 + blk_start_queueing(q); 616 616 break; 617 617 618 618 case ELEVATOR_INSERT_SORT: ··· 950 950 blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && 951 951 blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { 952 952 blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); 953 - q->request_fn(q); 953 + blk_start_queueing(q); 954 954 } 955 955 } 956 956 } ··· 1109 1109 elv_drain_elevator(q); 1110 1110 1111 1111 while (q->rq.elvpriv) { 1112 - blk_remove_plug(q); 1113 - q->request_fn(q); 1112 + blk_start_queueing(q); 1114 1113 spin_unlock_irq(q->queue_lock); 1115 1114 msleep(10); 1116 1115 spin_lock_irq(q->queue_lock);