diff options
author | Andy Grover <agrover@redhat.com> | 2015-05-11 21:19:35 -0700 |
---|---|---|
committer | Andy Grover <agrover@redhat.com> | 2015-05-11 21:19:35 -0700 |
commit | 0c1daffad632973c0139340cb297604b65b20e5c (patch) | |
tree | 61af5e2b75fa4e1ceb91b623052da57fab98fb14 | |
parent | 0d34082b2f11a94f3f372e1490d7a6f179b5a820 (diff) | |
download | linux-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.c | 63 | ||||
-rw-r--r-- | include/scsi/scsi.h | 2 |
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 */ |