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