STRUCT NVMEFC_TGT_FCP_REQ(9)
okay so today we're doing a vibe check on struct nvmefc_tgt_fcp_req(9) β the manual page for the structure that sits between the LLDD and the NVMET-FC layer and literally holds the exchange context plus the specific FC-NVME IU operation(s) you need to perform for one FC-NVME FCP IO. it's giving "middleman with main character energy" and honestly? iconic. π
π NAME π
struct nvmefc_tgt_fcp_req β the structure used between the LLDD and the NVMET-FC layer to represent the exchange context and the specific FC-NVME IU operation(s) to perform for a FC-NVME FCP IO. yes bestie, it's the blueprint for the whole operation. no cap.
β¨ SYNOPSIS β¨
here's the struct in all its glory β every field, every type, exactly as it lives in the kernel:
struct nvmefc_tgt_fcp_req {
u8 op;
u16 hwqid;
u32 offset;
u32 timeout;
u32 transfer_length;
struct fc_ba_rjt ba_rjt;
struct scatterlist *sg;
int sg_cnt;
void *rspaddr;
dma_addr_t rspdma;
u16 rsplen;
void (*done)(struct nvmefc_tgt_fcp_req *);
void *nvmet_fc_private;
u32 transferred_length;
int fcp_error;
};
π Members π
okay so let's go through every single field one by one, because each one has a job and we respect the hustle:
opβ indicates the FCP IU operation to perform (seeNVMET_FCOP_xxx). it's the "what are we doing" field, lowkey essential.hwqidβ specifies the hw queue index (0..N-1, where N is themax_hw_queuesvalue from the LLD'snvmet_fc_target_template) that the operation is to use. so like, which queue is this op sliding into? that one.offsetβ indicates theDATA_OUT/DATA_INpayload offset to be transferred. β οΈ this field is only valid onWRITEDATA,READDATA, orREADDATA_RSPops β don't come for it otherwise, it's not for you.timeoutβ amount of time, in seconds, to wait for a response from the NVME host. a value of0is an infinite wait (so basically "bestie will wait forever"). valid only for the following ops:WRITEDATAβ caps the wait for data receptionREADDATA_RSP&RSPβ caps the wait forFCP_CONFreception (if used)
yeah it's giving "patience is a virtue" but with a timer.
transfer_lengthβ the length, in bytes, of theDATA_OUTorDATA_INpayload that is to be transferred. valid only for theWRITEDATA,READDATA, orREADDATA_RSPops. so like, how much data are we moving? this field knows.ba_rjtβ contains theBA_RJTpayload that is to be transferred. valid only for theNVMET_FCOP_BA_RJTop β it's a very specific vibe, iykyk.sgβ scatter/gather list for theDATA_OUT/DATA_INpayload data. valid only for theWRITEDATA,READDATA, orREADDATA_RSPops. this is the "where's the data at" field.sg_cntβ number of valid entries in the scatter/gather list. valid only for theWRITEDATA,READDATA, orREADDATA_RSPops. it's literally the count of how many things are in the list β no cap, just counting.rspaddrβ pointer to the FCP RSP IU buffer to be transmitted. used byRSPandREADDATA_RSPops. this is giving "here's where the response lives".rspdmaβ PCI DMA address of the FCP RSP IU buffer. used byRSPandREADDATA_RSPops. DMA address, not regular address β important distinction, bestie.rsplenβ length, in bytes, of the FCP RSP IU buffer. used byRSPandREADDATA_RSPops. so how long is the buffer? this field says.doneβ the callback routine the LLDD is to invoke upon completion of the operation. thereqargument is the pointer to the original FCP subsystem op request. this is literally the "call me when you're done" field β very main character energy.nvmet_fc_privateβ pointer to an internal NVMET-FC layer structure used as part of the NVMET-FC processing.
β οΈ the LLDD is not to reference this field β it's private, it's giving "do not disturb", okay? respect the privacy.
transferred_lengthβ amount ofDATA_OUTpayload data received by aWRITEDATAoperation. if it's not aWRITEDATAoperation, the value must be set to0. should equaltransfer_lengthon success. so like, if everything went well, this matches the transfer length β that's the vibe check.fcp_errorβ status of the FCP operation. must be0on success; on failure, it must be aNVME_SC_FC_xxxxvalue. so0is the slay, anything else is the "something went wrong" moment.
π¦ Description π¦
so the whole point of this structure is to be the go-between for the LLDD and the nvmet-fc layer, representing the exchange context for a FC-NVME FCP I/O operation β think: a nvme sqe, the sqe-related memory transfers, and its associated cqe transfer. all of it. together. in one struct. it's a lot, but it's doing it beautifully.
here's how the lifecycle goes: the structure is allocated by the LLDD whenever a FCP CMD IU is received from the FC link. the address of the structure is passed to the nvmet-fc layer via the nvmet_fc_rcv_fcp_req call. then the address of the structure gets passed back to the LLDD for the data operations and transmit of the response. the LLDD is to use the address to map back to the LLDD exchange structure, which maintains information such as the targetport the FCP I/O was received on, the remote FC NVME initiator that sent the FCP I/O, and any FC exchange context. upon completion of the FCP target operation, the address of the structure will be passed back to the FCP op done routine, allowing the nvmet-fc layer to release dma resources. upon completion of the done routine for either RSP or ABORT ops, no further access will be made by the nvmet-fc layer and the LLDD can de-allocate the structure. periodt. that's the whole arc.
field initialization: at the time of the nvmet_fc_rcv_fcp_req call, there is no content that is valid in the structure. so like, don't go reading fields before they're ready β that's not the vibe.
when the structure is used for an FCP target operation, the nvmet-fc layer will fully set the fields in order to specify the scattergather list, the transfer length, as well as the done routine to be called upon completion of the operation. the nvmet-fc layer will also set a private pointer for its own use in the done routine.
values set by the NVMET-FC layer prior to calling the LLDD fcp_op entrypoint.
values set by the LLDD indicating completion status of the FCP operation. must be set prior to calling the done callback. so like, don't call done before you've set these β that's rude and also incorrect.
π SEE ALSO π
check out these other icons and the kernel file they live in β they're all connected, no cap:
- kernel file
./include/linux/nvme-fc-driver.h struct nvmefc_ls_req(9)struct nvmefc_ls_rsp(9)struct nvme_fc_port_info(9)struct nvmefc_fcp_req(9)struct nvme_fc_local_port(9)struct nvme_fc_remote_port(9)struct nvme_fc_port_template(9)struct nvmet_fc_port_info(9)struct nvmet_fc_target_port(9)struct nvmet_fc_target_template(9)
alright bestie, that's the whole page. source is ./include/linux, dated October 2026, and the manual name is struct nvmefc_tgt_fcp_req(9). hope this made the kernel a little less scary and a little more slay π«Άπβ¨
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms