drivers/target/loopback/tcm_loop.c
Source file repositories/reference/linux-study-clean/drivers/target/loopback/tcm_loop.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/target/loopback/tcm_loop.c- Extension
.c- Size
- 30122 bytes
- Lines
- 1142
- Domain
- Driver Families
- Bucket
- drivers/target
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- 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/module.hlinux/moduleparam.hlinux/init.hlinux/slab.hlinux/types.hlinux/configfs.hlinux/blk-mq.hscsi/scsi.hscsi/scsi_tcq.hscsi/scsi_host.hscsi/scsi_device.hscsi/scsi_cmnd.htarget/target_core_base.htarget/target_core_fabric.htcm_loop.h
Detected Declarations
function tcm_loop_check_stop_freefunction tcm_loop_release_cmdfunction tcm_loop_show_infofunction tcm_loop_target_queue_cmdfunction tcm_loop_make_naa_tpgfunction scsi_get_prot_opfunction tcm_loop_queuecommandfunction tcm_loop_issue_tmrfunction tcm_loop_abort_taskfunction tcm_loop_device_resetfunction tcm_loop_driver_probefunction tcm_loop_driver_removefunction tcm_loop_release_adapterfunction tcm_loop_make_scsi_hbafunction tcm_loop_fabric_initfunction tcm_loop_release_core_busfunction tcm_loop_get_tagfunction Returningfunction tcm_loop_check_prot_fabric_onlyfunction tcm_loop_sess_get_indexfunction tcm_loop_get_cmd_statefunction tcm_loop_write_pendingfunction tcm_loop_queue_data_or_statusfunction tcm_loop_queue_data_infunction tcm_loop_queue_statusfunction tcm_loop_queue_tm_rspfunction tcm_loop_aborted_taskfunction tcm_loop_port_linkfunction tcm_loop_port_unlinkfunction tcm_loop_tpg_attrib_fabric_prot_type_showfunction tcm_loop_tpg_attrib_fabric_prot_type_storefunction tcm_loop_alloc_sess_cbfunction tcm_loop_make_nexusfunction tcm_loop_drop_nexusfunction tcm_loop_tpg_nexus_showfunction tcm_loop_tpg_nexus_storefunction tcm_loop_make_scsi_hbafunction tcm_loop_tpg_transport_status_showfunction tcm_loop_tpg_transport_status_storefunction tcm_loop_tpg_address_showfunction tcm_loop_drop_naa_tpgfunction tcm_loop_drop_scsi_hbafunction tcm_loop_wwn_version_showfunction tcm_loop_fabric_initfunction tcm_loop_fabric_exitmodule init tcm_loop_fabric_init
Annotated Snippet
static const struct bus_type tcm_loop_lld_bus = {
.name = "tcm_loop_bus",
.probe = tcm_loop_driver_probe,
.remove = tcm_loop_driver_remove,
};
static struct device_driver tcm_loop_driverfs = {
.name = "tcm_loop",
.bus = &tcm_loop_lld_bus,
};
/*
* Used with root_device_register() in tcm_loop_alloc_core_bus() below
*/
static struct device *tcm_loop_primary;
static void tcm_loop_target_queue_cmd(struct tcm_loop_cmd *tl_cmd)
{
struct se_cmd *se_cmd = &tl_cmd->tl_se_cmd;
struct scsi_cmnd *sc = tl_cmd->sc;
struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_hba *tl_hba;
struct tcm_loop_tpg *tl_tpg;
struct scatterlist *sgl_bidi = NULL;
u32 sgl_bidi_count = 0, transfer_length;
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
/*
* Ensure that this tl_tpg reference from the incoming sc->device->id
* has already been configured via tcm_loop_make_naa_tpg().
*/
if (!tl_tpg->tl_hba) {
set_host_byte(sc, DID_NO_CONNECT);
goto out_done;
}
if (tl_tpg->tl_transport_status == TCM_TRANSPORT_OFFLINE) {
set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
goto out_done;
}
tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus) {
scmd_printk(KERN_ERR, sc,
"TCM_Loop I_T Nexus does not exist\n");
set_host_byte(sc, DID_ERROR);
goto out_done;
}
transfer_length = scsi_transfer_length(sc);
if (!scsi_prot_sg_count(sc) &&
scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) {
se_cmd->prot_pto = true;
/*
* loopback transport doesn't support
* WRITE_GENERATE, READ_STRIP protection
* information operations, go ahead unprotected.
*/
transfer_length = scsi_bufflen(sc);
}
se_cmd->tag = tl_cmd->sc_cmd_tag;
target_init_cmd(se_cmd, tl_nexus->se_sess, &tl_cmd->tl_sense_buf[0],
tl_cmd->sc->device->lun, transfer_length,
TCM_SIMPLE_TAG, sc->sc_data_direction, 0);
if (target_submit_prep(se_cmd, sc->cmnd, scsi_sglist(sc),
scsi_sg_count(sc), sgl_bidi, sgl_bidi_count,
scsi_prot_sglist(sc), scsi_prot_sg_count(sc),
GFP_ATOMIC))
return;
target_submit(se_cmd);
return;
out_done:
scsi_done(sc);
}
/*
* ->queuecommand can be and usually is called from interrupt context, so
* defer the actual submission to a workqueue.
*/
static enum scsi_qc_status tcm_loop_queuecommand(struct Scsi_Host *sh,
struct scsi_cmnd *sc)
{
struct tcm_loop_cmd *tl_cmd = scsi_cmd_priv(sc);
pr_debug("%s() %d:%d:%d:%llu got CDB: 0x%02x scsi_buf_len: %u\n",
__func__, sc->device->host->host_no, sc->device->id,
sc->device->channel, sc->device->lun, sc->cmnd[0],
Annotation
- Immediate include surface: `linux/module.h`, `linux/moduleparam.h`, `linux/init.h`, `linux/slab.h`, `linux/types.h`, `linux/configfs.h`, `linux/blk-mq.h`, `scsi/scsi.h`.
- Detected declarations: `function tcm_loop_check_stop_free`, `function tcm_loop_release_cmd`, `function tcm_loop_show_info`, `function tcm_loop_target_queue_cmd`, `function tcm_loop_make_naa_tpg`, `function scsi_get_prot_op`, `function tcm_loop_queuecommand`, `function tcm_loop_issue_tmr`, `function tcm_loop_abort_task`, `function tcm_loop_device_reset`.
- Atlas domain: Driver Families / drivers/target.
- 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.