aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorAndy Grover <agrover@redhat.com>2015-05-01 13:43:45 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-05-02 21:20:51 -0400
commit8ee83a747ac2309934c229281dda8f26648ec462 (patch)
tree210020dd37017542b572a712cc41cd941eb7590d /drivers/target
parenta928d28d4487402e6bd18bea1b8cc2b2ec6e6d8f (diff)
target/user: Disallow full passthrough (pass_level=0)
TCMU requires more work to correctly handle both user handlers that want all SCSI commands (pass_level=0) for a se_device, and also handlers that just want I/O commands and let the others be emulated by the kernel (pass_level=1). Only support the latter for now. For full passthrough, we will need to support a second se_subsystem_api template, due to configfs attributes being different between the two modes. Thus pass_level is extraneous, and we can remove it. The ABI break for TCMU v2 is already applied for this release, so it's best to do this now to avoid another ABI break in the future. Signed-off-by: Andy Grover <agrover@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_user.c68
1 files changed, 3 insertions, 65 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index dbc872a6c981..0e0feeaec39c 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -71,13 +71,6 @@ struct tcmu_hba {
71 u32 host_id; 71 u32 host_id;
72}; 72};
73 73
74/* User wants all cmds or just some */
75enum passthru_level {
76 TCMU_PASS_ALL = 0,
77 TCMU_PASS_IO,
78 TCMU_PASS_INVALID,
79};
80
81#define TCMU_CONFIG_LEN 256 74#define TCMU_CONFIG_LEN 256
82 75
83struct tcmu_dev { 76struct tcmu_dev {
@@ -89,7 +82,6 @@ struct tcmu_dev {
89#define TCMU_DEV_BIT_OPEN 0 82#define TCMU_DEV_BIT_OPEN 0
90#define TCMU_DEV_BIT_BROKEN 1 83#define TCMU_DEV_BIT_BROKEN 1
91 unsigned long flags; 84 unsigned long flags;
92 enum passthru_level pass_level;
93 85
94 struct uio_info uio_info; 86 struct uio_info uio_info;
95 87
@@ -683,8 +675,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
683 setup_timer(&udev->timeout, tcmu_device_timedout, 675 setup_timer(&udev->timeout, tcmu_device_timedout,
684 (unsigned long)udev); 676 (unsigned long)udev);
685 677
686 udev->pass_level = TCMU_PASS_ALL;
687
688 return &udev->se_dev; 678 return &udev->se_dev;
689} 679}
690 680
@@ -948,13 +938,12 @@ static void tcmu_free_device(struct se_device *dev)
948} 938}
949 939
950enum { 940enum {
951 Opt_dev_config, Opt_dev_size, Opt_err, Opt_pass_level, 941 Opt_dev_config, Opt_dev_size, Opt_err,
952}; 942};
953 943
954static match_table_t tokens = { 944static match_table_t tokens = {
955 {Opt_dev_config, "dev_config=%s"}, 945 {Opt_dev_config, "dev_config=%s"},
956 {Opt_dev_size, "dev_size=%u"}, 946 {Opt_dev_size, "dev_size=%u"},
957 {Opt_pass_level, "pass_level=%u"},
958 {Opt_err, NULL} 947 {Opt_err, NULL}
959}; 948};
960 949
@@ -965,7 +954,6 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev,
965 char *orig, *ptr, *opts, *arg_p; 954 char *orig, *ptr, *opts, *arg_p;
966 substring_t args[MAX_OPT_ARGS]; 955 substring_t args[MAX_OPT_ARGS];
967 int ret = 0, token; 956 int ret = 0, token;
968 int arg;
969 957
970 opts = kstrdup(page, GFP_KERNEL); 958 opts = kstrdup(page, GFP_KERNEL);
971 if (!opts) 959 if (!opts)
@@ -998,16 +986,6 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev,
998 if (ret < 0) 986 if (ret < 0)
999 pr_err("kstrtoul() failed for dev_size=\n"); 987 pr_err("kstrtoul() failed for dev_size=\n");
1000 break; 988 break;
1001 case Opt_pass_level:
1002 match_int(args, &arg);
1003 if (arg >= TCMU_PASS_INVALID) {
1004 pr_warn("TCMU: Invalid pass_level: %d\n", arg);
1005 break;
1006 }
1007
1008 pr_debug("TCMU: Setting pass_level to %d\n", arg);
1009 udev->pass_level = arg;
1010 break;
1011 default: 989 default:
1012 break; 990 break;
1013 } 991 }
@@ -1024,8 +1002,7 @@ static ssize_t tcmu_show_configfs_dev_params(struct se_device *dev, char *b)
1024 1002
1025 bl = sprintf(b + bl, "Config: %s ", 1003 bl = sprintf(b + bl, "Config: %s ",
1026 udev->dev_config[0] ? udev->dev_config : "NULL"); 1004 udev->dev_config[0] ? udev->dev_config : "NULL");
1027 bl += sprintf(b + bl, "Size: %zu PassLevel: %u\n", 1005 bl += sprintf(b + bl, "Size: %zu\n", udev->dev_size);
1028 udev->dev_size, udev->pass_level);
1029 1006
1030 return bl; 1007 return bl;
1031} 1008}
@@ -1074,46 +1051,7 @@ static struct sbc_ops tcmu_sbc_ops = {
1074static sense_reason_t 1051static sense_reason_t
1075tcmu_parse_cdb(struct se_cmd *cmd) 1052tcmu_parse_cdb(struct se_cmd *cmd)
1076{ 1053{
1077 unsigned char *cdb = cmd->t_task_cdb; 1054 return sbc_parse_cdb(cmd, &tcmu_sbc_ops);
1078 struct tcmu_dev *udev = TCMU_DEV(cmd->se_dev);
1079 sense_reason_t ret;
1080
1081 switch (udev->pass_level) {
1082 case TCMU_PASS_ALL:
1083 /* We're just like pscsi, then */
1084 /*
1085 * For REPORT LUNS we always need to emulate the response, for everything
1086 * else, pass it up.
1087 */
1088 switch (cdb[0]) {
1089 case REPORT_LUNS:
1090 cmd->execute_cmd = spc_emulate_report_luns;
1091 break;
1092 case READ_6:
1093 case READ_10:
1094 case READ_12:
1095 case READ_16:
1096 case WRITE_6:
1097 case WRITE_10:
1098 case WRITE_12:
1099 case WRITE_16:
1100 case WRITE_VERIFY:
1101 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
1102 /* FALLTHROUGH */
1103 default:
1104 cmd->execute_cmd = tcmu_pass_op;
1105 }
1106 ret = TCM_NO_SENSE;
1107 break;
1108 case TCMU_PASS_IO:
1109 ret = sbc_parse_cdb(cmd, &tcmu_sbc_ops);
1110 break;
1111 default:
1112 pr_err("Unknown tcm-user pass level %d\n", udev->pass_level);
1113 ret = TCM_CHECK_CONDITION_ABORT_CMD;
1114 }
1115
1116 return ret;
1117} 1055}
1118 1056
1119DEF_TB_DEFAULT_ATTRIBS(tcmu); 1057DEF_TB_DEFAULT_ATTRIBS(tcmu);