Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

target/user: Only support full command pass-through

After much discussion, give up on only passing a subset of SCSI commands
to userspace and pass them all. Based on what pscsi is doing, make sure
to set SCF_SCSI_DATA_CDB for I/O ops, and define attributes identical to
pscsi.

Make hw_block_size configurable via dev param.

Remove mention of command filtering from tcmu-design.txt.

Signed-off-by: Andy Grover <agrover@redhat.com>
Reviewed-by: Ilias Tsitsimpis <iliastsi@arrikto.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Andy Grover and committed by
Nicholas Bellinger
9c1cd1b6 cf87edc6

+76 -71
+1 -20
Documentation/target/tcmu-design.txt
··· 15 15 a) Discovering and configuring TCMU uio devices 16 16 b) Waiting for events on the device(s) 17 17 c) Managing the command ring 18 - 3) Command filtering 19 - 4) A final note 18 + 3) A final note 20 19 21 20 22 21 TCM Userspace Design ··· 361 362 362 363 return 0; 363 364 } 364 - 365 - 366 - Command filtering 367 - ----------------- 368 - 369 - Initial TCMU support is for a filtered commandset. Only IO-related 370 - commands are presented to userspace, and the rest are handled by LIO's 371 - in-kernel command emulation. The commands presented are all versions 372 - of: 373 - 374 - READ 375 - WRITE 376 - WRITE_VERIFY 377 - XDWRITEREAD 378 - WRITE_SAME 379 - COMPARE_AND_WRITE 380 - SYNCHRONIZE_CACHE 381 - UNMAP 382 365 383 366 384 367 A final note
+75 -51
drivers/target/target_core_user.c
··· 938 938 } 939 939 940 940 enum { 941 - Opt_dev_config, Opt_dev_size, Opt_err, 941 + Opt_dev_config, Opt_dev_size, Opt_hw_block_size, Opt_err, 942 942 }; 943 943 944 944 static match_table_t tokens = { 945 945 {Opt_dev_config, "dev_config=%s"}, 946 946 {Opt_dev_size, "dev_size=%u"}, 947 + {Opt_hw_block_size, "hw_block_size=%u"}, 947 948 {Opt_err, NULL} 948 949 }; 949 950 ··· 955 954 char *orig, *ptr, *opts, *arg_p; 956 955 substring_t args[MAX_OPT_ARGS]; 957 956 int ret = 0, token; 957 + unsigned long tmp_ul; 958 958 959 959 opts = kstrdup(page, GFP_KERNEL); 960 960 if (!opts) ··· 988 986 if (ret < 0) 989 987 pr_err("kstrtoul() failed for dev_size=\n"); 990 988 break; 989 + case Opt_hw_block_size: 990 + arg_p = match_strdup(&args[0]); 991 + if (!arg_p) { 992 + ret = -ENOMEM; 993 + break; 994 + } 995 + ret = kstrtoul(arg_p, 0, &tmp_ul); 996 + kfree(arg_p); 997 + if (ret < 0) { 998 + pr_err("kstrtoul() failed for hw_block_size=\n"); 999 + break; 1000 + } 1001 + if (!tmp_ul) { 1002 + pr_err("hw_block_size must be nonzero\n"); 1003 + break; 1004 + } 1005 + dev->dev_attrib.hw_block_size = tmp_ul; 1006 + break; 991 1007 default: 992 1008 break; 993 1009 } ··· 1036 1016 } 1037 1017 1038 1018 static sense_reason_t 1039 - tcmu_execute_rw(struct se_cmd *se_cmd, struct scatterlist *sgl, u32 sgl_nents, 1040 - enum dma_data_direction data_direction) 1041 - { 1042 - int ret; 1043 - 1044 - ret = tcmu_queue_cmd(se_cmd); 1045 - 1046 - if (ret != 0) 1047 - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1048 - else 1049 - return TCM_NO_SENSE; 1050 - } 1051 - 1052 - static sense_reason_t 1053 1019 tcmu_pass_op(struct se_cmd *se_cmd) 1054 1020 { 1055 1021 int ret = tcmu_queue_cmd(se_cmd); ··· 1046 1040 return TCM_NO_SENSE; 1047 1041 } 1048 1042 1049 - static struct sbc_ops tcmu_sbc_ops = { 1050 - .execute_rw = tcmu_execute_rw, 1051 - .execute_sync_cache = tcmu_pass_op, 1052 - .execute_write_same = tcmu_pass_op, 1053 - .execute_write_same_unmap = tcmu_pass_op, 1054 - .execute_unmap = tcmu_pass_op, 1055 - }; 1056 - 1057 1043 static sense_reason_t 1058 1044 tcmu_parse_cdb(struct se_cmd *cmd) 1059 1045 { 1060 - return sbc_parse_cdb(cmd, &tcmu_sbc_ops); 1046 + unsigned char *cdb = cmd->t_task_cdb; 1047 + 1048 + /* 1049 + * For REPORT LUNS we always need to emulate the response, for everything 1050 + * else, pass it up. 1051 + */ 1052 + if (cdb[0] == REPORT_LUNS) { 1053 + cmd->execute_cmd = spc_emulate_report_luns; 1054 + return TCM_NO_SENSE; 1055 + } 1056 + 1057 + /* Set DATA_CDB flag for ops that should have it */ 1058 + switch (cdb[0]) { 1059 + case READ_6: 1060 + case READ_10: 1061 + case READ_12: 1062 + case READ_16: 1063 + case WRITE_6: 1064 + case WRITE_10: 1065 + case WRITE_12: 1066 + case WRITE_16: 1067 + case WRITE_VERIFY: 1068 + case WRITE_VERIFY_12: 1069 + case 0x8e: /* WRITE_VERIFY_16 */ 1070 + case COMPARE_AND_WRITE: 1071 + case XDWRITEREAD_10: 1072 + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 1073 + break; 1074 + case VARIABLE_LENGTH_CMD: 1075 + switch (get_unaligned_be16(&cdb[8])) { 1076 + case READ_32: 1077 + case WRITE_32: 1078 + case 0x0c: /* WRITE_VERIFY_32 */ 1079 + case XDWRITEREAD_32: 1080 + cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 1081 + break; 1082 + } 1083 + } 1084 + 1085 + cmd->execute_cmd = tcmu_pass_op; 1086 + 1087 + return TCM_NO_SENSE; 1061 1088 } 1062 1089 1063 - DEF_TB_DEFAULT_ATTRIBS(tcmu); 1090 + DEF_TB_DEV_ATTRIB_RO(tcmu, hw_pi_prot_type); 1091 + TB_DEV_ATTR_RO(tcmu, hw_pi_prot_type); 1092 + 1093 + DEF_TB_DEV_ATTRIB_RO(tcmu, hw_block_size); 1094 + TB_DEV_ATTR_RO(tcmu, hw_block_size); 1095 + 1096 + DEF_TB_DEV_ATTRIB_RO(tcmu, hw_max_sectors); 1097 + TB_DEV_ATTR_RO(tcmu, hw_max_sectors); 1098 + 1099 + DEF_TB_DEV_ATTRIB_RO(tcmu, hw_queue_depth); 1100 + TB_DEV_ATTR_RO(tcmu, hw_queue_depth); 1064 1101 1065 1102 static struct configfs_attribute *tcmu_backend_dev_attrs[] = { 1066 - &tcmu_dev_attrib_emulate_model_alias.attr, 1067 - &tcmu_dev_attrib_emulate_dpo.attr, 1068 - &tcmu_dev_attrib_emulate_fua_write.attr, 1069 - &tcmu_dev_attrib_emulate_fua_read.attr, 1070 - &tcmu_dev_attrib_emulate_write_cache.attr, 1071 - &tcmu_dev_attrib_emulate_ua_intlck_ctrl.attr, 1072 - &tcmu_dev_attrib_emulate_tas.attr, 1073 - &tcmu_dev_attrib_emulate_tpu.attr, 1074 - &tcmu_dev_attrib_emulate_tpws.attr, 1075 - &tcmu_dev_attrib_emulate_caw.attr, 1076 - &tcmu_dev_attrib_emulate_3pc.attr, 1077 - &tcmu_dev_attrib_pi_prot_type.attr, 1078 1103 &tcmu_dev_attrib_hw_pi_prot_type.attr, 1079 - &tcmu_dev_attrib_pi_prot_format.attr, 1080 - &tcmu_dev_attrib_enforce_pr_isids.attr, 1081 - &tcmu_dev_attrib_is_nonrot.attr, 1082 - &tcmu_dev_attrib_emulate_rest_reord.attr, 1083 - &tcmu_dev_attrib_force_pr_aptpl.attr, 1084 1104 &tcmu_dev_attrib_hw_block_size.attr, 1085 - &tcmu_dev_attrib_block_size.attr, 1086 1105 &tcmu_dev_attrib_hw_max_sectors.attr, 1087 - &tcmu_dev_attrib_optimal_sectors.attr, 1088 1106 &tcmu_dev_attrib_hw_queue_depth.attr, 1089 - &tcmu_dev_attrib_queue_depth.attr, 1090 - &tcmu_dev_attrib_max_unmap_lba_count.attr, 1091 - &tcmu_dev_attrib_max_unmap_block_desc_count.attr, 1092 - &tcmu_dev_attrib_unmap_granularity.attr, 1093 - &tcmu_dev_attrib_unmap_granularity_alignment.attr, 1094 - &tcmu_dev_attrib_max_write_same_len.attr, 1095 1107 NULL, 1096 1108 }; 1097 1109 ··· 1118 1094 .inquiry_prod = "USER", 1119 1095 .inquiry_rev = TCMU_VERSION, 1120 1096 .owner = THIS_MODULE, 1121 - .transport_type = TRANSPORT_PLUGIN_VHBA_PDEV, 1097 + .transport_type = TRANSPORT_PLUGIN_PHBA_PDEV, 1122 1098 .attach_hba = tcmu_attach_hba, 1123 1099 .detach_hba = tcmu_detach_hba, 1124 1100 .alloc_device = tcmu_alloc_device,