Skip to content

Commit 7211aef

Browse files
damien-lemoalaxboe
authored andcommitted
block: mq-deadline: Fix write completion handling
For a zoned block device using mq-deadline, if a write request for a zone is received while another write was already dispatched for the same zone, dd_dispatch_request() will return NULL and the newly inserted write request is kept in the scheduler queue waiting for the ongoing zone write to complete. With this behavior, when no other request has been dispatched, rq_list in blk_mq_sched_dispatch_requests() is empty and blk_mq_sched_mark_restart_hctx() not called. This in turn leads to __blk_mq_free_request() call of blk_mq_sched_restart() to not run the queue when the already dispatched write request completes. The newly dispatched request stays stuck in the scheduler queue until eventually another request is submitted. This problem does not affect SCSI disk as the SCSI stack handles queue restart on request completion. However, this problem is can be triggered the nullblk driver with zoned mode enabled. Fix this by always requesting a queue restart in dd_dispatch_request() if no request was dispatched while WRITE requests are queued. Fixes: 5700f69 ("mq-deadline: Introduce zone locking support") Cc: <stable@vger.kernel.org> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> Add missing export of blk_mq_sched_restart() Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 7e849dd commit 7211aef

File tree

3 files changed

+14
-2
lines changed

3 files changed

+14
-2
lines changed

block/blk-mq-sched.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,14 @@ void blk_mq_sched_assign_ioc(struct request *rq)
6161
* Mark a hardware queue as needing a restart. For shared queues, maintain
6262
* a count of how many hardware queues are marked for restart.
6363
*/
64-
static void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
64+
void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
6565
{
6666
if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
6767
return;
6868

6969
set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
7070
}
71+
EXPORT_SYMBOL_GPL(blk_mq_sched_mark_restart_hctx);
7172

7273
void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx)
7374
{

block/blk-mq-sched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio,
1515
struct request **merged_request);
1616
bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio);
1717
bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq);
18+
void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx);
1819
void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx);
1920

2021
void blk_mq_sched_insert_request(struct request *rq, bool at_head,

block/mq-deadline.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,16 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd)
373373

374374
/*
375375
* One confusing aspect here is that we get called for a specific
376-
* hardware queue, but we return a request that may not be for a
376+
* hardware queue, but we may return a request that is for a
377377
* different hardware queue. This is because mq-deadline has shared
378378
* state for all hardware queues, in terms of sorting, FIFOs, etc.
379+
*
380+
* For a zoned block device, __dd_dispatch_request() may return NULL
381+
* if all the queued write requests are directed at zones that are already
382+
* locked due to on-going write requests. In this case, make sure to mark
383+
* the queue as needing a restart to ensure that the queue is run again
384+
* and the pending writes dispatched once the target zones for the ongoing
385+
* write requests are unlocked in dd_finish_request().
379386
*/
380387
static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
381388
{
@@ -384,6 +391,9 @@ static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
384391

385392
spin_lock(&dd->lock);
386393
rq = __dd_dispatch_request(dd);
394+
if (!rq && blk_queue_is_zoned(hctx->queue) &&
395+
!list_empty(&dd->fifo_list[WRITE]))
396+
blk_mq_sched_mark_restart_hctx(hctx);
387397
spin_unlock(&dd->lock);
388398

389399
return rq;

0 commit comments

Comments
 (0)