[PATCH 1/5] nvmet-fc: only send read data for successful commands
From: Andrea Parri
Date: Mon Oct 12 2026 - 10:55:51 EST
When a read command completes with an error,
__nvmet_fc_fcp_nvme_cmd_done() still pushes the whole data buffer to
the host before the response. nvmet_fc_alloc_tgt_pgs() allocates that
buffer with sgl_alloc() and no __GFP_ZERO, and a command rejected by
nvmet_check_transfer_len() leaves it untouched, so the host receives
stale target memory.
The buffer is as large as the data length in the command IU, so the
amount of stale memory returned is up to the host.
The tcp and rdma targets send data only when cqe->status is zero (see
nvmet_tcp_need_data_out() and nvmet_rdma_need_data_out()), so no nvmet
command can rely on returning data with an error status. Do the same
for fc. The ERSP then reports a transferred length of fod->offset,
which is 0, matching what nvme_fc_fcpio_done() checks on the host.
Tested over nvme-fcloop: a failed read command no longer transfers
data and still completes with its error status, and successful reads
are unaffected.
Fixes: c53432030d86 ("nvme-fabrics: Add target support for FC transport")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Andrea Parri <parri.andrea@xxxxxxxxx>
---
drivers/nvme/target/fc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index 1b557775e033a..44bbc7d26f07d 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -2484,11 +2484,11 @@ __nvmet_fc_fcp_nvme_cmd_done(struct nvmet_fc_tgtport *tgtport,
} else {
/*
- * try to push the data even if the SQE status is non-zero.
- * There may be a status where data still was intended to
- * be moved
+ * A failed command may not have filled its read buffer, so
+ * only push data for success, as the tcp and rdma targets do.
*/
- if ((fod->io_dir == NVMET_FCP_READ) && (fod->data_sg_cnt)) {
+ if (fod->io_dir == NVMET_FCP_READ && fod->data_sg_cnt &&
+ !cqe->status) {
/* push the data over before sending rsp */
nvmet_fc_transfer_fcp_data(tgtport, fod,
NVMET_FCOP_READDATA);
--
2.53.0