aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-23 19:37:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-23 19:37:58 -0400
commita55da8a0ddac4ebe0d7b3a1e5902cb1d286f8062 (patch)
tree9a9ae5bceedb3d7e35a656769c4c83c84d2866f5
parente6995f22d3a0f0f56716fdd62a9cbc0c0791f824 (diff)
parent1ba0158fa66b5b2c597a748f87be1650c9960ccc (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
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
-rw-r--r--drivers/target/iscsi/iscsi_target.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c4
-rw-r--r--drivers/target/target_core_transport.c39
-rw-r--r--drivers/target/target_core_user.c50
-rw-r--r--drivers/target/target_core_xcopy.c34
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c4
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c42
-rw-r--r--include/target/target_core_base.h1
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}
1809EXPORT_SYMBOL(iscsit_process_nop_out); 1813EXPORT_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}
2988EXPORT_SYMBOL(iscsit_build_nopin_rsp); 2992EXPORT_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
755void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) 755void 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 */
2628void target_sess_cmd_list_set_waiting(struct se_session *se_sess) 2619void 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
392static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) 392static sense_reason_t
393tcmu_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
532static int tcmu_queue_cmd(struct se_cmd *se_cmd) 534static sense_reason_t
535tcmu_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
1131static sense_reason_t 1134static sense_reason_t
1132tcmu_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
1142static sense_reason_t
1143tcmu_parse_cdb(struct se_cmd *cmd) 1135tcmu_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
1148static const struct target_backend_ops tcmu_ops = { 1140static 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
186static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, 186static 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)
815out: 828out:
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
581err: 581err:
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
42static void ft_sess_delete_all(struct ft_tport *); 47static 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 }
185out: 194out:
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