Pull SCSI target fixes from Nicholas Bellinger: "Here are the outstanding target-pending fixes for v4.9-rc2. This includes: - Fix v4.1.y+ reference leak regression with concurrent TMR ABORT_TASK + session shutdown. (Vaibhav Tandon) - Enable tcm_fc w/ SCF_USE_CPUID to avoid host exchange timeouts (Hannes) - target/user error sense handling fixes. (Andy + MNC + HCH) - Fix iscsi-target NOP_OUT error path iscsi_cmd descriptor leak (Varun) - Two EXTENDED_COPY SCSI status fixes for ESX VAAI (Dinesh Israni + Nixon Vincent) - Revert a v4.8 residual overflow change, that breaks sg_inq with small allocation lengths. There are a number of folks stress testing the v4.1.y regression fix in their environments, and more folks doing iser-target I/O stress testing atop recent v4.x.y code. There is also one v4.2.y+ RCU conversion regression related to explicit NodeACL configfs changes, that is still being tracked down" * git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: target/tcm_fc: use CPU affinity for responses target/tcm_fc: Update debugging statements to match libfc usage target/tcm_fc: return detailed error in ft_sess_create() target/tcm_fc: print command pointer in debug message target: fix potential race window in target_sess_cmd_list_waiting() Revert "target: Fix residual overflow handling in target_complete_cmd_with_length" target: Don't override EXTENDED_COPY xcopy_pt_cmd SCSI status code target: Make EXTENDED_COPY 0xe4 failure return COPY TARGET DEVICE NOT REACHABLE target: Re-add missing SCF_ACK_KREF assignment in v4.1.y iscsi-target: fix iscsi cmd leak iscsi-target: fix spelling mistake "Unsolicitied" -> "Unsolicited" target/user: Fix comments to not refer to data ring target/user: Return an error if cmd data size is too large target/user: Use sense_reason_t in tcmu_queue_cmd_ring
Unified · Split
| @@ -1804,6 +1804,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, · 1803 unmodified lines | ||
| 1804 | 1804 | * Otherwise, initiator is not expecting a NOPIN is response. |
| 1805 | 1805 | * Just ignore for now. |
| 1806 | 1806 | */ |
| 1807 | + | |
| 1808 | + if (cmd) | |
| 1809 | + iscsit_free_cmd(cmd, false); | |
| 1810 | + | |
| 1807 | 1811 | return 0; |
| 1808 | 1812 | } |
| 1809 | 1813 | EXPORT_SYMBOL(iscsit_process_nop_out); |
| @@ -2982,7 +2986,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, · 1172 unmodified lines | ||
| 2982 | 2986 | |
| 2983 | 2987 | pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x," |
| 2984 | 2988 | " StatSN: 0x%08x, Length %u\n", (nopout_response) ? |
| 2985 | − "Solicitied" : "Unsolicitied", cmd->init_task_tag, | |
| 2989 | + "Solicited" : "Unsolicited", cmd->init_task_tag, | |
| 2986 | 2990 | cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size); |
| 2987 | 2991 | } |
| 2988 | 2992 | EXPORT_SYMBOL(iscsit_build_nopin_rsp); |
| @@ -434,7 +434,7 @@ static int iscsi_login_zero_tsih_s2( · 433 unmodified lines | ||
| 434 | 434 | |
| 435 | 435 | /* |
| 436 | 436 | * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for |
| 437 | − * Immediate Data + Unsolicitied Data-OUT if necessary.. | |
| 437 | + * Immediate Data + Unsolicited Data-OUT if necessary.. | |
| 438 | 438 | */ |
| 439 | 439 | param = iscsi_find_param_from_key("MaxRecvDataSegmentLength", |
| 440 | 440 | conn->param_list); |
| @@ -646,7 +646,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) · 205 unmodified lines | ||
| 646 | 646 | { |
| 647 | 647 | struct iscsi_session *sess = conn->sess; |
| 648 | 648 | /* |
| 649 | − * FIXME: Unsolicitied NopIN support for ISER | |
| 649 | + * FIXME: Unsolicited NopIN support for ISER | |
| 650 | 650 | */ |
| 651 | 651 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) |
| 652 | 652 | return; |
| @@ -754,15 +754,7 @@ EXPORT_SYMBOL(target_complete_cmd); · 753 unmodified lines | ||
| 754 | 754 | |
| 755 | 755 | void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) |
| 756 | 756 | { |
| 757 | − if (scsi_status != SAM_STAT_GOOD) { | |
| 758 | − return; | |
| 759 | − } | |
| 760 | − | |
| 761 | − /* | |
| 762 | − * Calculate new residual count based upon length of SCSI data | |
| 763 | − * transferred. | |
| 764 | − */ | |
| 765 | − if (length < cmd->data_length) { | |
| 757 | + if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) { | |
| 766 | 758 | if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { |
| 767 | 759 | cmd->residual_count += cmd->data_length - length; |
| 768 | 760 | } else { |
| @@ -771,12 +763,6 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len · 2 unmodified lines | ||
| 771 | 763 | } |
| 772 | 764 | |
| 773 | 765 | cmd->data_length = length; |
| 774 | − } else if (length > cmd->data_length) { | |
| 775 | − cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; | |
| 776 | − cmd->residual_count = length - cmd->data_length; | |
| 777 | − } else { | |
| 778 | − cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT); | |
| 779 | − cmd->residual_count = 0; | |
| 780 | 766 | } |
| 781 | 767 | |
| 782 | 768 | target_complete_cmd(cmd, scsi_status); |
| @@ -1706,6 +1692,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, · 923 unmodified lines | ||
| 1706 | 1692 | case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: |
| 1707 | 1693 | case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: |
| 1708 | 1694 | case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: |
| 1695 | + case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE: | |
| 1709 | 1696 | break; |
| 1710 | 1697 | case TCM_OUT_OF_RESOURCES: |
| 1711 | 1698 | sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| @@ -2547,8 +2534,12 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref) · 835 unmodified lines | ||
| 2547 | 2534 | * fabric acknowledgement that requires two target_put_sess_cmd() |
| 2548 | 2535 | * invocations before se_cmd descriptor release. |
| 2549 | 2536 | */ |
| 2550 | − if (ack_kref) | |
| 2551 | − kref_get(&se_cmd->cmd_kref); | |
| 2537 | + if (ack_kref) { | |
| 2538 | + if (!kref_get_unless_zero(&se_cmd->cmd_kref)) | |
| 2539 | + return -EINVAL; | |
| 2540 | + | |
| 2541 | + se_cmd->se_cmd_flags |= SCF_ACK_KREF; | |
| 2542 | + } | |
| 2552 | 2543 | |
| 2553 | 2544 | spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); |
| 2554 | 2545 | if (se_sess->sess_tearing_down) { |
| @@ -2627,7 +2618,7 @@ EXPORT_SYMBOL(target_put_sess_cmd); · 72 unmodified lines | ||
| 2627 | 2618 | */ |
| 2628 | 2619 | void target_sess_cmd_list_set_waiting(struct se_session *se_sess) |
| 2629 | 2620 | { |
| 2630 | − struct se_cmd *se_cmd; | |
| 2621 | + struct se_cmd *se_cmd, *tmp_cmd; | |
| 2631 | 2622 | unsigned long flags; |
| 2632 | 2623 | int rc; |
| 2633 | 2624 | |
| @@ -2639,14 +2630,16 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) · 5 unmodified lines | ||
| 2639 | 2630 | se_sess->sess_tearing_down = 1; |
| 2640 | 2631 | list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list); |
| 2641 | 2632 | |
| 2642 | − list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) { | |
| 2633 | + list_for_each_entry_safe(se_cmd, tmp_cmd, | |
| 2634 | + &se_sess->sess_wait_list, se_cmd_list) { | |
| 2643 | 2635 | rc = kref_get_unless_zero(&se_cmd->cmd_kref); |
| 2644 | 2636 | if (rc) { |
| 2645 | 2637 | se_cmd->cmd_wait_set = 1; |
| 2646 | 2638 | spin_lock(&se_cmd->t_state_lock); |
| 2647 | 2639 | se_cmd->transport_state |= CMD_T_FABRIC_STOP; |
| 2648 | 2640 | spin_unlock(&se_cmd->t_state_lock); |
| 2649 | − } | |
| 2641 | + } else | |
| 2642 | + list_del_init(&se_cmd->se_cmd_list); | |
| 2650 | 2643 | } |
| 2651 | 2644 | |
| 2652 | 2645 | spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); |
| @@ -2871,6 +2864,12 @@ static const struct sense_info sense_info_table[] = { · 218 unmodified lines | ||
| 2871 | 2864 | .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ |
| 2872 | 2865 | .add_sector_info = true, |
| 2873 | 2866 | }, |
| 2867 | + [TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = { | |
| 2868 | + .key = COPY_ABORTED, | |
| 2869 | + .asc = 0x0d, | |
| 2870 | + .ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */ | |
| 2871 | + | |
| 2872 | + }, | |
| 2874 | 2873 | [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { |
| 2875 | 2874 | /* |
| 2876 | 2875 | * Returning ILLEGAL REQUEST would cause immediate IO errors on |
| @@ -96,7 +96,7 @@ struct tcmu_dev { · 95 unmodified lines | ||
| 96 | 96 | size_t dev_size; |
| 97 | 97 | u32 cmdr_size; |
| 98 | 98 | u32 cmdr_last_cleaned; |
| 99 | − /* Offset of data ring from start of mb */ | |
| 99 | + /* Offset of data area from start of mb */ | |
| 100 | 100 | /* Must add data_off and mb_addr to get the address */ |
| 101 | 101 | size_t data_off; |
| 102 | 102 | size_t data_size; |
| @@ -349,7 +349,7 @@ static inline size_t spc_bitmap_free(unsigned long *bitmap) · 246 unmodified lines | ||
| 349 | 349 | |
| 350 | 350 | /* |
| 351 | 351 | * We can't queue a command until we have space available on the cmd ring *and* |
| 352 | − * space available on the data ring. | |
| 352 | + * space available on the data area. | |
| 353 | 353 | * |
| 354 | 354 | * Called with ring lock held. |
| 355 | 355 | */ |
| @@ -389,7 +389,8 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d · 33 unmodified lines | ||
| 389 | 389 | return true; |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | −static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |
| 392 | +static sense_reason_t | |
| 393 | +tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |
| 393 | 394 | { |
| 394 | 395 | struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; |
| 395 | 396 | struct se_cmd *se_cmd = tcmu_cmd->se_cmd; |
| @@ -405,7 +406,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) · 9 unmodified lines | ||
| 405 | 406 | DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); |
| 406 | 407 | |
| 407 | 408 | if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) |
| 408 | − return -EINVAL; | |
| 409 | + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | |
| 409 | 410 | |
| 410 | 411 | /* |
| 411 | 412 | * Must be a certain minimum size for response sense info, but |
| @@ -432,11 +433,14 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) · 20 unmodified lines | ||
| 432 | 433 | BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); |
| 433 | 434 | data_length += se_cmd->t_bidi_data_sg->length; |
| 434 | 435 | } |
| 435 | − if ((command_size > (udev->cmdr_size / 2)) | |
| 436 | − || data_length > udev->data_size) | |
| 437 | − pr_warn("TCMU: Request of size %zu/%zu may be too big for %u/%zu " | |
| 438 | − "cmd/data ring buffers\n", command_size, data_length, | |
| 436 | + if ((command_size > (udev->cmdr_size / 2)) || | |
| 437 | + data_length > udev->data_size) { | |
| 438 | + pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu " | |
| 439 | + "cmd ring/data area\n", command_size, data_length, | |
| 439 | 440 | udev->cmdr_size, udev->data_size); |
| 441 | + spin_unlock_irq(&udev->cmdr_lock); | |
| 442 | + return TCM_INVALID_CDB_FIELD; | |
| 443 | + } | |
| 440 | 444 | |
| 441 | 445 | while (!is_ring_space_avail(udev, command_size, data_length)) { |
| 442 | 446 | int ret; |
| @@ -450,7 +454,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) · 7 unmodified lines | ||
| 450 | 454 | finish_wait(&udev->wait_cmdr, &__wait); |
| 451 | 455 | if (!ret) { |
| 452 | 456 | pr_warn("tcmu: command timed out\n"); |
| 453 | − return -ETIMEDOUT; | |
| 457 | + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | |
| 454 | 458 | } |
| 455 | 459 | |
| 456 | 460 | spin_lock_irq(&udev->cmdr_lock); |
| @@ -487,9 +491,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) · 30 unmodified lines | ||
| 487 | 491 | |
| 488 | 492 | bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS); |
| 489 | 493 | |
| 490 | − /* | |
| 491 | − * Fix up iovecs, and handle if allocation in data ring wrapped. | |
| 492 | − */ | |
| 494 | + /* Handle allocating space from the data area */ | |
| 493 | 495 | iov = &entry->req.iov[0]; |
| 494 | 496 | iov_cnt = 0; |
| 495 | 497 | copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE |
| @@ -526,10 +528,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) · 30 unmodified lines | ||
| 526 | 528 | mod_timer(&udev->timeout, |
| 527 | 529 | round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT))); |
| 528 | 530 | |
| 529 | − return 0; | |
| 531 | + return TCM_NO_SENSE; | |
| 530 | 532 | } |
| 531 | 533 | |
| 532 | −static int tcmu_queue_cmd(struct se_cmd *se_cmd) | |
| 534 | +static sense_reason_t | |
| 535 | +tcmu_queue_cmd(struct se_cmd *se_cmd) | |
| 533 | 536 | { |
| 534 | 537 | struct se_device *se_dev = se_cmd->se_dev; |
| 535 | 538 | struct tcmu_dev *udev = TCMU_DEV(se_dev); |
| @@ -538,10 +541,10 @@ static int tcmu_queue_cmd(struct se_cmd *se_cmd) · 2 unmodified lines | ||
| 538 | 541 | |
| 539 | 542 | tcmu_cmd = tcmu_alloc_cmd(se_cmd); |
| 540 | 543 | if (!tcmu_cmd) |
| 541 | − return -ENOMEM; | |
| 544 | + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | |
| 542 | 545 | |
| 543 | 546 | ret = tcmu_queue_cmd_ring(tcmu_cmd); |
| 544 | − if (ret < 0) { | |
| 547 | + if (ret != TCM_NO_SENSE) { | |
| 545 | 548 | pr_err("TCMU: Could not queue command\n"); |
| 546 | 549 | spin_lock_irq(&udev->commands_lock); |
| 547 | 550 | idr_remove(&udev->commands, tcmu_cmd->cmd_id); |
| @@ -561,7 +564,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry * · 13 unmodified lines | ||
| 561 | 564 | if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { |
| 562 | 565 | /* |
| 563 | 566 | * cmd has been completed already from timeout, just reclaim |
| 564 | − * data ring space and free cmd | |
| 567 | + * data area space and free cmd | |
| 565 | 568 | */ |
| 566 | 569 | free_data_area(udev, cmd); |
| 567 | 570 | |
| @@ -1128,21 +1131,10 @@ static sector_t tcmu_get_blocks(struct se_device *dev) · 560 unmodified lines | ||
| 1128 | 1131 | dev->dev_attrib.block_size); |
| 1129 | 1132 | } |
| 1130 | 1133 | |
| 1131 | −static sense_reason_t | |
| 1132 | −tcmu_pass_op(struct se_cmd *se_cmd) | |
| 1133 | −{ | |
| 1134 | − int ret = tcmu_queue_cmd(se_cmd); | |
| 1135 | − | |
| 1136 | − if (ret != 0) | |
| 1137 | − return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | |
| 1138 | − else | |
| 1139 | − return TCM_NO_SENSE; | |
| 1140 | −} | |
| 1141 | − | |
| 1142 | 1134 | static sense_reason_t |
| 1143 | 1135 | tcmu_parse_cdb(struct se_cmd *cmd) |
| 1144 | 1136 | { |
| 1145 | − return passthrough_parse_cdb(cmd, tcmu_pass_op); | |
| 1137 | + return passthrough_parse_cdb(cmd, tcmu_queue_cmd); | |
| 1146 | 1138 | } |
| 1147 | 1139 | |
| 1148 | 1140 | static const struct target_backend_ops tcmu_ops = { |
| @@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op · 103 unmodified lines | ||
| 104 | 104 | } |
| 105 | 105 | mutex_unlock(&g_device_mutex); |
| 106 | 106 | |
| 107 | − pr_err("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); | |
| 107 | + pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); | |
| 108 | 108 | return -EINVAL; |
| 109 | 109 | } |
| 110 | 110 | |
| @@ -185,7 +185,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op · 74 unmodified lines | ||
| 185 | 185 | |
| 186 | 186 | static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, |
| 187 | 187 | struct xcopy_op *xop, unsigned char *p, |
| 188 | − unsigned short tdll) | |
| 188 | + unsigned short tdll, sense_reason_t *sense_ret) | |
| 189 | 189 | { |
| 190 | 190 | struct se_device *local_dev = se_cmd->se_dev; |
| 191 | 191 | unsigned char *desc = p; |
| @@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, · 1 unmodified line | ||
| 193 | 193 | unsigned short start = 0; |
| 194 | 194 | bool src = true; |
| 195 | 195 | |
| 196 | + *sense_ret = TCM_INVALID_PARAMETER_LIST; | |
| 197 | + | |
| 196 | 198 | if (offset != 0) { |
| 197 | 199 | pr_err("XCOPY target descriptor list length is not" |
| 198 | 200 | " multiple of %d\n", XCOPY_TARGET_DESC_LEN); |
| @@ -243,9 +245,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, · 44 unmodified lines | ||
| 243 | 245 | rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); |
| 244 | 246 | else |
| 245 | 247 | rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); |
| 246 | − | |
| 247 | − if (rc < 0) | |
| 248 | + /* | |
| 249 | + * If a matching IEEE NAA 0x83 descriptor for the requested device | |
| 250 | + * is not located on this node, return COPY_ABORTED with ASQ/ASQC | |
| 251 | + * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the | |
| 252 | + * initiator to fall back to normal copy method. | |
| 253 | + */ | |
| 254 | + if (rc < 0) { | |
| 255 | + *sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE; | |
| 248 | 256 | goto out; |
| 257 | + } | |
| 249 | 258 | |
| 250 | 259 | pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n", |
| 251 | 260 | xop->src_dev, &xop->src_tid_wwn[0]); |
| @@ -653,6 +662,7 @@ static int target_xcopy_read_source( · 401 unmodified lines | ||
| 653 | 662 | rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0], |
| 654 | 663 | remote_port, true); |
| 655 | 664 | if (rc < 0) { |
| 665 | + ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | |
| 656 | 666 | transport_generic_free_cmd(se_cmd, 0); |
| 657 | 667 | return rc; |
| 658 | 668 | } |
| @@ -664,6 +674,7 @@ static int target_xcopy_read_source( · 5 unmodified lines | ||
| 664 | 674 | |
| 665 | 675 | rc = target_xcopy_issue_pt_cmd(xpt_cmd); |
| 666 | 676 | if (rc < 0) { |
| 677 | + ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | |
| 667 | 678 | transport_generic_free_cmd(se_cmd, 0); |
| 668 | 679 | return rc; |
| 669 | 680 | } |
| @@ -714,6 +725,7 @@ static int target_xcopy_write_destination( · 44 unmodified lines | ||
| 714 | 725 | remote_port, false); |
| 715 | 726 | if (rc < 0) { |
| 716 | 727 | struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd; |
| 728 | + ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | |
| 717 | 729 | /* |
| 718 | 730 | * If the failure happened before the t_mem_list hand-off in |
| 719 | 731 | * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that |
| @@ -729,6 +741,7 @@ static int target_xcopy_write_destination( · 9 unmodified lines | ||
| 729 | 741 | |
| 730 | 742 | rc = target_xcopy_issue_pt_cmd(xpt_cmd); |
| 731 | 743 | if (rc < 0) { |
| 744 | + ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | |
| 732 | 745 | se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; |
| 733 | 746 | transport_generic_free_cmd(se_cmd, 0); |
| 734 | 747 | return rc; |
| @@ -815,9 +828,14 @@ static void target_xcopy_do_work(struct work_struct *work) · 80 unmodified lines | ||
| 815 | 828 | out: |
| 816 | 829 | xcopy_pt_undepend_remotedev(xop); |
| 817 | 830 | kfree(xop); |
| 818 | − | |
| 819 | − pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n"); | |
| 820 | − ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; | |
| 831 | + /* | |
| 832 | + * Don't override an error scsi status if it has already been set | |
| 833 | + */ | |
| 834 | + if (ec_cmd->scsi_status == SAM_STAT_GOOD) { | |
| 835 | + pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY" | |
| 836 | + " CHECK_CONDITION -> sending response\n", rc); | |
| 837 | + ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; | |
| 838 | + } | |
| 821 | 839 | target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION); |
| 822 | 840 | } |
| 823 | 841 | |
| @@ -875,7 +893,7 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) · 51 unmodified lines | ||
| 875 | 893 | " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, |
| 876 | 894 | tdll, sdll, inline_dl); |
| 877 | 895 | |
| 878 | − rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll); | |
| 896 | + rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret); | |
| 879 | 897 | if (rc <= 0) |
| 880 | 898 | goto out; |
| 881 | 899 | |
| @@ -572,10 +572,10 @@ static void ft_send_work(struct work_struct *work) · 571 unmodified lines | ||
| 572 | 572 | if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, |
| 573 | 573 | &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), |
| 574 | 574 | ntohl(fcp->fc_dl), task_attr, data_dir, |
| 575 | − TARGET_SCF_ACK_KREF)) | |
| 575 | + TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID)) | |
| 576 | 576 | goto err; |
| 577 | 577 | |
| 578 | − pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl); | |
| 578 | + pr_debug("r_ctl %x target_submit_cmd %p\n", fh->fh_r_ctl, cmd); | |
| 579 | 579 | return; |
| 580 | 580 | |
| 581 | 581 | err: |
| @@ -39,6 +39,11 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #include "tcm_fc.h" |
| 41 | 41 | |
| 42 | +#define TFC_SESS_DBG(lport, fmt, args...) \ | |
| 43 | + pr_debug("host%u: rport %6.6x: " fmt, \ | |
| 44 | + (lport)->host->host_no, \ | |
| 45 | + (lport)->port_id, ##args ) | |
| 46 | + | |
| 42 | 47 | static void ft_sess_delete_all(struct ft_tport *); |
| 43 | 48 | |
| 44 | 49 | /* |
| @@ -167,24 +172,29 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) · 122 unmodified lines | ||
| 167 | 172 | struct ft_tport *tport; |
| 168 | 173 | struct hlist_head *head; |
| 169 | 174 | struct ft_sess *sess; |
| 175 | + char *reason = "no session created"; | |
| 170 | 176 | |
| 171 | 177 | rcu_read_lock(); |
| 172 | 178 | tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); |
| 173 | − if (!tport) | |
| 179 | + if (!tport) { | |
| 180 | + reason = "not an FCP port"; | |
| 174 | 181 | goto out; |
| 182 | + } | |
| 175 | 183 | |
| 176 | 184 | head = &tport->hash[ft_sess_hash(port_id)]; |
| 177 | 185 | hlist_for_each_entry_rcu(sess, head, hash) { |
| 178 | 186 | if (sess->port_id == port_id) { |
| 179 | 187 | kref_get(&sess->kref); |
| 180 | 188 | rcu_read_unlock(); |
| 181 | − pr_debug("port_id %x found %p\n", port_id, sess); | |
| 189 | + TFC_SESS_DBG(lport, "port_id %x found %p\n", | |
| 190 | + port_id, sess); | |
| 182 | 191 | return sess; |
| 183 | 192 | } |
| 184 | 193 | } |
| 185 | 194 | out: |
| 186 | 195 | rcu_read_unlock(); |
| 187 | − pr_debug("port_id %x not found\n", port_id); | |
| 196 | + TFC_SESS_DBG(lport, "port_id %x not found, %s\n", | |
| 197 | + port_id, reason); | |
| 188 | 198 | return NULL; |
| 189 | 199 | } |
| 190 | 200 | |
| @@ -195,7 +205,7 @@ static int ft_sess_alloc_cb(struct se_portal_group *se_tpg, · 4 unmodified lines | ||
| 195 | 205 | struct ft_tport *tport = sess->tport; |
| 196 | 206 | struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)]; |
| 197 | 207 | |
| 198 | − pr_debug("port_id %x sess %p\n", sess->port_id, sess); | |
| 208 | + TFC_SESS_DBG(tport->lport, "port_id %x sess %p\n", sess->port_id, sess); | |
| 199 | 209 | hlist_add_head_rcu(&sess->hash, head); |
| 200 | 210 | tport->sess_count++; |
| 201 | 211 | |
| @@ -223,7 +233,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, · 21 unmodified lines | ||
| 223 | 233 | |
| 224 | 234 | sess = kzalloc(sizeof(*sess), GFP_KERNEL); |
| 225 | 235 | if (!sess) |
| 226 | − return NULL; | |
| 236 | + return ERR_PTR(-ENOMEM); | |
| 227 | 237 | |
| 228 | 238 | kref_init(&sess->kref); /* ref for table entry */ |
| 229 | 239 | sess->tport = tport; |
| @@ -234,8 +244,9 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, · 4 unmodified lines | ||
| 234 | 244 | TARGET_PROT_NORMAL, &initiatorname[0], |
| 235 | 245 | sess, ft_sess_alloc_cb); |
| 236 | 246 | if (IS_ERR(sess->se_sess)) { |
| 247 | + int rc = PTR_ERR(sess->se_sess); | |
| 237 | 248 | kfree(sess); |
| 238 | − return NULL; | |
| 249 | + sess = ERR_PTR(rc); | |
| 239 | 250 | } |
| 240 | 251 | return sess; |
| 241 | 252 | } |
| @@ -319,7 +330,7 @@ void ft_sess_close(struct se_session *se_sess) · 77 unmodified lines | ||
| 319 | 330 | mutex_unlock(&ft_lport_lock); |
| 320 | 331 | return; |
| 321 | 332 | } |
| 322 | − pr_debug("port_id %x\n", port_id); | |
| 333 | + TFC_SESS_DBG(sess->tport->lport, "port_id %x close session\n", port_id); | |
| 323 | 334 | ft_sess_unhash(sess); |
| 324 | 335 | mutex_unlock(&ft_lport_lock); |
| 325 | 336 | ft_close_sess(sess); |
| @@ -379,8 +390,13 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, · 53 unmodified lines | ||
| 379 | 390 | if (!(fcp_parm & FCP_SPPF_INIT_FCN)) |
| 380 | 391 | return FC_SPP_RESP_CONF; |
| 381 | 392 | sess = ft_sess_create(tport, rdata->ids.port_id, rdata); |
| 382 | − if (!sess) | |
| 383 | − return FC_SPP_RESP_RES; | |
| 393 | + if (IS_ERR(sess)) { | |
| 394 | + if (PTR_ERR(sess) == -EACCES) { | |
| 395 | + spp->spp_flags &= ~FC_SPP_EST_IMG_PAIR; | |
| 396 | + return FC_SPP_RESP_CONF; | |
| 397 | + } else | |
| 398 | + return FC_SPP_RESP_RES; | |
| 399 | + } | |
| 384 | 400 | if (!sess->params) |
| 385 | 401 | rdata->prli_count++; |
| 386 | 402 | sess->params = fcp_parm; |
| @@ -423,8 +439,8 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, · 36 unmodified lines | ||
| 423 | 439 | mutex_lock(&ft_lport_lock); |
| 424 | 440 | ret = ft_prli_locked(rdata, spp_len, rspp, spp); |
| 425 | 441 | mutex_unlock(&ft_lport_lock); |
| 426 | − pr_debug("port_id %x flags %x ret %x\n", | |
| 427 | − rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); | |
| 442 | + TFC_SESS_DBG(rdata->local_port, "port_id %x flags %x ret %x\n", | |
| 443 | + rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); | |
| 428 | 444 | return ret; |
| 429 | 445 | } |
| 430 | 446 | |
| @@ -477,11 +493,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) · 46 unmodified lines | ||
| 477 | 493 | struct ft_sess *sess; |
| 478 | 494 | u32 sid = fc_frame_sid(fp); |
| 479 | 495 | |
| 480 | − pr_debug("sid %x\n", sid); | |
| 496 | + TFC_SESS_DBG(lport, "recv sid %x\n", sid); | |
| 481 | 497 | |
| 482 | 498 | sess = ft_sess_get(lport, sid); |
| 483 | 499 | if (!sess) { |
| 484 | − pr_debug("sid %x sess lookup failed\n", sid); | |
| 500 | + TFC_SESS_DBG(lport, "sid %x sess lookup failed\n", sid); | |
| 485 | 501 | /* TBD XXX - if FCP_CMND, send PRLO */ |
| 486 | 502 | fc_frame_free(fp); |
| 487 | 503 | return; |
| @@ -177,6 +177,7 @@ enum tcm_sense_reason_table { · 176 unmodified lines | ||
| 177 | 177 | TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), |
| 178 | 178 | TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), |
| 179 | 179 | TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), |
| 180 | + TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18), | |
| 180 | 181 | #undef R |
| 181 | 182 | }; |
| 182 | 183 | |