block/blk-mq-sched.c
Source file repositories/reference/linux-study-clean/block/blk-mq-sched.c
File Facts
- System
- Linux kernel
- Corpus path
block/blk-mq-sched.c- Extension
.c- Size
- 17679 bytes
- Lines
- 707
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kernel.hlinux/module.hlinux/list_sort.htrace/events/block.hblk.hblk-mq.hblk-mq-debugfs.hblk-mq-sched.hblk-wbt.h
Detected Declarations
function Copyrightfunction __blk_mq_sched_restartfunction sched_rq_cmpfunction blk_mq_dispatch_hctx_listfunction list_for_each_entryfunction __blk_mq_do_dispatch_schedfunction blk_mq_do_dispatch_schedfunction blk_mq_do_dispatch_ctxfunction __blk_mq_sched_dispatch_requestsfunction blk_mq_sched_dispatch_requestsfunction blk_mq_sched_bio_mergefunction blk_mq_sched_try_insert_mergefunction blk_mq_sched_tags_teardownfunction blk_mq_sched_reg_debugfsfunction blk_mq_sched_unreg_debugfsfunction blk_mq_free_sched_tagsfunction blk_mq_free_sched_resfunction blk_mq_free_sched_res_batchfunction list_for_each_entryfunction blk_mq_free_sched_ctx_batchfunction xa_for_eachfunction blk_mq_alloc_sched_ctx_batchfunction list_for_each_entryfunction blk_mq_alloc_sched_resfunction blk_mq_alloc_sched_res_batchfunction list_for_each_entryfunction blk_mq_init_schedfunction queue_for_each_hw_ctxfunction queue_for_each_hw_ctxfunction blk_mq_sched_free_rqsfunction queue_for_each_hw_ctxfunction blk_mq_exit_schedfunction queue_for_each_hw_ctxexport blk_mq_sched_mark_restart_hctxexport blk_mq_sched_try_insert_merge
Annotated Snippet
if (rq->mq_hctx != hctx) {
list_cut_before(&hctx_list, rq_list, &rq->queuelist);
goto dispatch;
}
}
list_splice_tail_init(rq_list, &hctx_list);
dispatch:
return blk_mq_dispatch_rq_list(hctx, &hctx_list, false);
}
#define BLK_MQ_BUDGET_DELAY 3 /* ms units */
/*
* 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() fails to get the budget.
*
* Returns -EAGAIN if hctx->dispatch was found non-empty and run_work has to
* be run again. This is necessary to avoid starving flushes.
*/
static int __blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
{
struct request_queue *q = hctx->queue;
struct elevator_queue *e = q->elevator;
bool multi_hctxs = false, run_queue = false;
bool dispatched = false, busy = false;
unsigned int max_dispatch;
LIST_HEAD(rq_list);
int count = 0;
if (hctx->dispatch_busy)
max_dispatch = 1;
else
max_dispatch = hctx->queue->nr_requests;
do {
struct request *rq;
int budget_token;
if (e->type->ops.has_work && !e->type->ops.has_work(hctx))
break;
if (!list_empty_careful(&hctx->dispatch)) {
busy = true;
break;
}
budget_token = blk_mq_get_dispatch_budget(q);
if (budget_token < 0)
break;
rq = e->type->ops.dispatch_request(hctx);
if (!rq) {
blk_mq_put_dispatch_budget(q, budget_token);
/*
* We're releasing without dispatching. Holding the
* budget could have blocked any "hctx"s with the
* same queue and if we didn't dispatch then there's
* no guarantee anyone will kick the queue. Kick it
* ourselves.
*/
run_queue = true;
break;
}
blk_mq_set_rq_budget_token(rq, budget_token);
/*
* Now this rq owns the budget which has to be released
* if this rq won't be queued to driver via .queue_rq()
* in blk_mq_dispatch_rq_list().
*/
list_add_tail(&rq->queuelist, &rq_list);
count++;
if (rq->mq_hctx != hctx)
multi_hctxs = true;
/*
* If we cannot get tag for the request, stop dequeueing
* requests from the IO scheduler. We are unlikely to be able
* to submit them anyway and it creates false impression for
* scheduling heuristics that the device can take more IO.
*/
if (!blk_mq_get_driver_tag(rq))
break;
} while (count < max_dispatch);
if (!count) {
if (run_queue)
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/list_sort.h`, `trace/events/block.h`, `blk.h`, `blk-mq.h`, `blk-mq-debugfs.h`, `blk-mq-sched.h`.
- Detected declarations: `function Copyright`, `function __blk_mq_sched_restart`, `function sched_rq_cmp`, `function blk_mq_dispatch_hctx_list`, `function list_for_each_entry`, `function __blk_mq_do_dispatch_sched`, `function blk_mq_do_dispatch_sched`, `function blk_mq_do_dispatch_ctx`, `function __blk_mq_sched_dispatch_requests`, `function blk_mq_sched_dispatch_requests`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.