This allows userspace to request the fabric drivers do direct submissions if they support it. With the new device file, submit_type, users can write 0 - 2 to control how commands are submitted to the backend: 0 - TARGET_FABRIC_DEFAULT_SUBMIT - LIO will use the fabric's default submission type. This is the default for compat. 1 - TARGET_DIRECT_SUBMIT - LIO will submit the cmd to the backend from the calling context if the fabric the cmd was received on supports it, else it will use the fabric's default type. 2 - TARGET_QUEUE_SUBMIT - LIO will queue the cmd to the LIO submission workqueue which will pass it to the backend. When using an NVMe drive and vhost-scsi with direct submission we see around a 20% improvement in 4K I/Os: fio jobs 1 2 4 8 10 -------------------------------------------------- defer 94K 190K 394K 770K 890K direct 128K 252K 488K 950K - And when using the queueing mode, we now no longer see issues like where the iSCSI tx thread is blocked in the block layer waiting on a tag so it can't respond to a nop or perform I/Os for other LUs.
Unified · Split
| @@ -154,7 +154,7 @@ static void tcm_loop_target_queue_cmd(struct tcm_loop_cmd *tl_cmd) · 153 unmodified lines | |||
| 154 | GFP_ATOMIC)) | 154 | GFP_ATOMIC)) |
| 155 | return; | 155 | return; |
| 156 | 156 | ||
| 157 | target_queue_submission(se_cmd); | 157 | target_submit(se_cmd); |
| 158 | return; | 158 | return; |
| 159 | 159 | ||
| 160 | out_done: | 160 | out_done: |
| @@ -577,6 +577,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment); · 576 unmodified lines | |||
| 577 | DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data); | 577 | DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data); |
| 578 | DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); | 578 | DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); |
| 579 | DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); | 579 | DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); |
| 580 | DEF_CONFIGFS_ATTRIB_SHOW(submit_type); | ||
| 580 | 581 | ||
| 581 | #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ | 582 | #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ |
| 582 | static ssize_t _name##_store(struct config_item *item, const char *page,\ | 583 | static ssize_t _name##_store(struct config_item *item, const char *page,\ |
| @@ -1231,6 +1232,24 @@ static ssize_t emulate_rsoc_store(struct config_item *item, · 648 unmodified lines | |||
| 1231 | return count; | 1232 | return count; |
| 1232 | } | 1233 | } |
| 1233 | 1234 | ||
| 1235 | static ssize_t submit_type_store(struct config_item *item, const char *page, | ||
| 1236 | size_t count) | ||
| 1237 | { | ||
| 1238 | struct se_dev_attrib *da = to_attrib(item); | ||
| 1239 | int ret; | ||
| 1240 | u8 val; | ||
| 1241 | |||
| 1242 | ret = kstrtou8(page, 0, &val); | ||
| 1243 | if (ret < 0) | ||
| 1244 | return ret; | ||
| 1245 | |||
| 1246 | if (val > TARGET_QUEUE_SUBMIT) | ||
| 1247 | return -EINVAL; | ||
| 1248 | |||
| 1249 | da->submit_type = val; | ||
| 1250 | return count; | ||
| 1251 | } | ||
| 1252 | |||
| 1234 | CONFIGFS_ATTR(, emulate_model_alias); | 1253 | CONFIGFS_ATTR(, emulate_model_alias); |
| 1235 | CONFIGFS_ATTR(, emulate_dpo); | 1254 | CONFIGFS_ATTR(, emulate_dpo); |
| 1236 | CONFIGFS_ATTR(, emulate_fua_write); | 1255 | CONFIGFS_ATTR(, emulate_fua_write); |
| @@ -1266,6 +1285,7 @@ CONFIGFS_ATTR(, unmap_zeroes_data); · 29 unmodified lines | |||
| 1266 | CONFIGFS_ATTR(, max_write_same_len); | 1285 | CONFIGFS_ATTR(, max_write_same_len); |
| 1267 | CONFIGFS_ATTR(, alua_support); | 1286 | CONFIGFS_ATTR(, alua_support); |
| 1268 | CONFIGFS_ATTR(, pgr_support); | 1287 | CONFIGFS_ATTR(, pgr_support); |
| 1288 | CONFIGFS_ATTR(, submit_type); | ||
| 1269 | 1289 | ||
| 1270 | /* | 1290 | /* |
| 1271 | * dev_attrib attributes for devices using the target core SBC/SPC | 1291 | * dev_attrib attributes for devices using the target core SBC/SPC |
| @@ -1308,6 +1328,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = { · 36 unmodified lines | |||
| 1308 | &attr_alua_support, | 1328 | &attr_alua_support, |
| 1309 | &attr_pgr_support, | 1329 | &attr_pgr_support, |
| 1310 | &attr_emulate_rsoc, | 1330 | &attr_emulate_rsoc, |
| 1331 | &attr_submit_type, | ||
| 1311 | NULL, | 1332 | NULL, |
| 1312 | }; | 1333 | }; |
| 1313 | EXPORT_SYMBOL(sbc_attrib_attrs); | 1334 | EXPORT_SYMBOL(sbc_attrib_attrs); |
| @@ -1325,6 +1346,7 @@ struct configfs_attribute *passthrough_attrib_attrs[] = { · 11 unmodified lines | |||
| 1325 | &attr_emulate_pr, | 1346 | &attr_emulate_pr, |
| 1326 | &attr_alua_support, | 1347 | &attr_alua_support, |
| 1327 | &attr_pgr_support, | 1348 | &attr_pgr_support, |
| 1349 | &attr_submit_type, | ||
| 1328 | NULL, | 1350 | NULL, |
| 1329 | }; | 1351 | }; |
| 1330 | EXPORT_SYMBOL(passthrough_attrib_attrs); | 1352 | EXPORT_SYMBOL(passthrough_attrib_attrs); |
| @@ -779,6 +779,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) · 778 unmodified lines | |||
| 779 | dev->dev_attrib.unmap_zeroes_data = | 779 | dev->dev_attrib.unmap_zeroes_data = |
| 780 | DA_UNMAP_ZEROES_DATA_DEFAULT; | 780 | DA_UNMAP_ZEROES_DATA_DEFAULT; |
| 781 | dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; | 781 | dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; |
| 782 | dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT; | ||
| 782 | 783 | ||
| 783 | xcopy_lun = &dev->xcopy_lun; | 784 | xcopy_lun = &dev->xcopy_lun; |
| 784 | rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); | 785 | rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); |
| @@ -1575,14 +1575,7 @@ target_cmd_parse_cdb(struct se_cmd *cmd) · 1574 unmodified lines | |||
| 1575 | } | 1575 | } |
| 1576 | EXPORT_SYMBOL(target_cmd_parse_cdb); | 1576 | EXPORT_SYMBOL(target_cmd_parse_cdb); |
| 1577 | 1577 | ||
| 1578 | /** | 1578 | static int __target_submit(struct se_cmd *cmd) |
| 1579 | * target_submit - perform final initialization and submit cmd to LIO core | ||
| 1580 | * @cmd: command descriptor to submit | ||
| 1581 | * | ||
| 1582 | * target_submit_prep or something similar must have been called on the cmd, | ||
| 1583 | * and this must be called from process context. | ||
| 1584 | */ | ||
| 1585 | int target_submit(struct se_cmd *cmd) | ||
| 1586 | { | 1579 | { |
| 1587 | sense_reason_t ret; | 1580 | sense_reason_t ret; |
| 1588 | 1581 | ||
| @@ -1642,7 +1635,6 @@ int target_submit(struct se_cmd *cmd) · 53 unmodified lines | |||
| 1642 | transport_generic_request_failure(cmd, ret); | 1635 | transport_generic_request_failure(cmd, ret); |
| 1643 | return 0; | 1636 | return 0; |
| 1644 | } | 1637 | } |
| 1645 | EXPORT_SYMBOL_GPL(target_submit); | ||
| 1646 | 1638 | ||
| 1647 | sense_reason_t | 1639 | sense_reason_t |
| 1648 | transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, | 1640 | transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, |
| @@ -1904,7 +1896,7 @@ void target_queued_submit_work(struct work_struct *work) · 255 unmodified lines | |||
| 1904 | se_plug = target_plug_device(se_dev); | 1896 | se_plug = target_plug_device(se_dev); |
| 1905 | } | 1897 | } |
| 1906 | 1898 | ||
| 1907 | target_submit(se_cmd); | 1899 | __target_submit(se_cmd); |
| 1908 | } | 1900 | } |
| 1909 | 1901 | ||
| 1910 | if (se_plug) | 1902 | if (se_plug) |
| @@ -1927,6 +1919,35 @@ void target_queue_submission(struct se_cmd *se_cmd) · 16 unmodified lines | |||
| 1927 | } | 1919 | } |
| 1928 | EXPORT_SYMBOL_GPL(target_queue_submission); | 1920 | EXPORT_SYMBOL_GPL(target_queue_submission); |
| 1929 | 1921 | ||
| 1922 | /** | ||
| 1923 | * target_submit - perform final initialization and submit cmd to LIO core | ||
| 1924 | * @cmd: command descriptor to submit | ||
| 1925 | * | ||
| 1926 | * target_submit_prep or something similar must have been called on the cmd, | ||
| 1927 | * and this must be called from process context. | ||
| 1928 | */ | ||
| 1929 | int target_submit(struct se_cmd *se_cmd) | ||
| 1930 | { | ||
| 1931 | const struct target_core_fabric_ops *tfo = se_cmd->se_sess->se_tpg->se_tpg_tfo; | ||
| 1932 | struct se_dev_attrib *da = &se_cmd->se_dev->dev_attrib; | ||
| 1933 | u8 submit_type; | ||
| 1934 | |||
| 1935 | if (da->submit_type == TARGET_FABRIC_DEFAULT_SUBMIT) | ||
| 1936 | submit_type = tfo->default_submit_type; | ||
| 1937 | else if (da->submit_type == TARGET_DIRECT_SUBMIT && | ||
| 1938 | tfo->direct_submit_supp) | ||
| 1939 | submit_type = TARGET_DIRECT_SUBMIT; | ||
| 1940 | else | ||
| 1941 | submit_type = TARGET_QUEUE_SUBMIT; | ||
| 1942 | |||
| 1943 | if (submit_type == TARGET_DIRECT_SUBMIT) | ||
| 1944 | return __target_submit(se_cmd); | ||
| 1945 | |||
| 1946 | target_queue_submission(se_cmd); | ||
| 1947 | return 0; | ||
| 1948 | } | ||
| 1949 | EXPORT_SYMBOL_GPL(target_submit); | ||
| 1950 | |||
| 1930 | static void target_complete_tmr_failure(struct work_struct *work) | 1951 | static void target_complete_tmr_failure(struct work_struct *work) |
| 1931 | { | 1952 | { |
| 1932 | struct se_cmd *se_cmd = container_of(work, struct se_cmd, work); | 1953 | struct se_cmd *se_cmd = container_of(work, struct se_cmd, work); |
| @@ -909,7 +909,7 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd) · 908 unmodified lines | |||
| 909 | cmd->tvc_prot_sgl_count, GFP_KERNEL)) | 909 | cmd->tvc_prot_sgl_count, GFP_KERNEL)) |
| 910 | return; | 910 | return; |
| 911 | 911 | ||
| 912 | target_queue_submission(se_cmd); | 912 | target_submit(se_cmd); |
| 913 | } | 913 | } |
| 914 | 914 | ||
| 915 | static void | 915 | static void |
| @@ -726,6 +726,7 @@ struct se_dev_attrib { · 725 unmodified lines | |||
| 726 | u32 unmap_granularity; | 726 | u32 unmap_granularity; |
| 727 | u32 unmap_granularity_alignment; | 727 | u32 unmap_granularity_alignment; |
| 728 | u32 max_write_same_len; | 728 | u32 max_write_same_len; |
| 729 | u8 submit_type; | ||
| 729 | struct se_device *da_dev; | 730 | struct se_device *da_dev; |
| 730 | struct config_group da_group; | 731 | struct config_group da_group; |
| 731 | }; | 732 | }; |