Skip to content

Commit 9586e67

Browse files
naotaaxboe
authored andcommitted
block: schedule queue restart after BLK_STS_ZONE_RESOURCE
When dispatching a zone append write request to a SCSI zoned block device, if the target zone of the request is already locked, the device driver will return BLK_STS_ZONE_RESOURCE and the request will be pushed back to the hctx dipatch queue. The queue will be marked as RESTART in dd_finish_request() and restarted in __blk_mq_free_request(). However, this restart applies to the hctx of the completed request. If the requeued request is on a different hctx, dispatch will no be retried until another request is submitted or the next periodic queue run triggers, leading to up to 30 seconds latency for the requeued request. Fix this problem by scheduling a queue restart similarly to the BLK_STS_RESOURCE case or when we cannot get the budget. Also, consolidate the checks into the "need_resource" variable to simplify the condition. Signed-off-by: Naohiro Aota <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Cc: Niklas Cassel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent d308ae0 commit 9586e67

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

block/blk-mq.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
13251325
int errors, queued;
13261326
blk_status_t ret = BLK_STS_OK;
13271327
LIST_HEAD(zone_list);
1328+
bool needs_resource = false;
13281329

13291330
if (list_empty(list))
13301331
return false;
@@ -1370,6 +1371,8 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
13701371
queued++;
13711372
break;
13721373
case BLK_STS_RESOURCE:
1374+
needs_resource = true;
1375+
fallthrough;
13731376
case BLK_STS_DEV_RESOURCE:
13741377
blk_mq_handle_dev_resource(rq, list);
13751378
goto out;
@@ -1380,6 +1383,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
13801383
* accept.
13811384
*/
13821385
blk_mq_handle_zone_resource(rq, &zone_list);
1386+
needs_resource = true;
13831387
break;
13841388
default:
13851389
errors++;
@@ -1406,7 +1410,6 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
14061410
/* For non-shared tags, the RESTART check will suffice */
14071411
bool no_tag = prep == PREP_DISPATCH_NO_TAG &&
14081412
(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED);
1409-
bool no_budget_avail = prep == PREP_DISPATCH_NO_BUDGET;
14101413

14111414
if (nr_budgets)
14121415
blk_mq_release_budgets(q, list);
@@ -1447,14 +1450,16 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
14471450
* If driver returns BLK_STS_RESOURCE and SCHED_RESTART
14481451
* bit is set, run queue after a delay to avoid IO stalls
14491452
* that could otherwise occur if the queue is idle. We'll do
1450-
* similar if we couldn't get budget and SCHED_RESTART is set.
1453+
* similar if we couldn't get budget or couldn't lock a zone
1454+
* and SCHED_RESTART is set.
14511455
*/
14521456
needs_restart = blk_mq_sched_needs_restart(hctx);
1457+
if (prep == PREP_DISPATCH_NO_BUDGET)
1458+
needs_resource = true;
14531459
if (!needs_restart ||
14541460
(no_tag && list_empty_careful(&hctx->dispatch_wait.entry)))
14551461
blk_mq_run_hw_queue(hctx, true);
1456-
else if (needs_restart && (ret == BLK_STS_RESOURCE ||
1457-
no_budget_avail))
1462+
else if (needs_restart && needs_resource)
14581463
blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY);
14591464

14601465
blk_mq_update_dispatch_busy(hctx, true);

0 commit comments

Comments
 (0)