diff options
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 6 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 4 | ||||
| -rw-r--r-- | drivers/target/target_core_transport.c | 39 | ||||
| -rw-r--r-- | drivers/target/target_core_user.c | 50 | ||||
| -rw-r--r-- | drivers/target/target_core_xcopy.c | 34 | ||||
| -rw-r--r-- | drivers/target/tcm_fc/tfc_cmd.c | 4 | ||||
| -rw-r--r-- | drivers/target/tcm_fc/tfc_sess.c | 42 | ||||
| -rw-r--r-- | include/target/target_core_base.h | 1 |
8 files changed, 105 insertions, 75 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 39b928c2849d..b7d747e92c7a 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
| @@ -1804,6 +1804,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
| 1804 | * Otherwise, initiator is not expecting a NOPIN is response. | 1804 | * Otherwise, initiator is not expecting a NOPIN is response. |
| 1805 | * Just ignore for now. | 1805 | * Just ignore for now. |
| 1806 | */ | 1806 | */ |
| 1807 | |||
| 1808 | if (cmd) | ||
| 1809 | iscsit_free_cmd(cmd, false); | ||
| 1810 | |||
| 1807 | return 0; | 1811 | return 0; |
| 1808 | } | 1812 | } |
| 1809 | EXPORT_SYMBOL(iscsit_process_nop_out); | 1813 | EXPORT_SYMBOL(iscsit_process_nop_out); |
| @@ -2982,7 +2986,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, | |||
| 2982 | 2986 | ||
| 2983 | pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x," | 2987 | pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x," |
| 2984 | " StatSN: 0x%08x, Length %u\n", (nopout_response) ? | 2988 | " StatSN: 0x%08x, Length %u\n", (nopout_response) ? |
| 2985 | "Solicitied" : "Unsolicitied", cmd->init_task_tag, | 2989 | "Solicited" : "Unsolicited", cmd->init_task_tag, |
| 2986 | cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size); | 2990 | cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size); |
| 2987 | } | 2991 | } |
| 2988 | EXPORT_SYMBOL(iscsit_build_nopin_rsp); | 2992 | EXPORT_SYMBOL(iscsit_build_nopin_rsp); |
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index adf419fa4291..15f79a2ca34a 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
| @@ -434,7 +434,7 @@ static int iscsi_login_zero_tsih_s2( | |||
| 434 | 434 | ||
| 435 | /* | 435 | /* |
| 436 | * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for | 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 | param = iscsi_find_param_from_key("MaxRecvDataSegmentLength", | 439 | param = iscsi_find_param_from_key("MaxRecvDataSegmentLength", |
| 440 | conn->param_list); | 440 | conn->param_list); |
| @@ -646,7 +646,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) | |||
| 646 | { | 646 | { |
| 647 | struct iscsi_session *sess = conn->sess; | 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 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) | 651 | if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) |
| 652 | return; | 652 | return; |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 6094a6beddde..7dfefd66df93 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -754,15 +754,7 @@ EXPORT_SYMBOL(target_complete_cmd); | |||
| 754 | 754 | ||
| 755 | void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) | 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) { | 757 | if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) { |
| 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) { | ||
| 766 | if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { | 758 | if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { |
| 767 | cmd->residual_count += cmd->data_length - length; | 759 | cmd->residual_count += cmd->data_length - length; |
| 768 | } else { | 760 | } else { |
| @@ -771,12 +763,6 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len | |||
| 771 | } | 763 | } |
| 772 | 764 | ||
| 773 | cmd->data_length = length; | 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 | target_complete_cmd(cmd, scsi_status); | 768 | target_complete_cmd(cmd, scsi_status); |
| @@ -1706,6 +1692,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, | |||
| 1706 | case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: | 1692 | case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: |
| 1707 | case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: | 1693 | case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: |
| 1708 | case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: | 1694 | case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: |
| 1695 | case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE: | ||
| 1709 | break; | 1696 | break; |
| 1710 | case TCM_OUT_OF_RESOURCES: | 1697 | case TCM_OUT_OF_RESOURCES: |
| 1711 | sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 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) | |||
| 2547 | * fabric acknowledgement that requires two target_put_sess_cmd() | 2534 | * fabric acknowledgement that requires two target_put_sess_cmd() |
| 2548 | * invocations before se_cmd descriptor release. | 2535 | * invocations before se_cmd descriptor release. |
| 2549 | */ | 2536 | */ |
| 2550 | if (ack_kref) | 2537 | if (ack_kref) { |
| 2551 | kref_get(&se_cmd->cmd_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 | spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); | 2544 | spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); |
| 2554 | if (se_sess->sess_tearing_down) { | 2545 | if (se_sess->sess_tearing_down) { |
| @@ -2627,7 +2618,7 @@ EXPORT_SYMBOL(target_put_sess_cmd); | |||
| 2627 | */ | 2618 | */ |
| 2628 | void target_sess_cmd_list_set_waiting(struct se_session *se_sess) | 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 | unsigned long flags; | 2622 | unsigned long flags; |
| 2632 | int rc; | 2623 | int rc; |
| 2633 | 2624 | ||
| @@ -2639,14 +2630,16 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) | |||
| 2639 | se_sess->sess_tearing_down = 1; | 2630 | se_sess->sess_tearing_down = 1; |
| 2640 | list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list); | 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 | rc = kref_get_unless_zero(&se_cmd->cmd_kref); | 2635 | rc = kref_get_unless_zero(&se_cmd->cmd_kref); |
| 2644 | if (rc) { | 2636 | if (rc) { |
| 2645 | se_cmd->cmd_wait_set = 1; | 2637 | se_cmd->cmd_wait_set = 1; |
| 2646 | spin_lock(&se_cmd->t_state_lock); | 2638 | spin_lock(&se_cmd->t_state_lock); |
| 2647 | se_cmd->transport_state |= CMD_T_FABRIC_STOP; | 2639 | se_cmd->transport_state |= CMD_T_FABRIC_STOP; |
| 2648 | spin_unlock(&se_cmd->t_state_lock); | 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 | spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); | 2645 | spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); |
| @@ -2871,6 +2864,12 @@ static const struct sense_info sense_info_table[] = { | |||
| 2871 | .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ | 2864 | .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ |
| 2872 | .add_sector_info = true, | 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 | [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { | 2873 | [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { |
| 2875 | /* | 2874 | /* |
| 2876 | * Returning ILLEGAL REQUEST would cause immediate IO errors on | 2875 | * Returning ILLEGAL REQUEST would cause immediate IO errors on |
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 62bf4fe5704a..47562509b489 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c | |||
| @@ -96,7 +96,7 @@ struct tcmu_dev { | |||
| 96 | size_t dev_size; | 96 | size_t dev_size; |
| 97 | u32 cmdr_size; | 97 | u32 cmdr_size; |
| 98 | u32 cmdr_last_cleaned; | 98 | u32 cmdr_last_cleaned; |
| 99 | /* Offset of data ring from start of mb */ | 99 | /* Offset of data area from start of mb */ |
| 100 | /* Must add data_off and mb_addr to get the address */ | 100 | /* Must add data_off and mb_addr to get the address */ |
| 101 | size_t data_off; | 101 | size_t data_off; |
| 102 | size_t data_size; | 102 | size_t data_size; |
| @@ -349,7 +349,7 @@ static inline size_t spc_bitmap_free(unsigned long *bitmap) | |||
| 349 | 349 | ||
| 350 | /* | 350 | /* |
| 351 | * We can't queue a command until we have space available on the cmd ring *and* | 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 | * Called with ring lock held. | 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 | |||
| 389 | return true; | 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 | struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; | 395 | struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; |
| 395 | struct se_cmd *se_cmd = tcmu_cmd->se_cmd; | 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) | |||
| 405 | DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); | 406 | DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); |
| 406 | 407 | ||
| 407 | if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) | 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 | * Must be a certain minimum size for response sense info, but | 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) | |||
| 432 | BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); | 433 | BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); |
| 433 | data_length += se_cmd->t_bidi_data_sg->length; | 434 | data_length += se_cmd->t_bidi_data_sg->length; |
| 434 | } | 435 | } |
| 435 | if ((command_size > (udev->cmdr_size / 2)) | 436 | if ((command_size > (udev->cmdr_size / 2)) || |
| 436 | || data_length > udev->data_size) | 437 | data_length > udev->data_size) { |
| 437 | pr_warn("TCMU: Request of size %zu/%zu may be too big for %u/%zu " | 438 | pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu " |
| 438 | "cmd/data ring buffers\n", command_size, data_length, | 439 | "cmd ring/data area\n", command_size, data_length, |
| 439 | udev->cmdr_size, udev->data_size); | 440 | udev->cmdr_size, udev->data_size); |
| 441 | spin_unlock_irq(&udev->cmdr_lock); | ||
| 442 | return TCM_INVALID_CDB_FIELD; | ||
| 443 | } | ||
| 440 | 444 | ||
| 441 | while (!is_ring_space_avail(udev, command_size, data_length)) { | 445 | while (!is_ring_space_avail(udev, command_size, data_length)) { |
| 442 | int ret; | 446 | int ret; |
| @@ -450,7 +454,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |||
| 450 | finish_wait(&udev->wait_cmdr, &__wait); | 454 | finish_wait(&udev->wait_cmdr, &__wait); |
| 451 | if (!ret) { | 455 | if (!ret) { |
| 452 | pr_warn("tcmu: command timed out\n"); | 456 | pr_warn("tcmu: command timed out\n"); |
| 453 | return -ETIMEDOUT; | 457 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 454 | } | 458 | } |
| 455 | 459 | ||
| 456 | spin_lock_irq(&udev->cmdr_lock); | 460 | spin_lock_irq(&udev->cmdr_lock); |
| @@ -487,9 +491,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |||
| 487 | 491 | ||
| 488 | bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS); | 492 | bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS); |
| 489 | 493 | ||
| 490 | /* | 494 | /* Handle allocating space from the data area */ |
| 491 | * Fix up iovecs, and handle if allocation in data ring wrapped. | ||
| 492 | */ | ||
| 493 | iov = &entry->req.iov[0]; | 495 | iov = &entry->req.iov[0]; |
| 494 | iov_cnt = 0; | 496 | iov_cnt = 0; |
| 495 | copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE | 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) | |||
| 526 | mod_timer(&udev->timeout, | 528 | mod_timer(&udev->timeout, |
| 527 | round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT))); | 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 | struct se_device *se_dev = se_cmd->se_dev; | 537 | struct se_device *se_dev = se_cmd->se_dev; |
| 535 | struct tcmu_dev *udev = TCMU_DEV(se_dev); | 538 | struct tcmu_dev *udev = TCMU_DEV(se_dev); |
| @@ -538,10 +541,10 @@ static int tcmu_queue_cmd(struct se_cmd *se_cmd) | |||
| 538 | 541 | ||
| 539 | tcmu_cmd = tcmu_alloc_cmd(se_cmd); | 542 | tcmu_cmd = tcmu_alloc_cmd(se_cmd); |
| 540 | if (!tcmu_cmd) | 543 | if (!tcmu_cmd) |
| 541 | return -ENOMEM; | 544 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 542 | 545 | ||
| 543 | ret = tcmu_queue_cmd_ring(tcmu_cmd); | 546 | ret = tcmu_queue_cmd_ring(tcmu_cmd); |
| 544 | if (ret < 0) { | 547 | if (ret != TCM_NO_SENSE) { |
| 545 | pr_err("TCMU: Could not queue command\n"); | 548 | pr_err("TCMU: Could not queue command\n"); |
| 546 | spin_lock_irq(&udev->commands_lock); | 549 | spin_lock_irq(&udev->commands_lock); |
| 547 | idr_remove(&udev->commands, tcmu_cmd->cmd_id); | 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 * | |||
| 561 | if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { | 564 | if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { |
| 562 | /* | 565 | /* |
| 563 | * cmd has been completed already from timeout, just reclaim | 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 | free_data_area(udev, cmd); | 569 | free_data_area(udev, cmd); |
| 567 | 570 | ||
| @@ -1129,20 +1132,9 @@ static sector_t tcmu_get_blocks(struct se_device *dev) | |||
| 1129 | } | 1132 | } |
| 1130 | 1133 | ||
| 1131 | static sense_reason_t | 1134 | 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 | static sense_reason_t | ||
| 1143 | tcmu_parse_cdb(struct se_cmd *cmd) | 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 | static const struct target_backend_ops tcmu_ops = { | 1140 | static const struct target_backend_ops tcmu_ops = { |
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 75cd85426ae3..094a1440eacb 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c | |||
| @@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op | |||
| 104 | } | 104 | } |
| 105 | mutex_unlock(&g_device_mutex); | 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 | return -EINVAL; | 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 | |||
| 185 | 185 | ||
| 186 | static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, | 186 | static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, |
| 187 | struct xcopy_op *xop, unsigned char *p, | 187 | struct xcopy_op *xop, unsigned char *p, |
| 188 | unsigned short tdll) | 188 | unsigned short tdll, sense_reason_t *sense_ret) |
| 189 | { | 189 | { |
| 190 | struct se_device *local_dev = se_cmd->se_dev; | 190 | struct se_device *local_dev = se_cmd->se_dev; |
| 191 | unsigned char *desc = p; | 191 | unsigned char *desc = p; |
| @@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, | |||
| 193 | unsigned short start = 0; | 193 | unsigned short start = 0; |
| 194 | bool src = true; | 194 | bool src = true; |
| 195 | 195 | ||
| 196 | *sense_ret = TCM_INVALID_PARAMETER_LIST; | ||
| 197 | |||
| 196 | if (offset != 0) { | 198 | if (offset != 0) { |
| 197 | pr_err("XCOPY target descriptor list length is not" | 199 | pr_err("XCOPY target descriptor list length is not" |
| 198 | " multiple of %d\n", XCOPY_TARGET_DESC_LEN); | 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, | |||
| 243 | rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); | 245 | rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); |
| 244 | else | 246 | else |
| 245 | rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); | 247 | rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); |
| 246 | 248 | /* | |
| 247 | if (rc < 0) | 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 | goto out; | 256 | goto out; |
| 257 | } | ||
| 249 | 258 | ||
| 250 | pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n", | 259 | pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n", |
| 251 | xop->src_dev, &xop->src_tid_wwn[0]); | 260 | xop->src_dev, &xop->src_tid_wwn[0]); |
| @@ -653,6 +662,7 @@ static int target_xcopy_read_source( | |||
| 653 | rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0], | 662 | rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0], |
| 654 | remote_port, true); | 663 | remote_port, true); |
| 655 | if (rc < 0) { | 664 | if (rc < 0) { |
| 665 | ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | ||
| 656 | transport_generic_free_cmd(se_cmd, 0); | 666 | transport_generic_free_cmd(se_cmd, 0); |
| 657 | return rc; | 667 | return rc; |
| 658 | } | 668 | } |
| @@ -664,6 +674,7 @@ static int target_xcopy_read_source( | |||
| 664 | 674 | ||
| 665 | rc = target_xcopy_issue_pt_cmd(xpt_cmd); | 675 | rc = target_xcopy_issue_pt_cmd(xpt_cmd); |
| 666 | if (rc < 0) { | 676 | if (rc < 0) { |
| 677 | ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | ||
| 667 | transport_generic_free_cmd(se_cmd, 0); | 678 | transport_generic_free_cmd(se_cmd, 0); |
| 668 | return rc; | 679 | return rc; |
| 669 | } | 680 | } |
| @@ -714,6 +725,7 @@ static int target_xcopy_write_destination( | |||
| 714 | remote_port, false); | 725 | remote_port, false); |
| 715 | if (rc < 0) { | 726 | if (rc < 0) { |
| 716 | struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd; | 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 | * If the failure happened before the t_mem_list hand-off in | 730 | * If the failure happened before the t_mem_list hand-off in |
| 719 | * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that | 731 | * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that |
| @@ -729,6 +741,7 @@ static int target_xcopy_write_destination( | |||
| 729 | 741 | ||
| 730 | rc = target_xcopy_issue_pt_cmd(xpt_cmd); | 742 | rc = target_xcopy_issue_pt_cmd(xpt_cmd); |
| 731 | if (rc < 0) { | 743 | if (rc < 0) { |
| 744 | ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status; | ||
| 732 | se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; | 745 | se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; |
| 733 | transport_generic_free_cmd(se_cmd, 0); | 746 | transport_generic_free_cmd(se_cmd, 0); |
| 734 | return rc; | 747 | return rc; |
| @@ -815,9 +828,14 @@ static void target_xcopy_do_work(struct work_struct *work) | |||
| 815 | out: | 828 | out: |
| 816 | xcopy_pt_undepend_remotedev(xop); | 829 | xcopy_pt_undepend_remotedev(xop); |
| 817 | kfree(xop); | 830 | kfree(xop); |
| 818 | 831 | /* | |
| 819 | pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n"); | 832 | * Don't override an error scsi status if it has already been set |
| 820 | ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; | 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 | target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION); | 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) | |||
| 875 | " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, | 893 | " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, |
| 876 | tdll, sdll, inline_dl); | 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 | if (rc <= 0) | 897 | if (rc <= 0) |
| 880 | goto out; | 898 | goto out; |
| 881 | 899 | ||
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 216e18cc9133..ff5de9a96643 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
| @@ -572,10 +572,10 @@ static void ft_send_work(struct work_struct *work) | |||
| 572 | if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, | 572 | if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, |
| 573 | &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), | 573 | &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), |
| 574 | ntohl(fcp->fc_dl), task_attr, data_dir, | 574 | ntohl(fcp->fc_dl), task_attr, data_dir, |
| 575 | TARGET_SCF_ACK_KREF)) | 575 | TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID)) |
| 576 | goto err; | 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 | return; | 579 | return; |
| 580 | 580 | ||
| 581 | err: | 581 | err: |
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 6ffbb603d912..fd5c3de79470 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c | |||
| @@ -39,6 +39,11 @@ | |||
| 39 | 39 | ||
| 40 | #include "tcm_fc.h" | 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 | static void ft_sess_delete_all(struct ft_tport *); | 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) | |||
| 167 | struct ft_tport *tport; | 172 | struct ft_tport *tport; |
| 168 | struct hlist_head *head; | 173 | struct hlist_head *head; |
| 169 | struct ft_sess *sess; | 174 | struct ft_sess *sess; |
| 175 | char *reason = "no session created"; | ||
| 170 | 176 | ||
| 171 | rcu_read_lock(); | 177 | rcu_read_lock(); |
| 172 | tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); | 178 | tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); |
| 173 | if (!tport) | 179 | if (!tport) { |
| 180 | reason = "not an FCP port"; | ||
| 174 | goto out; | 181 | goto out; |
| 182 | } | ||
| 175 | 183 | ||
| 176 | head = &tport->hash[ft_sess_hash(port_id)]; | 184 | head = &tport->hash[ft_sess_hash(port_id)]; |
| 177 | hlist_for_each_entry_rcu(sess, head, hash) { | 185 | hlist_for_each_entry_rcu(sess, head, hash) { |
| 178 | if (sess->port_id == port_id) { | 186 | if (sess->port_id == port_id) { |
| 179 | kref_get(&sess->kref); | 187 | kref_get(&sess->kref); |
| 180 | rcu_read_unlock(); | 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 | return sess; | 191 | return sess; |
| 183 | } | 192 | } |
| 184 | } | 193 | } |
| 185 | out: | 194 | out: |
| 186 | rcu_read_unlock(); | 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 | return NULL; | 198 | return NULL; |
| 189 | } | 199 | } |
| 190 | 200 | ||
| @@ -195,7 +205,7 @@ static int ft_sess_alloc_cb(struct se_portal_group *se_tpg, | |||
| 195 | struct ft_tport *tport = sess->tport; | 205 | struct ft_tport *tport = sess->tport; |
| 196 | struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)]; | 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 | hlist_add_head_rcu(&sess->hash, head); | 209 | hlist_add_head_rcu(&sess->hash, head); |
| 200 | tport->sess_count++; | 210 | tport->sess_count++; |
| 201 | 211 | ||
| @@ -223,7 +233,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, | |||
| 223 | 233 | ||
| 224 | sess = kzalloc(sizeof(*sess), GFP_KERNEL); | 234 | sess = kzalloc(sizeof(*sess), GFP_KERNEL); |
| 225 | if (!sess) | 235 | if (!sess) |
| 226 | return NULL; | 236 | return ERR_PTR(-ENOMEM); |
| 227 | 237 | ||
| 228 | kref_init(&sess->kref); /* ref for table entry */ | 238 | kref_init(&sess->kref); /* ref for table entry */ |
| 229 | sess->tport = tport; | 239 | sess->tport = tport; |
| @@ -234,8 +244,9 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, | |||
| 234 | TARGET_PROT_NORMAL, &initiatorname[0], | 244 | TARGET_PROT_NORMAL, &initiatorname[0], |
| 235 | sess, ft_sess_alloc_cb); | 245 | sess, ft_sess_alloc_cb); |
| 236 | if (IS_ERR(sess->se_sess)) { | 246 | if (IS_ERR(sess->se_sess)) { |
| 247 | int rc = PTR_ERR(sess->se_sess); | ||
| 237 | kfree(sess); | 248 | kfree(sess); |
| 238 | return NULL; | 249 | sess = ERR_PTR(rc); |
| 239 | } | 250 | } |
| 240 | return sess; | 251 | return sess; |
| 241 | } | 252 | } |
| @@ -319,7 +330,7 @@ void ft_sess_close(struct se_session *se_sess) | |||
| 319 | mutex_unlock(&ft_lport_lock); | 330 | mutex_unlock(&ft_lport_lock); |
| 320 | return; | 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 | ft_sess_unhash(sess); | 334 | ft_sess_unhash(sess); |
| 324 | mutex_unlock(&ft_lport_lock); | 335 | mutex_unlock(&ft_lport_lock); |
| 325 | ft_close_sess(sess); | 336 | ft_close_sess(sess); |
| @@ -379,8 +390,13 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, | |||
| 379 | if (!(fcp_parm & FCP_SPPF_INIT_FCN)) | 390 | if (!(fcp_parm & FCP_SPPF_INIT_FCN)) |
| 380 | return FC_SPP_RESP_CONF; | 391 | return FC_SPP_RESP_CONF; |
| 381 | sess = ft_sess_create(tport, rdata->ids.port_id, rdata); | 392 | sess = ft_sess_create(tport, rdata->ids.port_id, rdata); |
| 382 | if (!sess) | 393 | if (IS_ERR(sess)) { |
| 383 | return FC_SPP_RESP_RES; | 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 | if (!sess->params) | 400 | if (!sess->params) |
| 385 | rdata->prli_count++; | 401 | rdata->prli_count++; |
| 386 | sess->params = fcp_parm; | 402 | sess->params = fcp_parm; |
| @@ -423,8 +439,8 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, | |||
| 423 | mutex_lock(&ft_lport_lock); | 439 | mutex_lock(&ft_lport_lock); |
| 424 | ret = ft_prli_locked(rdata, spp_len, rspp, spp); | 440 | ret = ft_prli_locked(rdata, spp_len, rspp, spp); |
| 425 | mutex_unlock(&ft_lport_lock); | 441 | mutex_unlock(&ft_lport_lock); |
| 426 | pr_debug("port_id %x flags %x ret %x\n", | 442 | TFC_SESS_DBG(rdata->local_port, "port_id %x flags %x ret %x\n", |
| 427 | rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); | 443 | rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); |
| 428 | return ret; | 444 | return ret; |
| 429 | } | 445 | } |
| 430 | 446 | ||
| @@ -477,11 +493,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) | |||
| 477 | struct ft_sess *sess; | 493 | struct ft_sess *sess; |
| 478 | u32 sid = fc_frame_sid(fp); | 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 | sess = ft_sess_get(lport, sid); | 498 | sess = ft_sess_get(lport, sid); |
| 483 | if (!sess) { | 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 | /* TBD XXX - if FCP_CMND, send PRLO */ | 501 | /* TBD XXX - if FCP_CMND, send PRLO */ |
| 486 | fc_frame_free(fp); | 502 | fc_frame_free(fp); |
| 487 | return; | 503 | return; |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index fb8e3b6febdf..c2119008990a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
| @@ -177,6 +177,7 @@ enum tcm_sense_reason_table { | |||
| 177 | TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), | 177 | TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), |
| 178 | TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), | 178 | TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), |
| 179 | TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), | 179 | TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), |
| 180 | TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18), | ||
| 180 | #undef R | 181 | #undef R |
| 181 | }; | 182 | }; |
| 182 | 183 | ||
