[PATCH v2] target: transport should allow st ILI reads

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
assume 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 the ILI, EOM,
or FM bits set, with a sense code of NO_SENSE,
treating such cases as if there is no sense data
and the read succeeded. The layered tape driver then
"does the right thing" when it gets such a response.

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

Signed-off-by: Lee Duncan <lduncan@xxxxxxxx>
---
 drivers/target/target_core_pscsi.c     | 22 +++++++++++++++++++++-
 drivers/target/target_core_transport.c |  6 ++++++
 include/target/target_core_base.h      |  1 +
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 0d99b242e82e..b237104af81c 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -689,8 +689,28 @@ 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);
+
+		/*
+		 * hack to 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 */
+				cmd->se_cmd_flags |= SCF_TREAT_READ_AS_NORMAL;
+			}
+		}
+	}
 }
 
 enum {
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 74b646f165d4..56661a824266 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2192,6 +2192,11 @@ static void target_complete_ok_work(struct work_struct *work)
 	if (atomic_read(&cmd->se_dev->dev_qf_count) != 0)
 		schedule_work(&cmd->se_dev->qf_work_queue);
 
+	if (cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) {
+		pr_debug("Tape FM/EOM/ILI status detected. Treating as OK\n");
+		goto treat_as_normal_read;
+	}
+
 	/*
 	 * Check if we need to send a sense buffer from
 	 * the struct se_cmd in question.
@@ -2241,6 +2246,7 @@ static void target_complete_ok_work(struct work_struct *work)
 		if (cmd->scsi_status)
 			goto queue_status;
 
+treat_as_normal_read:
 		atomic_long_add(cmd->data_length,
 				&cmd->se_lun->lun_stats.tx_data_octets);
 		/*
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 9f9f5902af38..922a39f45abc 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -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,
 };
 
 /*
-- 
2.13.6




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux