block/blk-mq.c
Source file repositories/reference/linux-study-clean/block/blk-mq.c
File Facts
- System
- Linux kernel
- Corpus path
block/blk-mq.c- Extension
.c- Size
- 136727 bytes
- Lines
- 5301
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: operation-table or driver-model contract
- Status
- pattern 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- 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/backing-dev.hlinux/bio.hlinux/blkdev.hlinux/blk-integrity.hlinux/kmemleak.hlinux/mm.hlinux/init.hlinux/slab.hlinux/workqueue.hlinux/smp.hlinux/interrupt.hlinux/llist.hlinux/cpu.hlinux/cache.hlinux/sched/topology.hlinux/sched/signal.hlinux/suspend.hlinux/delay.hlinux/crash_dump.hlinux/prefetch.hlinux/blk-crypto.hlinux/part_stat.hlinux/sched/isolation.htrace/events/block.hlinux/t10-pi.hblk.hblk-mq.hblk-mq-debugfs.hblk-pm.hblk-stat.h
Detected Declarations
struct mq_inflightstruct blk_rq_waitstruct blk_expired_datastruct flush_busy_ctx_datastruct dispatch_rq_datastruct rq_iter_dataenum prep_dispatchfunction blk_mq_hctx_has_pendingfunction blk_mq_hctx_mark_pendingfunction blk_mq_hctx_clear_pendingfunction blk_mq_check_in_driverfunction blk_mq_in_driver_rwfunction blk_freeze_set_ownerfunction blk_unfreeze_check_ownerfunction blk_freeze_set_ownerfunction blk_unfreeze_check_ownerfunction __blk_freeze_queue_startfunction blk_freeze_queue_startfunction blk_mq_freeze_queue_waitfunction blk_mq_freeze_queue_wait_timeoutfunction blk_mq_freeze_queue_nomemsavefunction __blk_mq_unfreeze_queuefunction blk_mq_unfreeze_queue_nomemrestorefunction blk_freeze_queue_start_non_ownerfunction blk_mq_unfreeze_queue_non_ownerfunction blk_mq_quiesce_queue_nowaitfunction blk_mq_wait_quiesce_donefunction blk_mq_quiesce_queuefunction blk_mq_unquiesce_queuefunction blk_mq_quiesce_tagsetfunction blk_mq_unquiesce_tagsetfunction blk_mq_wake_waitersfunction blk_rq_initfunction blk_mq_rq_time_initfunction blk_mq_bio_issue_initfunction __blk_mq_alloc_requests_batchfunction blk_mq_limit_depthfunction blk_mq_finish_requestfunction __blk_mq_free_requestfunction blk_mq_free_requestfunction blk_mq_free_plug_rqsfunction blk_dump_rq_flagsfunction blk_account_io_completionfunction blk_print_req_errorfunction blk_complete_requestfunction blk_rq_bytesfunction blk_account_io_donefunction blk_account_io_start
Annotated Snippet
* more requests. (See comment in struct blk_mq_ops for commit_rqs for
* details)
* Attention, we should explicitly call this in unusual cases:
* 1) did not queue everything initially scheduled to queue
* 2) the last attempt to queue a request failed
*/
static void blk_mq_commit_rqs(struct blk_mq_hw_ctx *hctx, int queued,
bool from_schedule)
{
if (hctx->queue->mq_ops->commit_rqs && queued) {
trace_block_unplug(hctx->queue, queued, !from_schedule);
hctx->queue->mq_ops->commit_rqs(hctx);
}
}
/*
* Returns true if we did some work AND can potentially do more.
*/
bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
bool get_budget)
{
enum prep_dispatch prep;
struct request_queue *q = hctx->queue;
struct request *rq;
int queued;
blk_status_t ret = BLK_STS_OK;
bool needs_resource = false;
if (list_empty(list))
return false;
/*
* Now process all the entries, sending them to the driver.
*/
queued = 0;
do {
struct blk_mq_queue_data bd;
rq = list_first_entry(list, struct request, queuelist);
WARN_ON_ONCE(hctx != rq->mq_hctx);
prep = blk_mq_prep_dispatch_rq(rq, get_budget);
if (prep != PREP_DISPATCH_OK)
break;
list_del_init(&rq->queuelist);
bd.rq = rq;
bd.last = list_empty(list);
ret = q->mq_ops->queue_rq(hctx, &bd);
switch (ret) {
case BLK_STS_OK:
queued++;
break;
case BLK_STS_RESOURCE:
needs_resource = true;
fallthrough;
case BLK_STS_DEV_RESOURCE:
blk_mq_handle_dev_resource(rq, list);
goto out;
default:
blk_mq_end_request(rq, ret);
}
} while (!list_empty(list));
out:
/* If we didn't flush the entire list, we could have told the driver
* there was more coming, but that turned out to be a lie.
*/
if (!list_empty(list) || ret != BLK_STS_OK)
blk_mq_commit_rqs(hctx, queued, false);
/*
* Any items that need requeuing? Stuff them into hctx->dispatch,
* that is where we will continue on next queue run.
*/
if (!list_empty(list)) {
bool needs_restart;
/* For non-shared tags, the RESTART check will suffice */
bool no_tag = prep == PREP_DISPATCH_NO_TAG &&
((hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED) ||
blk_mq_is_shared_tags(hctx->flags));
/*
* If the caller allocated budgets, free the budgets of the
* requests that have not yet been passed to the block driver.
*/
if (!get_budget)
blk_mq_release_budgets(q, list);
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/backing-dev.h`, `linux/bio.h`, `linux/blkdev.h`, `linux/blk-integrity.h`, `linux/kmemleak.h`, `linux/mm.h`.
- Detected declarations: `struct mq_inflight`, `struct blk_rq_wait`, `struct blk_expired_data`, `struct flush_busy_ctx_data`, `struct dispatch_rq_data`, `struct rq_iter_data`, `enum prep_dispatch`, `function blk_mq_hctx_has_pending`, `function blk_mq_hctx_mark_pending`, `function blk_mq_hctx_clear_pending`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: pattern 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.