mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	blk-mq: don't restart queue when .get_budget returns BLK_STS_RESOURCE
SCSI restarts its queue in scsi_end_request() automatically, so we don't need to handle this case in blk-mq. Especailly any request won't be dequeued in this case, we needn't to worry about IO hang caused by restart vs. dispatch. Signed-off-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
		
							parent
							
								
									358a3a6bcc
								
							
						
					
					
						commit
						1f460b63d4
					
				
					 3 changed files with 23 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -81,8 +81,12 @@ void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return true if hctx need to run again */
 | 
			
		||||
static bool blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
/*
 | 
			
		||||
 * Only SCSI implements .get_budget and .put_budget, and SCSI restarts
 | 
			
		||||
 * its queue by itself in its completion handler, so we don't need to
 | 
			
		||||
 * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE.
 | 
			
		||||
 */
 | 
			
		||||
static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
{
 | 
			
		||||
	struct request_queue *q = hctx->queue;
 | 
			
		||||
	struct elevator_queue *e = q->elevator;
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +102,7 @@ static bool blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
 | 
			
		||||
		ret = blk_mq_get_dispatch_budget(hctx);
 | 
			
		||||
		if (ret == BLK_STS_RESOURCE)
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		rq = e->type->ops.mq.dispatch_request(hctx);
 | 
			
		||||
		if (!rq) {
 | 
			
		||||
| 
						 | 
				
			
			@ -116,8 +120,6 @@ static bool blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
		 */
 | 
			
		||||
		list_add(&rq->queuelist, &rq_list);
 | 
			
		||||
	} while (blk_mq_dispatch_rq_list(q, &rq_list, true));
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx,
 | 
			
		||||
| 
						 | 
				
			
			@ -131,8 +133,12 @@ static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx,
 | 
			
		|||
	return hctx->ctxs[idx];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return true if hctx need to run again */
 | 
			
		||||
static bool blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
/*
 | 
			
		||||
 * Only SCSI implements .get_budget and .put_budget, and SCSI restarts
 | 
			
		||||
 * its queue by itself in its completion handler, so we don't need to
 | 
			
		||||
 * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE.
 | 
			
		||||
 */
 | 
			
		||||
static void blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
{
 | 
			
		||||
	struct request_queue *q = hctx->queue;
 | 
			
		||||
	LIST_HEAD(rq_list);
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +153,7 @@ static bool blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
 | 
			
		||||
		ret = blk_mq_get_dispatch_budget(hctx);
 | 
			
		||||
		if (ret == BLK_STS_RESOURCE)
 | 
			
		||||
			return true;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		rq = blk_mq_dequeue_from_ctx(hctx, ctx);
 | 
			
		||||
		if (!rq) {
 | 
			
		||||
| 
						 | 
				
			
			@ -171,22 +177,19 @@ static bool blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
	} while (blk_mq_dispatch_rq_list(q, &rq_list, true));
 | 
			
		||||
 | 
			
		||||
	WRITE_ONCE(hctx->dispatch_from, ctx);
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return true if hw queue need to be run again */
 | 
			
		||||
bool blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
{
 | 
			
		||||
	struct request_queue *q = hctx->queue;
 | 
			
		||||
	struct elevator_queue *e = q->elevator;
 | 
			
		||||
	const bool has_sched_dispatch = e && e->type->ops.mq.dispatch_request;
 | 
			
		||||
	LIST_HEAD(rq_list);
 | 
			
		||||
	bool run_queue = false;
 | 
			
		||||
 | 
			
		||||
	/* RCU or SRCU read lock is needed before checking quiesced flag */
 | 
			
		||||
	if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(q)))
 | 
			
		||||
		return false;
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	hctx->run++;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -218,12 +221,12 @@ bool blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
		blk_mq_sched_mark_restart_hctx(hctx);
 | 
			
		||||
		if (blk_mq_dispatch_rq_list(q, &rq_list, false)) {
 | 
			
		||||
			if (has_sched_dispatch)
 | 
			
		||||
				run_queue = blk_mq_do_dispatch_sched(hctx);
 | 
			
		||||
				blk_mq_do_dispatch_sched(hctx);
 | 
			
		||||
			else
 | 
			
		||||
				run_queue = blk_mq_do_dispatch_ctx(hctx);
 | 
			
		||||
				blk_mq_do_dispatch_ctx(hctx);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (has_sched_dispatch) {
 | 
			
		||||
		run_queue = blk_mq_do_dispatch_sched(hctx);
 | 
			
		||||
		blk_mq_do_dispatch_sched(hctx);
 | 
			
		||||
	} else if (q->mq_ops->get_budget) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * If we need to get budget before queuing request, we
 | 
			
		||||
| 
						 | 
				
			
			@ -233,19 +236,11 @@ bool blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
		 * TODO: get more budgets, and dequeue more requests in
 | 
			
		||||
		 * one time.
 | 
			
		||||
		 */
 | 
			
		||||
		run_queue = blk_mq_do_dispatch_ctx(hctx);
 | 
			
		||||
		blk_mq_do_dispatch_ctx(hctx);
 | 
			
		||||
	} else {
 | 
			
		||||
		blk_mq_flush_busy_ctxs(hctx, &rq_list);
 | 
			
		||||
		blk_mq_dispatch_rq_list(q, &rq_list, false);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (run_queue && !blk_mq_sched_needs_restart(hctx) &&
 | 
			
		||||
			!test_bit(BLK_MQ_S_TAG_WAITING, &hctx->state)) {
 | 
			
		||||
		blk_mq_sched_mark_restart_hctx(hctx);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ void blk_mq_sched_insert_requests(struct request_queue *q,
 | 
			
		|||
				  struct blk_mq_ctx *ctx,
 | 
			
		||||
				  struct list_head *list, bool run_queue_async);
 | 
			
		||||
 | 
			
		||||
bool blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
 | 
			
		||||
void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
 | 
			
		||||
 | 
			
		||||
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e);
 | 
			
		||||
void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1226,7 +1226,6 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
 | 
			
		|||
static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
 | 
			
		||||
{
 | 
			
		||||
	int srcu_idx;
 | 
			
		||||
	bool run_queue;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * We should be running this queue from one of the CPUs that
 | 
			
		||||
| 
						 | 
				
			
			@ -1243,18 +1242,15 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
 | 
			
		|||
 | 
			
		||||
	if (!(hctx->flags & BLK_MQ_F_BLOCKING)) {
 | 
			
		||||
		rcu_read_lock();
 | 
			
		||||
		run_queue = blk_mq_sched_dispatch_requests(hctx);
 | 
			
		||||
		blk_mq_sched_dispatch_requests(hctx);
 | 
			
		||||
		rcu_read_unlock();
 | 
			
		||||
	} else {
 | 
			
		||||
		might_sleep();
 | 
			
		||||
 | 
			
		||||
		srcu_idx = srcu_read_lock(hctx->queue_rq_srcu);
 | 
			
		||||
		run_queue = blk_mq_sched_dispatch_requests(hctx);
 | 
			
		||||
		blk_mq_sched_dispatch_requests(hctx);
 | 
			
		||||
		srcu_read_unlock(hctx->queue_rq_srcu, srcu_idx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (run_queue)
 | 
			
		||||
		blk_mq_run_hw_queue(hctx, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue