Commit 4347ab5a authored by Nicholas Bellinger's avatar Nicholas Bellinger

target: Avoid DataIN transfers for non-GOOD SAM status

This patch modifies existing transport_complete_*() code
to avoid invoking target_core_fabric_ops->queue_data_in()
driver callbacks for I/O READs with non-GOOD SAM status.

Some initiators expect GOOD status when a DATA-IN payload
transfer is involved, so to be safe go ahead and always
invoke target_core_fabric_ops->queue_status() to generate
fabric responses instead.

Note this is a prerequisite for IBLOCK supporting retriable
status, so SAM_STAT_BUSY + SAM_STAT_TASK_SET_FULL always
generates fabric driver responses instead of initiating
DataIN payload transfer when non-GOOD status is present
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Andy Grover <agrover@redhat.com>
Cc: Mike Christie <mchristi@redhat.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 32c76de3
...@@ -1997,6 +1997,9 @@ static void transport_complete_qf(struct se_cmd *cmd) ...@@ -1997,6 +1997,9 @@ static void transport_complete_qf(struct se_cmd *cmd)
switch (cmd->data_direction) { switch (cmd->data_direction) {
case DMA_FROM_DEVICE: case DMA_FROM_DEVICE:
if (cmd->scsi_status)
goto queue_status;
trace_target_cmd_complete(cmd); trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_data_in(cmd); ret = cmd->se_tfo->queue_data_in(cmd);
break; break;
...@@ -2007,6 +2010,7 @@ static void transport_complete_qf(struct se_cmd *cmd) ...@@ -2007,6 +2010,7 @@ static void transport_complete_qf(struct se_cmd *cmd)
} }
/* Fall through for DMA_TO_DEVICE */ /* Fall through for DMA_TO_DEVICE */
case DMA_NONE: case DMA_NONE:
queue_status:
trace_target_cmd_complete(cmd); trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_status(cmd); ret = cmd->se_tfo->queue_status(cmd);
break; break;
...@@ -2128,6 +2132,9 @@ static void target_complete_ok_work(struct work_struct *work) ...@@ -2128,6 +2132,9 @@ static void target_complete_ok_work(struct work_struct *work)
queue_rsp: queue_rsp:
switch (cmd->data_direction) { switch (cmd->data_direction) {
case DMA_FROM_DEVICE: case DMA_FROM_DEVICE:
if (cmd->scsi_status)
goto queue_status;
atomic_long_add(cmd->data_length, atomic_long_add(cmd->data_length,
&cmd->se_lun->lun_stats.tx_data_octets); &cmd->se_lun->lun_stats.tx_data_octets);
/* /*
...@@ -2167,6 +2174,7 @@ static void target_complete_ok_work(struct work_struct *work) ...@@ -2167,6 +2174,7 @@ static void target_complete_ok_work(struct work_struct *work)
} }
/* Fall through for DMA_TO_DEVICE */ /* Fall through for DMA_TO_DEVICE */
case DMA_NONE: case DMA_NONE:
queue_status:
trace_target_cmd_complete(cmd); trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_status(cmd); ret = cmd->se_tfo->queue_status(cmd);
if (ret == -EAGAIN || ret == -ENOMEM) if (ret == -EAGAIN || ret == -ENOMEM)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment