@@ -545,32 +545,15 @@ static int tcm_loop_write_pending(struct se_cmd *se_cmd)
return 0;
}
-static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
+static int tcm_loop_queue_data_or_status(const char *func,
+ struct se_cmd *se_cmd, u8 scsi_status)
{
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
struct tcm_loop_cmd, tl_se_cmd);
struct scsi_cmnd *sc = tl_cmd->sc;
pr_debug("%s() called for scsi_cmnd: %p cdb: 0x%02x\n",
- __func__, sc, sc->cmnd[0]);
-
- sc->result = SAM_STAT_GOOD;
- set_host_byte(sc, DID_OK);
- if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
- (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
- scsi_set_resid(sc, se_cmd->residual_count);
- sc->scsi_done(sc);
- return 0;
-}
-
-static int tcm_loop_queue_status(struct se_cmd *se_cmd)
-{
- struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
- struct tcm_loop_cmd, tl_se_cmd);
- struct scsi_cmnd *sc = tl_cmd->sc;
-
- pr_debug("%s() called for scsi_cmnd: %p cdb: 0x%02x\n",
- __func__, sc, sc->cmnd[0]);
+ func, sc, sc->cmnd[0]);
if (se_cmd->sense_buffer &&
((se_cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
@@ -581,7 +564,7 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
sc->result = SAM_STAT_CHECK_CONDITION;
set_driver_byte(sc, DRIVER_SENSE);
} else
- sc->result = se_cmd->scsi_status;
+ sc->result = scsi_status;
set_host_byte(sc, DID_OK);
if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
@@ -591,6 +574,17 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
return 0;
}
+static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
+{
+ return tcm_loop_queue_data_or_status(__func__, se_cmd, SAM_STAT_GOOD);
+}
+
+static int tcm_loop_queue_status(struct se_cmd *se_cmd)
+{
+ return tcm_loop_queue_data_or_status(__func__,
+ se_cmd, se_cmd->scsi_status);
+}
+
static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd)
{
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
We use tcm_loop with tape emulations running on tcmu. In case application reads a short tape block with a longer READ, or a long tape block with a short READ, according to SCC spec data has to be tranferred _and_ sensebytes with ILI set and information field containing the residual count. Similar problem also exists when using fixed block size in READ. Up to now tcm_loop is not prepared to handle sensebytes if input data is provided, as in tcm_loop_queue_data_in() it only sets SAM_STAT_GOOD and if necessary the residual count. To fix the bug, the same handling for sensebytes as present in tcm_loop_queue_status() must be done in tcm_loop_queue_data_in() also. After adding this handling, the two function now are nearly identical, so I created a single function with two wrappers. Signed-off-by: Bodo Stroesser <bstroesser@ts.fujitsu.com> --- drivers/target/loopback/tcm_loop.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-)