STRUCT NVMEFC_TGT_FCP_REQ(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

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 (see NVMET_FCOP_xxx). it's the "what are we doing" field, lowkey essential.
  • hwqid β€” specifies the hw queue index (0..N-1, where N is the max_hw_queues value from the LLD's nvmet_fc_target_template) that the operation is to use. so like, which queue is this op sliding into? that one.
  • offset β€” indicates the DATA_OUT/DATA_IN payload offset to be transferred. ⚠️ this field is only valid on WRITEDATA, READDATA, or READDATA_RSP ops β€” 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 of 0 is an infinite wait (so basically "bestie will wait forever"). valid only for the following ops:
    • WRITEDATA β€” caps the wait for data reception
    • READDATA_RSP & RSP β€” caps the wait for FCP_CONF reception (if used)

yeah it's giving "patience is a virtue" but with a timer.

  • transfer_length β€” the length, in bytes, of the DATA_OUT or DATA_IN payload that is to be transferred. valid only for the WRITEDATA, READDATA, or READDATA_RSP ops. so like, how much data are we moving? this field knows.
  • ba_rjt β€” contains the BA_RJT payload that is to be transferred. valid only for the NVMET_FCOP_BA_RJT op β€” it's a very specific vibe, iykyk.
  • sg β€” scatter/gather list for the DATA_OUT/DATA_IN payload data. valid only for the WRITEDATA, READDATA, or READDATA_RSP ops. this is the "where's the data at" field.
  • sg_cnt β€” number of valid entries in the scatter/gather list. valid only for the WRITEDATA, READDATA, or READDATA_RSP ops. 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 by RSP and READDATA_RSP ops. this is giving "here's where the response lives".
  • rspdma β€” PCI DMA address of the FCP RSP IU buffer. used by RSP and READDATA_RSP ops. DMA address, not regular address β€” important distinction, bestie.
  • rsplen β€” length, in bytes, of the FCP RSP IU buffer. used by RSP and READDATA_RSP ops. so how long is the buffer? this field says.
  • done β€” the callback routine the LLDD is to invoke upon completion of the operation. the req argument 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 of DATA_OUT payload data received by a WRITEDATA operation. if it's not a WRITEDATA operation, the value must be set to 0. should equal transfer_length on 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 be 0 on success; on failure, it must be a NVME_SC_FC_xxxx value. so 0 is 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