diff options
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 11 | ||||
| -rw-r--r-- | drivers/target/target_core_alua.c | 7 | ||||
| -rw-r--r-- | drivers/target/target_core_device.c | 7 | ||||
| -rw-r--r-- | drivers/target/target_core_iblock.c | 17 | ||||
| -rw-r--r-- | drivers/target/target_core_pr.c | 8 | ||||
| -rw-r--r-- | drivers/target/target_core_pscsi.c | 29 | ||||
| -rw-r--r-- | drivers/target/target_core_spc.c | 35 | ||||
| -rw-r--r-- | drivers/target/target_core_transport.c | 148 | ||||
| -rw-r--r-- | include/target/target_core_backend.h | 4 | ||||
| -rw-r--r-- | include/target/target_core_base.h | 1 |
10 files changed, 141 insertions, 126 deletions
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 0694d9b1bce6..6aba4395e8d8 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
| @@ -221,6 +221,7 @@ static int iscsi_login_zero_tsih_s1( | |||
| 221 | { | 221 | { |
| 222 | struct iscsi_session *sess = NULL; | 222 | struct iscsi_session *sess = NULL; |
| 223 | struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; | 223 | struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; |
| 224 | int ret; | ||
| 224 | 225 | ||
| 225 | sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); | 226 | sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); |
| 226 | if (!sess) { | 227 | if (!sess) { |
| @@ -257,9 +258,17 @@ static int iscsi_login_zero_tsih_s1( | |||
| 257 | return -ENOMEM; | 258 | return -ENOMEM; |
| 258 | } | 259 | } |
| 259 | spin_lock(&sess_idr_lock); | 260 | spin_lock(&sess_idr_lock); |
| 260 | idr_get_new(&sess_idr, NULL, &sess->session_index); | 261 | ret = idr_get_new(&sess_idr, NULL, &sess->session_index); |
| 261 | spin_unlock(&sess_idr_lock); | 262 | spin_unlock(&sess_idr_lock); |
| 262 | 263 | ||
| 264 | if (ret < 0) { | ||
| 265 | pr_err("idr_get_new() for sess_idr failed\n"); | ||
| 266 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
| 267 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
| 268 | kfree(sess); | ||
| 269 | return -ENOMEM; | ||
| 270 | } | ||
| 271 | |||
| 263 | sess->creation_time = get_jiffies_64(); | 272 | sess->creation_time = get_jiffies_64(); |
| 264 | spin_lock_init(&sess->session_stats_lock); | 273 | spin_lock_init(&sess->session_stats_lock); |
| 265 | /* | 274 | /* |
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 91799973081a..41641ba54828 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
| @@ -218,6 +218,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
| 218 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 218 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 219 | return -EINVAL; | 219 | return -EINVAL; |
| 220 | } | 220 | } |
| 221 | if (cmd->data_length < 4) { | ||
| 222 | pr_warn("SET TARGET PORT GROUPS parameter list length %u too" | ||
| 223 | " small\n", cmd->data_length); | ||
| 224 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | ||
| 225 | return -EINVAL; | ||
| 226 | } | ||
| 227 | |||
| 221 | buf = transport_kmap_data_sg(cmd); | 228 | buf = transport_kmap_data_sg(cmd); |
| 222 | 229 | ||
| 223 | /* | 230 | /* |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index cf2c66f3c116..9fc9a6006ca0 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
| @@ -669,6 +669,13 @@ int target_report_luns(struct se_cmd *se_cmd) | |||
| 669 | unsigned char *buf; | 669 | unsigned char *buf; |
| 670 | u32 lun_count = 0, offset = 8, i; | 670 | u32 lun_count = 0, offset = 8, i; |
| 671 | 671 | ||
| 672 | if (se_cmd->data_length < 16) { | ||
| 673 | pr_warn("REPORT LUNS allocation length %u too small\n", | ||
| 674 | se_cmd->data_length); | ||
| 675 | se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
| 676 | return -EINVAL; | ||
| 677 | } | ||
| 678 | |||
| 672 | buf = transport_kmap_data_sg(se_cmd); | 679 | buf = transport_kmap_data_sg(se_cmd); |
| 673 | if (!buf) | 680 | if (!buf) |
| 674 | return -ENOMEM; | 681 | return -ENOMEM; |
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 76db75e836ed..9ba495477fd2 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
| @@ -325,17 +325,30 @@ static int iblock_execute_unmap(struct se_cmd *cmd) | |||
| 325 | struct iblock_dev *ibd = dev->dev_ptr; | 325 | struct iblock_dev *ibd = dev->dev_ptr; |
| 326 | unsigned char *buf, *ptr = NULL; | 326 | unsigned char *buf, *ptr = NULL; |
| 327 | sector_t lba; | 327 | sector_t lba; |
| 328 | int size = cmd->data_length; | 328 | int size; |
| 329 | u32 range; | 329 | u32 range; |
| 330 | int ret = 0; | 330 | int ret = 0; |
| 331 | int dl, bd_dl; | 331 | int dl, bd_dl; |
| 332 | 332 | ||
| 333 | if (cmd->data_length < 8) { | ||
| 334 | pr_warn("UNMAP parameter list length %u too small\n", | ||
| 335 | cmd->data_length); | ||
| 336 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | ||
| 337 | return -EINVAL; | ||
| 338 | } | ||
| 339 | |||
| 333 | buf = transport_kmap_data_sg(cmd); | 340 | buf = transport_kmap_data_sg(cmd); |
| 334 | 341 | ||
| 335 | dl = get_unaligned_be16(&buf[0]); | 342 | dl = get_unaligned_be16(&buf[0]); |
| 336 | bd_dl = get_unaligned_be16(&buf[2]); | 343 | bd_dl = get_unaligned_be16(&buf[2]); |
| 337 | 344 | ||
| 338 | size = min(size - 8, bd_dl); | 345 | size = cmd->data_length - 8; |
| 346 | if (bd_dl > size) | ||
| 347 | pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", | ||
| 348 | cmd->data_length, bd_dl); | ||
| 349 | else | ||
| 350 | size = bd_dl; | ||
| 351 | |||
| 339 | if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { | 352 | if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { |
| 340 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | 353 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; |
| 341 | ret = -EINVAL; | 354 | ret = -EINVAL; |
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1e946502c378..956c84c6b666 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
| @@ -1540,6 +1540,14 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1540 | tidh_new->dest_local_nexus = 1; | 1540 | tidh_new->dest_local_nexus = 1; |
| 1541 | list_add_tail(&tidh_new->dest_list, &tid_dest_list); | 1541 | list_add_tail(&tidh_new->dest_list, &tid_dest_list); |
| 1542 | 1542 | ||
| 1543 | if (cmd->data_length < 28) { | ||
| 1544 | pr_warn("SPC-PR: Received PR OUT parameter list" | ||
| 1545 | " length too small: %u\n", cmd->data_length); | ||
| 1546 | cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; | ||
| 1547 | ret = -EINVAL; | ||
| 1548 | goto out; | ||
| 1549 | } | ||
| 1550 | |||
| 1543 | buf = transport_kmap_data_sg(cmd); | 1551 | buf = transport_kmap_data_sg(cmd); |
| 1544 | /* | 1552 | /* |
| 1545 | * For a PERSISTENT RESERVE OUT specify initiator ports payload, | 1553 | * For a PERSISTENT RESERVE OUT specify initiator ports payload, |
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5552fa7426bc..9d7ce3daa262 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
| @@ -667,7 +667,8 @@ static void pscsi_free_device(void *p) | |||
| 667 | kfree(pdv); | 667 | kfree(pdv); |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) | 670 | static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, |
| 671 | unsigned char *sense_buffer) | ||
| 671 | { | 672 | { |
| 672 | struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; | 673 | struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; |
| 673 | struct scsi_device *sd = pdv->pdv_sd; | 674 | struct scsi_device *sd = pdv->pdv_sd; |
| @@ -679,7 +680,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) | |||
| 679 | * not been allocated because TCM is handling the emulation directly. | 680 | * not been allocated because TCM is handling the emulation directly. |
| 680 | */ | 681 | */ |
| 681 | if (!pt) | 682 | if (!pt) |
| 682 | return 0; | 683 | return; |
| 683 | 684 | ||
| 684 | cdb = &pt->pscsi_cdb[0]; | 685 | cdb = &pt->pscsi_cdb[0]; |
| 685 | result = pt->pscsi_result; | 686 | result = pt->pscsi_result; |
| @@ -687,11 +688,11 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) | |||
| 687 | * Hack to make sure that Write-Protect modepage is set if R/O mode is | 688 | * Hack to make sure that Write-Protect modepage is set if R/O mode is |
| 688 | * forced. | 689 | * forced. |
| 689 | */ | 690 | */ |
| 691 | if (!cmd->se_deve || !cmd->data_length) | ||
| 692 | goto after_mode_sense; | ||
| 693 | |||
| 690 | if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && | 694 | if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && |
| 691 | (status_byte(result) << 1) == SAM_STAT_GOOD) { | 695 | (status_byte(result) << 1) == SAM_STAT_GOOD) { |
| 692 | if (!cmd->se_deve) | ||
| 693 | goto after_mode_sense; | ||
| 694 | |||
| 695 | if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { | 696 | if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { |
| 696 | unsigned char *buf = transport_kmap_data_sg(cmd); | 697 | unsigned char *buf = transport_kmap_data_sg(cmd); |
| 697 | 698 | ||
| @@ -708,7 +709,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) | |||
| 708 | } | 709 | } |
| 709 | after_mode_sense: | 710 | after_mode_sense: |
| 710 | 711 | ||
| 711 | if (sd->type != TYPE_TAPE) | 712 | if (sd->type != TYPE_TAPE || !cmd->data_length) |
| 712 | goto after_mode_select; | 713 | goto after_mode_select; |
| 713 | 714 | ||
| 714 | /* | 715 | /* |
| @@ -750,10 +751,10 @@ after_mode_sense: | |||
| 750 | } | 751 | } |
| 751 | after_mode_select: | 752 | after_mode_select: |
| 752 | 753 | ||
| 753 | if (status_byte(result) & CHECK_CONDITION) | 754 | if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) { |
| 754 | return 1; | 755 | memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER); |
| 755 | 756 | cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; | |
| 756 | return 0; | 757 | } |
| 757 | } | 758 | } |
| 758 | 759 | ||
| 759 | enum { | 760 | enum { |
| @@ -1184,13 +1185,6 @@ fail: | |||
| 1184 | return -ENOMEM; | 1185 | return -ENOMEM; |
| 1185 | } | 1186 | } |
| 1186 | 1187 | ||
| 1187 | static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd) | ||
| 1188 | { | ||
| 1189 | struct pscsi_plugin_task *pt = cmd->priv; | ||
| 1190 | |||
| 1191 | return pt->pscsi_sense; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | /* pscsi_get_device_rev(): | 1188 | /* pscsi_get_device_rev(): |
| 1195 | * | 1189 | * |
| 1196 | * | 1190 | * |
| @@ -1273,7 +1267,6 @@ static struct se_subsystem_api pscsi_template = { | |||
| 1273 | .check_configfs_dev_params = pscsi_check_configfs_dev_params, | 1267 | .check_configfs_dev_params = pscsi_check_configfs_dev_params, |
| 1274 | .set_configfs_dev_params = pscsi_set_configfs_dev_params, | 1268 | .set_configfs_dev_params = pscsi_set_configfs_dev_params, |
| 1275 | .show_configfs_dev_params = pscsi_show_configfs_dev_params, | 1269 | .show_configfs_dev_params = pscsi_show_configfs_dev_params, |
| 1276 | .get_sense_buffer = pscsi_get_sense_buffer, | ||
| 1277 | .get_device_rev = pscsi_get_device_rev, | 1270 | .get_device_rev = pscsi_get_device_rev, |
| 1278 | .get_device_type = pscsi_get_device_type, | 1271 | .get_device_type = pscsi_get_device_type, |
| 1279 | .get_blocks = pscsi_get_blocks, | 1272 | .get_blocks = pscsi_get_blocks, |
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4c861de538c9..388a922c8f6d 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
| @@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd) | |||
| 877 | static int spc_emulate_request_sense(struct se_cmd *cmd) | 877 | static int spc_emulate_request_sense(struct se_cmd *cmd) |
| 878 | { | 878 | { |
| 879 | unsigned char *cdb = cmd->t_task_cdb; | 879 | unsigned char *cdb = cmd->t_task_cdb; |
| 880 | unsigned char *buf; | 880 | unsigned char *rbuf; |
| 881 | u8 ua_asc = 0, ua_ascq = 0; | 881 | u8 ua_asc = 0, ua_ascq = 0; |
| 882 | int err = 0; | 882 | unsigned char buf[SE_SENSE_BUF]; |
| 883 | |||
| 884 | memset(buf, 0, SE_SENSE_BUF); | ||
| 883 | 885 | ||
| 884 | if (cdb[1] & 0x01) { | 886 | if (cdb[1] & 0x01) { |
| 885 | pr_err("REQUEST_SENSE description emulation not" | 887 | pr_err("REQUEST_SENSE description emulation not" |
| @@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) | |||
| 888 | return -ENOSYS; | 890 | return -ENOSYS; |
| 889 | } | 891 | } |
| 890 | 892 | ||
| 891 | buf = transport_kmap_data_sg(cmd); | 893 | rbuf = transport_kmap_data_sg(cmd); |
| 892 | 894 | if (cmd->scsi_sense_reason != 0) { | |
| 893 | if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { | 895 | /* |
| 896 | * Out of memory. We will fail with CHECK CONDITION, so | ||
| 897 | * we must not clear the unit attention condition. | ||
| 898 | */ | ||
| 899 | target_complete_cmd(cmd, CHECK_CONDITION); | ||
| 900 | return 0; | ||
| 901 | } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { | ||
| 894 | /* | 902 | /* |
| 895 | * CURRENT ERROR, UNIT ATTENTION | 903 | * CURRENT ERROR, UNIT ATTENTION |
| 896 | */ | 904 | */ |
| 897 | buf[0] = 0x70; | 905 | buf[0] = 0x70; |
| 898 | buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; | 906 | buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; |
| 899 | 907 | ||
| 900 | if (cmd->data_length < 18) { | ||
| 901 | buf[7] = 0x00; | ||
| 902 | err = -EINVAL; | ||
| 903 | goto end; | ||
| 904 | } | ||
| 905 | /* | 908 | /* |
| 906 | * The Additional Sense Code (ASC) from the UNIT ATTENTION | 909 | * The Additional Sense Code (ASC) from the UNIT ATTENTION |
| 907 | */ | 910 | */ |
| @@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) | |||
| 915 | buf[0] = 0x70; | 918 | buf[0] = 0x70; |
| 916 | buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; | 919 | buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; |
| 917 | 920 | ||
| 918 | if (cmd->data_length < 18) { | ||
| 919 | buf[7] = 0x00; | ||
| 920 | err = -EINVAL; | ||
| 921 | goto end; | ||
| 922 | } | ||
| 923 | /* | 921 | /* |
| 924 | * NO ADDITIONAL SENSE INFORMATION | 922 | * NO ADDITIONAL SENSE INFORMATION |
| 925 | */ | 923 | */ |
| @@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) | |||
| 927 | buf[7] = 0x0A; | 925 | buf[7] = 0x0A; |
| 928 | } | 926 | } |
| 929 | 927 | ||
| 930 | end: | 928 | if (rbuf) { |
| 931 | transport_kunmap_data_sg(cmd); | 929 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
| 930 | transport_kunmap_data_sg(cmd); | ||
| 931 | } | ||
| 932 | |||
| 932 | target_complete_cmd(cmd, GOOD); | 933 | target_complete_cmd(cmd, GOOD); |
| 933 | return 0; | 934 | return 0; |
| 934 | } | 935 | } |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4de3186dc44e..269f54488397 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -567,6 +567,34 @@ static void target_complete_failure_work(struct work_struct *work) | |||
| 567 | transport_generic_request_failure(cmd); | 567 | transport_generic_request_failure(cmd); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | /* | ||
| 571 | * Used when asking transport to copy Sense Data from the underlying | ||
| 572 | * Linux/SCSI struct scsi_cmnd | ||
| 573 | */ | ||
| 574 | static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd) | ||
| 575 | { | ||
| 576 | unsigned char *buffer = cmd->sense_buffer; | ||
| 577 | struct se_device *dev = cmd->se_dev; | ||
| 578 | u32 offset = 0; | ||
| 579 | |||
| 580 | WARN_ON(!cmd->se_lun); | ||
| 581 | |||
| 582 | if (!dev) | ||
| 583 | return NULL; | ||
| 584 | |||
| 585 | if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) | ||
| 586 | return NULL; | ||
| 587 | |||
| 588 | offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); | ||
| 589 | |||
| 590 | /* Automatically padded */ | ||
| 591 | cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; | ||
| 592 | |||
| 593 | pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n", | ||
| 594 | dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); | ||
| 595 | return &buffer[offset]; | ||
| 596 | } | ||
| 597 | |||
| 570 | void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) | 598 | void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) |
| 571 | { | 599 | { |
| 572 | struct se_device *dev = cmd->se_dev; | 600 | struct se_device *dev = cmd->se_dev; |
| @@ -580,11 +608,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) | |||
| 580 | cmd->transport_state &= ~CMD_T_BUSY; | 608 | cmd->transport_state &= ~CMD_T_BUSY; |
| 581 | 609 | ||
| 582 | if (dev && dev->transport->transport_complete) { | 610 | if (dev && dev->transport->transport_complete) { |
| 583 | if (dev->transport->transport_complete(cmd, | 611 | dev->transport->transport_complete(cmd, |
| 584 | cmd->t_data_sg) != 0) { | 612 | cmd->t_data_sg, |
| 585 | cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; | 613 | transport_get_sense_buffer(cmd)); |
| 614 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) | ||
| 586 | success = 1; | 615 | success = 1; |
| 587 | } | ||
| 588 | } | 616 | } |
| 589 | 617 | ||
| 590 | /* | 618 | /* |
| @@ -1181,15 +1209,20 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) | |||
| 1181 | /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ | 1209 | /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ |
| 1182 | goto out_invalid_cdb_field; | 1210 | goto out_invalid_cdb_field; |
| 1183 | } | 1211 | } |
| 1184 | 1212 | /* | |
| 1213 | * For the overflow case keep the existing fabric provided | ||
| 1214 | * ->data_length. Otherwise for the underflow case, reset | ||
| 1215 | * ->data_length to the smaller SCSI expected data transfer | ||
| 1216 | * length. | ||
| 1217 | */ | ||
| 1185 | if (size > cmd->data_length) { | 1218 | if (size > cmd->data_length) { |
| 1186 | cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; | 1219 | cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; |
| 1187 | cmd->residual_count = (size - cmd->data_length); | 1220 | cmd->residual_count = (size - cmd->data_length); |
| 1188 | } else { | 1221 | } else { |
| 1189 | cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; | 1222 | cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; |
| 1190 | cmd->residual_count = (cmd->data_length - size); | 1223 | cmd->residual_count = (cmd->data_length - size); |
| 1224 | cmd->data_length = size; | ||
| 1191 | } | 1225 | } |
| 1192 | cmd->data_length = size; | ||
| 1193 | } | 1226 | } |
| 1194 | 1227 | ||
| 1195 | return 0; | 1228 | return 0; |
| @@ -1816,61 +1849,6 @@ execute: | |||
| 1816 | EXPORT_SYMBOL(target_execute_cmd); | 1849 | EXPORT_SYMBOL(target_execute_cmd); |
| 1817 | 1850 | ||
| 1818 | /* | 1851 | /* |
| 1819 | * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd | ||
| 1820 | */ | ||
| 1821 | static int transport_get_sense_data(struct se_cmd *cmd) | ||
| 1822 | { | ||
| 1823 | unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; | ||
| 1824 | struct se_device *dev = cmd->se_dev; | ||
| 1825 | unsigned long flags; | ||
| 1826 | u32 offset = 0; | ||
| 1827 | |||
| 1828 | WARN_ON(!cmd->se_lun); | ||
| 1829 | |||
| 1830 | if (!dev) | ||
| 1831 | return 0; | ||
| 1832 | |||
| 1833 | spin_lock_irqsave(&cmd->t_state_lock, flags); | ||
| 1834 | if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { | ||
| 1835 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | ||
| 1836 | return 0; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) | ||
| 1840 | goto out; | ||
| 1841 | |||
| 1842 | if (!dev->transport->get_sense_buffer) { | ||
| 1843 | pr_err("dev->transport->get_sense_buffer is NULL\n"); | ||
| 1844 | goto out; | ||
| 1845 | } | ||
| 1846 | |||
| 1847 | sense_buffer = dev->transport->get_sense_buffer(cmd); | ||
| 1848 | if (!sense_buffer) { | ||
| 1849 | pr_err("ITT 0x%08x cmd %p: Unable to locate" | ||
| 1850 | " sense buffer for task with sense\n", | ||
| 1851 | cmd->se_tfo->get_task_tag(cmd), cmd); | ||
| 1852 | goto out; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | ||
| 1856 | |||
| 1857 | offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); | ||
| 1858 | |||
| 1859 | memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); | ||
| 1860 | |||
| 1861 | /* Automatically padded */ | ||
| 1862 | cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; | ||
| 1863 | |||
| 1864 | pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", | ||
| 1865 | dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); | ||
| 1866 | return 0; | ||
| 1867 | |||
| 1868 | out: | ||
| 1869 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | ||
| 1870 | return -1; | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | /* | ||
| 1874 | * Process all commands up to the last received ORDERED task attribute which | 1852 | * Process all commands up to the last received ORDERED task attribute which |
| 1875 | * requires another blocking boundary | 1853 | * requires another blocking boundary |
| 1876 | */ | 1854 | */ |
| @@ -1985,7 +1963,7 @@ static void transport_handle_queue_full( | |||
| 1985 | static void target_complete_ok_work(struct work_struct *work) | 1963 | static void target_complete_ok_work(struct work_struct *work) |
| 1986 | { | 1964 | { |
| 1987 | struct se_cmd *cmd = container_of(work, struct se_cmd, work); | 1965 | struct se_cmd *cmd = container_of(work, struct se_cmd, work); |
| 1988 | int reason = 0, ret; | 1966 | int ret; |
| 1989 | 1967 | ||
| 1990 | /* | 1968 | /* |
| 1991 | * Check if we need to move delayed/dormant tasks from cmds on the | 1969 | * Check if we need to move delayed/dormant tasks from cmds on the |
| @@ -2002,23 +1980,19 @@ static void target_complete_ok_work(struct work_struct *work) | |||
| 2002 | schedule_work(&cmd->se_dev->qf_work_queue); | 1980 | schedule_work(&cmd->se_dev->qf_work_queue); |
| 2003 | 1981 | ||
| 2004 | /* | 1982 | /* |
| 2005 | * Check if we need to retrieve a sense buffer from | 1983 | * Check if we need to send a sense buffer from |
| 2006 | * the struct se_cmd in question. | 1984 | * the struct se_cmd in question. |
| 2007 | */ | 1985 | */ |
| 2008 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { | 1986 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { |
| 2009 | if (transport_get_sense_data(cmd) < 0) | 1987 | WARN_ON(!cmd->scsi_status); |
| 2010 | reason = TCM_NON_EXISTENT_LUN; | 1988 | ret = transport_send_check_condition_and_sense( |
| 2011 | 1989 | cmd, 0, 1); | |
| 2012 | if (cmd->scsi_status) { | 1990 | if (ret == -EAGAIN || ret == -ENOMEM) |
| 2013 | ret = transport_send_check_condition_and_sense( | 1991 | goto queue_full; |
| 2014 | cmd, reason, 1); | ||
| 2015 | if (ret == -EAGAIN || ret == -ENOMEM) | ||
| 2016 | goto queue_full; | ||
| 2017 | 1992 | ||
| 2018 | transport_lun_remove_cmd(cmd); | 1993 | transport_lun_remove_cmd(cmd); |
| 2019 | transport_cmd_check_stop_to_fabric(cmd); | 1994 | transport_cmd_check_stop_to_fabric(cmd); |
| 2020 | return; | 1995 | return; |
| 2021 | } | ||
| 2022 | } | 1996 | } |
| 2023 | /* | 1997 | /* |
| 2024 | * Check for a callback, used by amongst other things | 1998 | * Check for a callback, used by amongst other things |
| @@ -2216,7 +2190,6 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) | |||
| 2216 | struct page **pages; | 2190 | struct page **pages; |
| 2217 | int i; | 2191 | int i; |
| 2218 | 2192 | ||
| 2219 | BUG_ON(!sg); | ||
| 2220 | /* | 2193 | /* |
| 2221 | * We need to take into account a possible offset here for fabrics like | 2194 | * We need to take into account a possible offset here for fabrics like |
| 2222 | * tcm_loop who may be using a contig buffer from the SCSI midlayer for | 2195 | * tcm_loop who may be using a contig buffer from the SCSI midlayer for |
| @@ -2224,13 +2197,17 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) | |||
| 2224 | */ | 2197 | */ |
| 2225 | if (!cmd->t_data_nents) | 2198 | if (!cmd->t_data_nents) |
| 2226 | return NULL; | 2199 | return NULL; |
| 2227 | else if (cmd->t_data_nents == 1) | 2200 | |
| 2201 | BUG_ON(!sg); | ||
| 2202 | if (cmd->t_data_nents == 1) | ||
| 2228 | return kmap(sg_page(sg)) + sg->offset; | 2203 | return kmap(sg_page(sg)) + sg->offset; |
| 2229 | 2204 | ||
| 2230 | /* >1 page. use vmap */ | 2205 | /* >1 page. use vmap */ |
| 2231 | pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); | 2206 | pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); |
| 2232 | if (!pages) | 2207 | if (!pages) { |
| 2208 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2233 | return NULL; | 2209 | return NULL; |
| 2210 | } | ||
| 2234 | 2211 | ||
| 2235 | /* convert sg[] to pages[] */ | 2212 | /* convert sg[] to pages[] */ |
| 2236 | for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { | 2213 | for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { |
| @@ -2239,8 +2216,10 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) | |||
| 2239 | 2216 | ||
| 2240 | cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); | 2217 | cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); |
| 2241 | kfree(pages); | 2218 | kfree(pages); |
| 2242 | if (!cmd->t_data_vmap) | 2219 | if (!cmd->t_data_vmap) { |
| 2220 | cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
| 2243 | return NULL; | 2221 | return NULL; |
| 2222 | } | ||
| 2244 | 2223 | ||
| 2245 | return cmd->t_data_vmap + cmd->t_data_sg[0].offset; | 2224 | return cmd->t_data_vmap + cmd->t_data_sg[0].offset; |
| 2246 | } | 2225 | } |
| @@ -2326,19 +2305,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd) | |||
| 2326 | * into the fabric for data transfers, go ahead and complete it right | 2305 | * into the fabric for data transfers, go ahead and complete it right |
| 2327 | * away. | 2306 | * away. |
| 2328 | */ | 2307 | */ |
| 2329 | if (!cmd->data_length) { | 2308 | if (!cmd->data_length && |
| 2309 | cmd->t_task_cdb[0] != REQUEST_SENSE && | ||
| 2310 | cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { | ||
| 2330 | spin_lock_irq(&cmd->t_state_lock); | 2311 | spin_lock_irq(&cmd->t_state_lock); |
| 2331 | cmd->t_state = TRANSPORT_COMPLETE; | 2312 | cmd->t_state = TRANSPORT_COMPLETE; |
| 2332 | cmd->transport_state |= CMD_T_ACTIVE; | 2313 | cmd->transport_state |= CMD_T_ACTIVE; |
| 2333 | spin_unlock_irq(&cmd->t_state_lock); | 2314 | spin_unlock_irq(&cmd->t_state_lock); |
| 2334 | 2315 | ||
| 2335 | if (cmd->t_task_cdb[0] == REQUEST_SENSE) { | ||
| 2336 | u8 ua_asc = 0, ua_ascq = 0; | ||
| 2337 | |||
| 2338 | core_scsi3_ua_clear_for_request_sense(cmd, | ||
| 2339 | &ua_asc, &ua_ascq); | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | INIT_WORK(&cmd->work, target_complete_ok_work); | 2316 | INIT_WORK(&cmd->work, target_complete_ok_work); |
| 2343 | queue_work(target_completion_wq, &cmd->work); | 2317 | queue_work(target_completion_wq, &cmd->work); |
| 2344 | return 0; | 2318 | return 0; |
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index f1405d335a96..941c84bf1065 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h | |||
| @@ -23,7 +23,9 @@ struct se_subsystem_api { | |||
| 23 | struct se_device *(*create_virtdevice)(struct se_hba *, | 23 | struct se_device *(*create_virtdevice)(struct se_hba *, |
| 24 | struct se_subsystem_dev *, void *); | 24 | struct se_subsystem_dev *, void *); |
| 25 | void (*free_device)(void *); | 25 | void (*free_device)(void *); |
| 26 | int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *); | 26 | void (*transport_complete)(struct se_cmd *cmd, |
| 27 | struct scatterlist *, | ||
| 28 | unsigned char *); | ||
| 27 | 29 | ||
| 28 | int (*parse_cdb)(struct se_cmd *cmd); | 30 | int (*parse_cdb)(struct se_cmd *cmd); |
| 29 | ssize_t (*check_configfs_dev_params)(struct se_hba *, | 31 | ssize_t (*check_configfs_dev_params)(struct se_hba *, |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 015cea01ae39..5be89373ceac 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
| @@ -121,6 +121,7 @@ | |||
| 121 | 121 | ||
| 122 | #define SE_INQUIRY_BUF 512 | 122 | #define SE_INQUIRY_BUF 512 |
| 123 | #define SE_MODE_PAGE_BUF 512 | 123 | #define SE_MODE_PAGE_BUF 512 |
| 124 | #define SE_SENSE_BUF 96 | ||
| 124 | 125 | ||
| 125 | /* struct se_hba->hba_flags */ | 126 | /* struct se_hba->hba_flags */ |
| 126 | enum hba_flags_table { | 127 | enum hba_flags_table { |
