drivers/nvme/target/loop.c
Source file repositories/reference/linux-study-clean/drivers/nvme/target/loop.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/nvme/target/loop.c- Extension
.c- Size
- 18619 bytes
- Lines
- 724
- 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/scatterlist.hlinux/blk-mq.hlinux/nvme.hlinux/module.hlinux/parser.hnvmet.h../host/nvme.h../host/fabrics.h
Detected Declarations
struct nvme_loop_iodstruct nvme_loop_ctrlstruct nvme_loop_queueenum nvme_loop_queue_flagsfunction nvme_loop_queue_idxfunction nvme_loop_complete_rqfunction nvme_loop_queue_responsefunction nvme_loop_execute_workfunction nvme_loop_queue_rqfunction nvme_loop_submit_async_eventfunction nvme_loop_init_iodfunction nvme_loop_init_requestfunction nvme_loop_init_hctxfunction nvme_loop_init_admin_hctxfunction nvme_loop_destroy_admin_queuefunction nvme_loop_free_ctrlfunction nvme_loop_destroy_io_queuesfunction nvme_loop_init_io_queuesfunction nvme_loop_connect_io_queuesfunction nvme_loop_configure_admin_queuefunction nvme_loop_shutdown_ctrlfunction nvme_loop_delete_ctrl_hostfunction nvme_loop_delete_ctrlfunction nvme_loop_reset_ctrl_workfunction nvme_loop_create_io_queuesfunction nvme_loop_add_portfunction nvme_loop_remove_portfunction nvme_loop_init_modulefunction nvme_loop_cleanup_modulemodule init nvme_loop_init_module
Annotated Snippet
static const struct blk_mq_ops nvme_loop_mq_ops = {
.queue_rq = nvme_loop_queue_rq,
.complete = nvme_loop_complete_rq,
.init_request = nvme_loop_init_request,
.init_hctx = nvme_loop_init_hctx,
};
static const struct blk_mq_ops nvme_loop_admin_mq_ops = {
.queue_rq = nvme_loop_queue_rq,
.complete = nvme_loop_complete_rq,
.init_request = nvme_loop_init_request,
.init_hctx = nvme_loop_init_admin_hctx,
};
static void nvme_loop_destroy_admin_queue(struct nvme_loop_ctrl *ctrl)
{
if (!test_and_clear_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[0].flags))
return;
/*
* It's possible that some requests might have been added
* after admin queue is stopped/quiesced. So now start the
* queue to flush these requests to the completion.
*/
nvme_unquiesce_admin_queue(&ctrl->ctrl);
nvmet_sq_destroy(&ctrl->queues[0].nvme_sq);
nvmet_cq_put(&ctrl->queues[0].nvme_cq);
}
static void nvme_loop_free_ctrl(struct nvme_ctrl *nctrl)
{
struct nvme_loop_ctrl *ctrl = to_loop_ctrl(nctrl);
if (list_empty(&ctrl->list))
goto free_ctrl;
mutex_lock(&nvme_loop_ctrl_mutex);
list_del(&ctrl->list);
mutex_unlock(&nvme_loop_ctrl_mutex);
if (nctrl->tagset)
nvme_remove_io_tag_set(nctrl);
kfree(ctrl->queues);
nvmf_free_options(nctrl->opts);
free_ctrl:
kfree(ctrl);
}
static void nvme_loop_destroy_io_queues(struct nvme_loop_ctrl *ctrl)
{
int i;
for (i = 1; i < ctrl->ctrl.queue_count; i++) {
clear_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[i].flags);
nvmet_sq_destroy(&ctrl->queues[i].nvme_sq);
nvmet_cq_put(&ctrl->queues[i].nvme_cq);
}
ctrl->ctrl.queue_count = 1;
/*
* It's possible that some requests might have been added
* after io queue is stopped/quiesced. So now start the
* queue to flush these requests to the completion.
*/
nvme_unquiesce_io_queues(&ctrl->ctrl);
}
static int nvme_loop_init_io_queues(struct nvme_loop_ctrl *ctrl)
{
struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
unsigned int nr_io_queues;
int ret, i;
nr_io_queues = min(opts->nr_io_queues, num_online_cpus());
ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
if (ret || !nr_io_queues)
return ret;
dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n", nr_io_queues);
for (i = 1; i <= nr_io_queues; i++) {
ctrl->queues[i].ctrl = ctrl;
nvmet_cq_init(&ctrl->queues[i].nvme_cq);
ret = nvmet_sq_init(&ctrl->queues[i].nvme_sq,
&ctrl->queues[i].nvme_cq);
if (ret) {
nvmet_cq_put(&ctrl->queues[i].nvme_cq);
goto out_destroy_queues;
}
ctrl->ctrl.queue_count++;
Annotation
- Immediate include surface: `linux/scatterlist.h`, `linux/blk-mq.h`, `linux/nvme.h`, `linux/module.h`, `linux/parser.h`, `nvmet.h`, `../host/nvme.h`, `../host/fabrics.h`.
- Detected declarations: `struct nvme_loop_iod`, `struct nvme_loop_ctrl`, `struct nvme_loop_queue`, `enum nvme_loop_queue_flags`, `function nvme_loop_queue_idx`, `function nvme_loop_complete_rq`, `function nvme_loop_queue_response`, `function nvme_loop_execute_work`, `function nvme_loop_queue_rq`, `function nvme_loop_submit_async_event`.
- 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.