diff mbox series

target: loopback: fix READ with data and sensebytes

Message ID 20200428182617.32726-1-bstroesser@ts.fujitsu.com (mailing list archive)
State Mainlined
Commit c68a56736c129f5dd1632856956f9c3e04bae200
Headers show
Series target: loopback: fix READ with data and sensebytes | expand

Commit Message

Bodo Stroesser April 28, 2020, 6:26 p.m. UTC
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(-)

Comments

Martin K. Petersen May 12, 2020, 3:28 a.m. UTC | #1
On Tue, 28 Apr 2020 20:26:17 +0200, Bodo Stroesser wrote:

> 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.
> 
> [...]

Applied to 5.8/scsi-queue, thanks!

[1/1] scsi: target: loopback: Fix READ with data and sensebytes
      https://git.kernel.org/mkp/scsi/c/c68a56736c12
diff mbox series

Patch

diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 3305b47fdf53..16d5a4e117a2 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -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,