aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Grover <agrover@redhat.com>2015-05-19 17:44:40 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-05-30 22:57:59 -0400
commit7bfea53b5c936d706d0bf60ec218fa72cde77121 (patch)
tree1bed6667ac527acab7c2b2fb72e2bb1aa7b4cca5
parent9c1cd1b68cd15c81d12a0cf2402129475882b620 (diff)
target: Move passthrough CDB parsing into a common function
Aside from whether they handle BIDI ops or not, parsing of the CDB by kernel and user SCSI passthrough modules should be identical. Move this into a new passthrough_parse_cdb() and call it from tcm-pscsi and tcm-user. Reported-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Ilias Tsitsimpis <iliastsi@arrikto.com> Signed-off-by: Andy Grover <agrover@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_device.c74
-rw-r--r--drivers/target/target_core_pscsi.c53
-rw-r--r--drivers/target/target_core_user.c43
-rw-r--r--include/target/target_core_backend.h2
4 files changed, 78 insertions, 94 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 7faa6aef9a4d..56b20dc54087 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -33,6 +33,7 @@
33#include <linux/kthread.h> 33#include <linux/kthread.h>
34#include <linux/in.h> 34#include <linux/in.h>
35#include <linux/export.h> 35#include <linux/export.h>
36#include <asm/unaligned.h>
36#include <net/sock.h> 37#include <net/sock.h>
37#include <net/tcp.h> 38#include <net/tcp.h>
38#include <scsi/scsi.h> 39#include <scsi/scsi.h>
@@ -1707,3 +1708,76 @@ void core_dev_release_virtual_lun0(void)
1707 target_free_device(g_lun0_dev); 1708 target_free_device(g_lun0_dev);
1708 core_delete_hba(hba); 1709 core_delete_hba(hba);
1709} 1710}
1711
1712/*
1713 * Common CDB parsing for kernel and user passthrough.
1714 */
1715sense_reason_t
1716passthrough_parse_cdb(struct se_cmd *cmd,
1717 sense_reason_t (*exec_cmd)(struct se_cmd *cmd))
1718{
1719 unsigned char *cdb = cmd->t_task_cdb;
1720
1721 /*
1722 * Clear a lun set in the cdb if the initiator talking to use spoke
1723 * and old standards version, as we can't assume the underlying device
1724 * won't choke up on it.
1725 */
1726 switch (cdb[0]) {
1727 case READ_10: /* SBC - RDProtect */
1728 case READ_12: /* SBC - RDProtect */
1729 case READ_16: /* SBC - RDProtect */
1730 case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
1731 case VERIFY: /* SBC - VRProtect */
1732 case VERIFY_16: /* SBC - VRProtect */
1733 case WRITE_VERIFY: /* SBC - VRProtect */
1734 case WRITE_VERIFY_12: /* SBC - VRProtect */
1735 case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
1736 break;
1737 default:
1738 cdb[1] &= 0x1f; /* clear logical unit number */
1739 break;
1740 }
1741
1742 /*
1743 * For REPORT LUNS we always need to emulate the response, for everything
1744 * else, pass it up.
1745 */
1746 if (cdb[0] == REPORT_LUNS) {
1747 cmd->execute_cmd = spc_emulate_report_luns;
1748 return TCM_NO_SENSE;
1749 }
1750
1751 /* Set DATA_CDB flag for ops that should have it */
1752 switch (cdb[0]) {
1753 case READ_6:
1754 case READ_10:
1755 case READ_12:
1756 case READ_16:
1757 case WRITE_6:
1758 case WRITE_10:
1759 case WRITE_12:
1760 case WRITE_16:
1761 case WRITE_VERIFY:
1762 case WRITE_VERIFY_12:
1763 case 0x8e: /* WRITE_VERIFY_16 */
1764 case COMPARE_AND_WRITE:
1765 case XDWRITEREAD_10:
1766 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
1767 break;
1768 case VARIABLE_LENGTH_CMD:
1769 switch (get_unaligned_be16(&cdb[8])) {
1770 case READ_32:
1771 case WRITE_32:
1772 case 0x0c: /* WRITE_VERIFY_32 */
1773 case XDWRITEREAD_32:
1774 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
1775 break;
1776 }
1777 }
1778
1779 cmd->execute_cmd = exec_cmd;
1780
1781 return TCM_NO_SENSE;
1782}
1783EXPORT_SYMBOL(passthrough_parse_cdb);
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 4073869d2090..53bd0eb57095 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -973,64 +973,13 @@ fail:
973 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 973 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
974} 974}
975 975
976/*
977 * Clear a lun set in the cdb if the initiator talking to use spoke
978 * and old standards version, as we can't assume the underlying device
979 * won't choke up on it.
980 */
981static inline void pscsi_clear_cdb_lun(unsigned char *cdb)
982{
983 switch (cdb[0]) {
984 case READ_10: /* SBC - RDProtect */
985 case READ_12: /* SBC - RDProtect */
986 case READ_16: /* SBC - RDProtect */
987 case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
988 case VERIFY: /* SBC - VRProtect */
989 case VERIFY_16: /* SBC - VRProtect */
990 case WRITE_VERIFY: /* SBC - VRProtect */
991 case WRITE_VERIFY_12: /* SBC - VRProtect */
992 case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
993 break;
994 default:
995 cdb[1] &= 0x1f; /* clear logical unit number */
996 break;
997 }
998}
999
1000static sense_reason_t 976static sense_reason_t
1001pscsi_parse_cdb(struct se_cmd *cmd) 977pscsi_parse_cdb(struct se_cmd *cmd)
1002{ 978{
1003 unsigned char *cdb = cmd->t_task_cdb;
1004
1005 if (cmd->se_cmd_flags & SCF_BIDI) 979 if (cmd->se_cmd_flags & SCF_BIDI)
1006 return TCM_UNSUPPORTED_SCSI_OPCODE; 980 return TCM_UNSUPPORTED_SCSI_OPCODE;
1007 981
1008 pscsi_clear_cdb_lun(cdb); 982 return passthrough_parse_cdb(cmd, pscsi_execute_cmd);
1009
1010 /*
1011 * For REPORT LUNS we always need to emulate the response, for everything
1012 * else the default for pSCSI is to pass the command to the underlying
1013 * LLD / physical hardware.
1014 */
1015 switch (cdb[0]) {
1016 case REPORT_LUNS:
1017 cmd->execute_cmd = spc_emulate_report_luns;
1018 return 0;
1019 case READ_6:
1020 case READ_10:
1021 case READ_12:
1022 case READ_16:
1023 case WRITE_6:
1024 case WRITE_10:
1025 case WRITE_12:
1026 case WRITE_16:
1027 case WRITE_VERIFY:
1028 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
1029 /* FALLTHROUGH*/
1030 default:
1031 cmd->execute_cmd = pscsi_execute_cmd;
1032 return 0;
1033 }
1034} 983}
1035 984
1036static sense_reason_t 985static sense_reason_t
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 90e084ea7b92..2768ea2cfd7a 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -1049,48 +1049,7 @@ tcmu_pass_op(struct se_cmd *se_cmd)
1049static sense_reason_t 1049static sense_reason_t
1050tcmu_parse_cdb(struct se_cmd *cmd) 1050tcmu_parse_cdb(struct se_cmd *cmd)
1051{ 1051{
1052 unsigned char *cdb = cmd->t_task_cdb; 1052 return passthrough_parse_cdb(cmd, tcmu_pass_op);
1053
1054 /*
1055 * For REPORT LUNS we always need to emulate the response, for everything
1056 * else, pass it up.
1057 */
1058 if (cdb[0] == REPORT_LUNS) {
1059 cmd->execute_cmd = spc_emulate_report_luns;
1060 return TCM_NO_SENSE;
1061 }
1062
1063 /* Set DATA_CDB flag for ops that should have it */
1064 switch (cdb[0]) {
1065 case READ_6:
1066 case READ_10:
1067 case READ_12:
1068 case READ_16:
1069 case WRITE_6:
1070 case WRITE_10:
1071 case WRITE_12:
1072 case WRITE_16:
1073 case WRITE_VERIFY:
1074 case WRITE_VERIFY_12:
1075 case 0x8e: /* WRITE_VERIFY_16 */
1076 case COMPARE_AND_WRITE:
1077 case XDWRITEREAD_10:
1078 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
1079 break;
1080 case VARIABLE_LENGTH_CMD:
1081 switch (get_unaligned_be16(&cdb[8])) {
1082 case READ_32:
1083 case WRITE_32:
1084 case 0x0c: /* WRITE_VERIFY_32 */
1085 case XDWRITEREAD_32:
1086 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
1087 break;
1088 }
1089 }
1090
1091 cmd->execute_cmd = tcmu_pass_op;
1092
1093 return TCM_NO_SENSE;
1094} 1053}
1095 1054
1096DEF_TB_DEV_ATTRIB_RO(tcmu, hw_pi_prot_type); 1055DEF_TB_DEV_ATTRIB_RO(tcmu, hw_pi_prot_type);
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index d61be7297b2c..563e11970152 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -138,5 +138,7 @@ int se_dev_set_queue_depth(struct se_device *, u32);
138int se_dev_set_max_sectors(struct se_device *, u32); 138int se_dev_set_max_sectors(struct se_device *, u32);
139int se_dev_set_optimal_sectors(struct se_device *, u32); 139int se_dev_set_optimal_sectors(struct se_device *, u32);
140int se_dev_set_block_size(struct se_device *, u32); 140int se_dev_set_block_size(struct se_device *, u32);
141sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
142 sense_reason_t (*exec_cmd)(struct se_cmd *cmd));
141 143
142#endif /* TARGET_CORE_BACKEND_H */ 144#endif /* TARGET_CORE_BACKEND_H */