aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Grover <agrover@redhat.com>2015-05-11 21:19:35 -0700
committerAndy Grover <agrover@redhat.com>2015-05-11 21:19:35 -0700
commit0c1daffad632973c0139340cb297604b65b20e5c (patch)
tree61af5e2b75fa4e1ceb91b623052da57fab98fb14
parent0d34082b2f11a94f3f372e1490d7a6f179b5a820 (diff)
downloadlinux-tcmu-iomode-option7.tar.gz
target/user: Avoid calling sbc_parse_cdb for all non-emulated opstcmu-iomode-option7
Only call sbc_parse_cdb for ops we want emulated. For the rest, set execute_cmd to pass them to userspace. Signed-off-by: Andy Grover <agrover@redhat.com>
-rw-r--r--drivers/target/target_core_user.c63
-rw-r--r--include/scsi/scsi.h2
2 files changed, 65 insertions, 0 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 0e0feeaec39c2..ebcbbd898c65f 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -21,6 +21,7 @@
#include <linux/idr.h>
#include <linux/timer.h>
#include <linux/parser.h>
+#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <linux/uio_driver.h>
@@ -1048,9 +1049,71 @@ static struct sbc_ops tcmu_sbc_ops = {
.execute_unmap = tcmu_pass_op,
};
+/*
+ * Clear a lun set in the cdb if the initiator talking to use spoke
+ * and old standards version, as we can't assume the underlying device
+ * won't choke up on it.
+ * Copied from pscsi.
+ */
+static inline void tcmu_clear_cdb_lun(unsigned char *cdb)
+{
+ switch (cdb[0]) {
+ case READ_10: /* SBC - RDProtect */
+ case READ_12: /* SBC - RDProtect */
+ case READ_16: /* SBC - RDProtect */
+ case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
+ case VERIFY: /* SBC - VRProtect */
+ case VERIFY_16: /* SBC - VRProtect */
+ case WRITE_VERIFY: /* SBC - VRProtect */
+ case WRITE_VERIFY_12: /* SBC - VRProtect */
+ case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
+ break;
+ default:
+ cdb[1] &= 0x1f; /* clear logical unit number */
+ break;
+ }
+}
+
static sense_reason_t
tcmu_parse_cdb(struct se_cmd *cmd)
{
+ unsigned char *cdb = cmd->t_task_cdb;
+
+ tcmu_clear_cdb_lun(cdb);
+
+ switch (cdb[0]) {
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case READ_16:
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
+ case WRITE_VERIFY:
+ case WRITE_VERIFY_12:
+ case WRITE_VERIFY_16:
+ case WRITE_SAME:
+ case WRITE_SAME_16:
+ case SYNCHRONIZE_CACHE:
+ case SYNCHRONIZE_CACHE_16:
+ case COMPARE_AND_WRITE:
+ cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+ cmd->execute_cmd = tcmu_pass_op;
+ return TCM_NO_SENSE;
+ case VARIABLE_LENGTH_CMD:
+ switch (get_unaligned_be16(&cdb[8])) {
+ case READ_32:
+ case WRITE_32:
+ case WRITE_VERIFY_32:
+ case WRITE_SAME_32:
+ cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+ cmd->execute_cmd = tcmu_pass_op;
+ return TCM_NO_SENSE;
+ }
+ }
+
+ /* TCMU in I/O mode uses LIO core to emulate all other SCSI ops */
return sbc_parse_cdb(cmd, &tcmu_sbc_ops);
}
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index d0a66aa1868d2..67811121ade15 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -150,6 +150,7 @@ enum scsi_timeouts {
#define WRITE_16 0x8a
#define READ_ATTRIBUTE 0x8c
#define WRITE_ATTRIBUTE 0x8d
+#define WRITE_VERIFY_16 0x8e
#define VERIFY_16 0x8f
#define SYNCHRONIZE_CACHE_16 0x91
#define WRITE_SAME_16 0x93
@@ -189,6 +190,7 @@ enum scsi_timeouts {
#define READ_32 0x09
#define VERIFY_32 0x0a
#define WRITE_32 0x0b
+#define WRITE_VERIFY_32 0x0c
#define WRITE_SAME_32 0x0d
/* Values for T10/04-262r7 */