Skip to contentSkip to conversation

target: transport should handle st FM/EOM/ILI reads

PATCH Applied Lee Duncan 2 participants 2 messages May 16, 2018 – May 18, 2018 SCSI target

lore
Share & tools
lore

Lee Duncan

author
#0 lore raw

PATCH v4 1/1 target: transport should handle st FM/EOM/ILI reads

When a tape drive is exported via LIO using the pscsi module, a read that requests more bytes per block than the tape can supply returns an empty buffer. This is because the pscsi pass-through target module sees the "ILI" illegal length bit set and thinks there is no reason to return the data.

This is a long-standing transport issue, since it assumes that no data need be returned under a check condition, which isn't always the case for tape.

Add in a check for tape reads with the ILI, EOM, or FM bits set, with a sense code of NO_SENSE, treating such cases as if the read succeeded. The layered tape driver then "does the right thing" when it gets such a response.

Changes from v3:
- cleaned up comment
- Added residual handling

Changes from v2:
- Cleaned up subject line and bug text formatting
- Removed unneeded inner braces
- Removed ugly goto
- Also updated the "queue full" path to handle this case

Changes from RFC:
- Moved ugly code from transport to pscsi module
- Added checking EOM and FM bits, as well as ILI
- fixed malformed patch
- Clarified description a bit

---
 drivers/target/target_core_pscsi.c     | 26 ++++++++++++++++++--
 drivers/target/target_core_transport.c | 43 +++++++++++++++++++++++++++++-----
 include/target/target_core_base.h      |  1 +
 3 files changed, 62 insertions(+), 8 deletions(-)
drivers/target/target_core_pscsi.c +24 -2
index 0d99b242e82e..f31215b1d009 100644
@@ -689,8 +689,29 @@ static void pscsi_complete_cmd(struct se_cmd *cmd, u8 scsi_status,
 	}
 after_mode_select:
 
-	if (scsi_status = SAM_STAT_CHECK_CONDITION)
+	if (scsi_status = SAM_STAT_CHECK_CONDITION) {
 		transport_copy_sense_to_cmd(cmd, req_sense);
+
+		/*
+		 * check for TAPE device reads with
+		 * FM/EOM/ILI set, so that we can get data
+		 * back despite framework assumption that a
+		 * check condition means there is no data
+		 */
+		if (sd->type = TYPE_TAPE &&
+		    cmd->data_direction = DMA_FROM_DEVICE) {
+			/*
+			 * is sense data valid, fixed format,
+			 * and have FM, EOM, or ILI set?
+			 */
+			if (req_sense[0] = 0xf0 &&	/* valid, fixed format */
+			    req_sense[2] & 0xe0 &&	/* FM, EOM, or ILI */
+			    (req_sense[2] & 0xf) = 0) { /* key=NO_SENSE */
+				pr_debug("Tape FM/EOM/ILI status detected. Treat as normal read.\n");
+				cmd->se_cmd_flags |= SCF_TREAT_READ_AS_NORMAL;
+			}
+		}
+	}
 }
 
 enum {
@@ -1061,7 +1082,8 @@ static void pscsi_req_done(struct request *req, blk_status_t status)
 
 	switch (host_byte(result)) {
 	case DID_OK:
-		target_complete_cmd(cmd, scsi_status);
+		target_complete_cmd_with_length(cmd, scsi_status,
+			cmd->data_length - scsi_req(req)->resid_len);
 		break;
 	default:
 		pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
drivers/target/target_core_transport.c +37 -6

72 lines not on this page · raw message

include/target/target_core_base.h +1 -0
index 9f9f5902af38..922a39f45abc 100644
@@ -143,6 +143,7 @@ enum se_cmd_flags_table {
 	SCF_ACK_KREF			= 0x00400000,
 	SCF_USE_CPUID			= 0x00800000,
 	SCF_TASK_ATTR_SET		= 0x01000000,
+	SCF_TREAT_READ_AS_NORMAL	= 0x02000000,
 };
 
 /*
Signature · 1 line
2.13.6
#1 lore raw

Lee,

Quoted 5 lines

When a tape drive is exported via LIO using the pscsi module, a read that requests more bytes per block than the tape can supply returns an empty buffer. This is because the pscsi pass-through target module sees the "ILI" illegal length bit set and thinks there is no reason to return the data.

Applied to 4.18/scsi-queue. Thank you!

Signature · 1 line
Martin K. Petersen	Oracle Linux Engineering