aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-13 01:38:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-13 01:38:32 -0400
commited9ea4ed3a44e8f8e8c7e8a12a05fd73f9ae1fb4 (patch)
treef7275c1cade0a756d5b456dc23ccb692ff6073d5 /drivers/target
parentc1fdb2d3389c5a1e7c559a37a4967c1d2580e75c (diff)
parent0ed6e189e3f6ac3a25383ed5cc8b0ac24c9b97b7 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger: "The highlights this round include: - Add support for T10 PI pass-through between vhost-scsi + virtio-scsi (MST + Paolo + MKP + nab) - Add support for T10 PI in qla2xxx target mode (Quinn + MKP + hch + nab, merged through scsi.git) - Add support for percpu-ida pre-allocation in qla2xxx target code (Quinn + nab) - A number of iser-target fixes related to hardening the network portal shutdown path (Sagi + Slava) - Fix response length residual handling for a number of control CDBs (Roland + Christophe V.) - Various iscsi RFC conformance fixes in the CHAP authentication path (Tejas and Calsoft folks + nab) - Return TASK_SET_FULL status for tcm_fc(FCoE) DataIn + Response failures (Vasu + Jun + nab) - Fix long-standing ABORT_TASK + session reset hang (nab) - Convert iser-initiator + iser-target to include T10 bytes into EDTL (Sagi + Or + MKP + Mike Christie) - Fix NULL pointer dereference regression related to XCOPY introduced in v3.15 + CC'ed to v3.12.y (nab)" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (34 commits) target: Fix NULL pointer dereference for XCOPY in target_put_sess_cmd vhost-scsi: Include prot_bytes into expected data transfer length TARGET/sbc,loopback: Adjust command data length in case pi exists on the wire libiscsi, iser: Adjust data_length to include protection information scsi_cmnd: Introduce scsi_transfer_length helper target: Report correct response length for some commands target/sbc: Check that the LBA and number of blocks are correct in VERIFY target/sbc: Remove sbc_check_valid_sectors() Target/iscsi: Fix sendtargets response pdu for iser transport Target/iser: Fix a wrong dereference in case discovery session is over iser iscsi-target: Fix ABORT_TASK + connection reset iscsi_queue_req memory leak target: Use complete_all for se_cmd->t_transport_stop_comp target: Set CMD_T_ACTIVE bit for Task Management Requests target: cleanup some boolean tests target/spc: Simplify INQUIRY EVPD=0x80 tcm_fc: Generate TASK_SET_FULL status for response failures tcm_fc: Generate TASK_SET_FULL status for DataIN failures iscsi-target: Reject mutual authentication with reflected CHAP_C iscsi-target: Remove no-op from iscsit_tpg_del_portal_group iscsi-target: Fix CHAP_A parameter list handling ...
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target.c29
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.c74
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.h1
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c12
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c14
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c8
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.h1
-rw-r--r--drivers/target/loopback/tcm_loop.c15
-rw-r--r--drivers/target/target_core_sbc.c68
-rw-r--r--drivers/target/target_core_spc.c18
-rw-r--r--drivers/target/target_core_transport.c37
-rw-r--r--drivers/target/target_core_xcopy.c10
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c19
-rw-r--r--drivers/target/tcm_fc/tfc_io.c17
15 files changed, 210 insertions, 115 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 9189bc0a87ae..5663f4d19d02 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -300,7 +300,7 @@ bool iscsit_check_np_match(
300 port = ntohs(sock_in->sin_port); 300 port = ntohs(sock_in->sin_port);
301 } 301 }
302 302
303 if ((ip_match == true) && (np->np_port == port) && 303 if (ip_match && (np->np_port == port) &&
304 (np->np_network_transport == network_transport)) 304 (np->np_network_transport == network_transport))
305 return true; 305 return true;
306 306
@@ -325,7 +325,7 @@ static struct iscsi_np *iscsit_get_np(
325 } 325 }
326 326
327 match = iscsit_check_np_match(sockaddr, np, network_transport); 327 match = iscsit_check_np_match(sockaddr, np, network_transport);
328 if (match == true) { 328 if (match) {
329 /* 329 /*
330 * Increment the np_exports reference count now to 330 * Increment the np_exports reference count now to
331 * prevent iscsit_del_np() below from being called 331 * prevent iscsit_del_np() below from being called
@@ -1121,7 +1121,7 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
1121 /* 1121 /*
1122 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. 1122 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
1123 */ 1123 */
1124 if (dump_payload == true) 1124 if (dump_payload)
1125 goto after_immediate_data; 1125 goto after_immediate_data;
1126 1126
1127 immed_ret = iscsit_handle_immediate_data(cmd, hdr, 1127 immed_ret = iscsit_handle_immediate_data(cmd, hdr,
@@ -3390,7 +3390,9 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
3390 3390
3391#define SENDTARGETS_BUF_LIMIT 32768U 3391#define SENDTARGETS_BUF_LIMIT 32768U
3392 3392
3393static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) 3393static int
3394iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3395 enum iscsit_transport_type network_transport)
3394{ 3396{
3395 char *payload = NULL; 3397 char *payload = NULL;
3396 struct iscsi_conn *conn = cmd->conn; 3398 struct iscsi_conn *conn = cmd->conn;
@@ -3467,6 +3469,9 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
3467 struct iscsi_np *np = tpg_np->tpg_np; 3469 struct iscsi_np *np = tpg_np->tpg_np;
3468 bool inaddr_any = iscsit_check_inaddr_any(np); 3470 bool inaddr_any = iscsit_check_inaddr_any(np);
3469 3471
3472 if (np->np_network_transport != network_transport)
3473 continue;
3474
3470 if (!target_name_printed) { 3475 if (!target_name_printed) {
3471 len = sprintf(buf, "TargetName=%s", 3476 len = sprintf(buf, "TargetName=%s",
3472 tiqn->tiqn); 3477 tiqn->tiqn);
@@ -3485,10 +3490,8 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
3485 3490
3486 len = sprintf(buf, "TargetAddress=" 3491 len = sprintf(buf, "TargetAddress="
3487 "%s:%hu,%hu", 3492 "%s:%hu,%hu",
3488 (inaddr_any == false) ? 3493 inaddr_any ? conn->local_ip : np->np_ip,
3489 np->np_ip : conn->local_ip, 3494 inaddr_any ? conn->local_port : np->np_port,
3490 (inaddr_any == false) ?
3491 np->np_port : conn->local_port,
3492 tpg->tpgt); 3495 tpg->tpgt);
3493 len += 1; 3496 len += 1;
3494 3497
@@ -3520,11 +3523,12 @@ eob:
3520 3523
3521int 3524int
3522iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, 3525iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
3523 struct iscsi_text_rsp *hdr) 3526 struct iscsi_text_rsp *hdr,
3527 enum iscsit_transport_type network_transport)
3524{ 3528{
3525 int text_length, padding; 3529 int text_length, padding;
3526 3530
3527 text_length = iscsit_build_sendtargets_response(cmd); 3531 text_length = iscsit_build_sendtargets_response(cmd, network_transport);
3528 if (text_length < 0) 3532 if (text_length < 0)
3529 return text_length; 3533 return text_length;
3530 3534
@@ -3562,7 +3566,7 @@ static int iscsit_send_text_rsp(
3562 u32 tx_size = 0; 3566 u32 tx_size = 0;
3563 int text_length, iov_count = 0, rc; 3567 int text_length, iov_count = 0, rc;
3564 3568
3565 rc = iscsit_build_text_rsp(cmd, conn, hdr); 3569 rc = iscsit_build_text_rsp(cmd, conn, hdr, ISCSI_TCP);
3566 if (rc < 0) 3570 if (rc < 0)
3567 return rc; 3571 return rc;
3568 3572
@@ -4234,8 +4238,6 @@ int iscsit_close_connection(
4234 if (conn->conn_transport->iscsit_wait_conn) 4238 if (conn->conn_transport->iscsit_wait_conn)
4235 conn->conn_transport->iscsit_wait_conn(conn); 4239 conn->conn_transport->iscsit_wait_conn(conn);
4236 4240
4237 iscsit_free_queue_reqs_for_conn(conn);
4238
4239 /* 4241 /*
4240 * During Connection recovery drop unacknowledged out of order 4242 * During Connection recovery drop unacknowledged out of order
4241 * commands for this connection, and prepare the other commands 4243 * commands for this connection, and prepare the other commands
@@ -4252,6 +4254,7 @@ int iscsit_close_connection(
4252 iscsit_clear_ooo_cmdsns_for_conn(conn); 4254 iscsit_clear_ooo_cmdsns_for_conn(conn);
4253 iscsit_release_commands_from_conn(conn); 4255 iscsit_release_commands_from_conn(conn);
4254 } 4256 }
4257 iscsit_free_queue_reqs_for_conn(conn);
4255 4258
4256 /* 4259 /*
4257 * Handle decrementing session or connection usage count if 4260 * Handle decrementing session or connection usage count if
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index de77d9aa22c6..19b842c3e0b3 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -71,6 +71,40 @@ static void chap_gen_challenge(
71 challenge_asciihex); 71 challenge_asciihex);
72} 72}
73 73
74static int chap_check_algorithm(const char *a_str)
75{
76 char *tmp, *orig, *token;
77
78 tmp = kstrdup(a_str, GFP_KERNEL);
79 if (!tmp) {
80 pr_err("Memory allocation failed for CHAP_A temporary buffer\n");
81 return CHAP_DIGEST_UNKNOWN;
82 }
83 orig = tmp;
84
85 token = strsep(&tmp, "=");
86 if (!token)
87 goto out;
88
89 if (strcmp(token, "CHAP_A")) {
90 pr_err("Unable to locate CHAP_A key\n");
91 goto out;
92 }
93 while (token) {
94 token = strsep(&tmp, ",");
95 if (!token)
96 goto out;
97
98 if (!strncmp(token, "5", 1)) {
99 pr_debug("Selected MD5 Algorithm\n");
100 kfree(orig);
101 return CHAP_DIGEST_MD5;
102 }
103 }
104out:
105 kfree(orig);
106 return CHAP_DIGEST_UNKNOWN;
107}
74 108
75static struct iscsi_chap *chap_server_open( 109static struct iscsi_chap *chap_server_open(
76 struct iscsi_conn *conn, 110 struct iscsi_conn *conn,
@@ -79,6 +113,7 @@ static struct iscsi_chap *chap_server_open(
79 char *aic_str, 113 char *aic_str,
80 unsigned int *aic_len) 114 unsigned int *aic_len)
81{ 115{
116 int ret;
82 struct iscsi_chap *chap; 117 struct iscsi_chap *chap;
83 118
84 if (!(auth->naf_flags & NAF_USERID_SET) || 119 if (!(auth->naf_flags & NAF_USERID_SET) ||
@@ -93,21 +128,24 @@ static struct iscsi_chap *chap_server_open(
93 return NULL; 128 return NULL;
94 129
95 chap = conn->auth_protocol; 130 chap = conn->auth_protocol;
96 /* 131 ret = chap_check_algorithm(a_str);
97 * We only support MD5 MDA presently. 132 switch (ret) {
98 */ 133 case CHAP_DIGEST_MD5:
99 if (strncmp(a_str, "CHAP_A=5", 8)) { 134 pr_debug("[server] Got CHAP_A=5\n");
100 pr_err("CHAP_A is not MD5.\n"); 135 /*
136 * Send back CHAP_A set to MD5.
137 */
138 *aic_len = sprintf(aic_str, "CHAP_A=5");
139 *aic_len += 1;
140 chap->digest_type = CHAP_DIGEST_MD5;
141 pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type);
142 break;
143 case CHAP_DIGEST_UNKNOWN:
144 default:
145 pr_err("Unsupported CHAP_A value\n");
101 return NULL; 146 return NULL;
102 } 147 }
103 pr_debug("[server] Got CHAP_A=5\n"); 148
104 /*
105 * Send back CHAP_A set to MD5.
106 */
107 *aic_len = sprintf(aic_str, "CHAP_A=5");
108 *aic_len += 1;
109 chap->digest_type = CHAP_DIGEST_MD5;
110 pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type);
111 /* 149 /*
112 * Set Identifier. 150 * Set Identifier.
113 */ 151 */
@@ -314,6 +352,16 @@ static int chap_server_compute_md5(
314 goto out; 352 goto out;
315 } 353 }
316 /* 354 /*
355 * During mutual authentication, the CHAP_C generated by the
356 * initiator must not match the original CHAP_C generated by
357 * the target.
358 */
359 if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) {
360 pr_err("initiator CHAP_C matches target CHAP_C, failing"
361 " login attempt\n");
362 goto out;
363 }
364 /*
317 * Generate CHAP_N and CHAP_R for mutual authentication. 365 * Generate CHAP_N and CHAP_R for mutual authentication.
318 */ 366 */
319 tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); 367 tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
diff --git a/drivers/target/iscsi/iscsi_target_auth.h b/drivers/target/iscsi/iscsi_target_auth.h
index 2f463c09626d..d22f7b96a06c 100644
--- a/drivers/target/iscsi/iscsi_target_auth.h
+++ b/drivers/target/iscsi/iscsi_target_auth.h
@@ -1,6 +1,7 @@
1#ifndef _ISCSI_CHAP_H_ 1#ifndef _ISCSI_CHAP_H_
2#define _ISCSI_CHAP_H_ 2#define _ISCSI_CHAP_H_
3 3
4#define CHAP_DIGEST_UNKNOWN 0
4#define CHAP_DIGEST_MD5 5 5#define CHAP_DIGEST_MD5 5
5#define CHAP_DIGEST_SHA 6 6#define CHAP_DIGEST_SHA 6
6 7
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index d9b1d88e1ad3..fecb69535a15 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -1145,7 +1145,7 @@ iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t)
1145void iscsi_target_login_sess_out(struct iscsi_conn *conn, 1145void iscsi_target_login_sess_out(struct iscsi_conn *conn,
1146 struct iscsi_np *np, bool zero_tsih, bool new_sess) 1146 struct iscsi_np *np, bool zero_tsih, bool new_sess)
1147{ 1147{
1148 if (new_sess == false) 1148 if (!new_sess)
1149 goto old_sess_out; 1149 goto old_sess_out;
1150 1150
1151 pr_err("iSCSI Login negotiation failed.\n"); 1151 pr_err("iSCSI Login negotiation failed.\n");
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 75b685960e80..62a095f36bf2 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -404,7 +404,7 @@ static void iscsi_target_sk_data_ready(struct sock *sk)
404 } 404 }
405 405
406 rc = schedule_delayed_work(&conn->login_work, 0); 406 rc = schedule_delayed_work(&conn->login_work, 0);
407 if (rc == false) { 407 if (!rc) {
408 pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work" 408 pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work"
409 " got false\n"); 409 " got false\n");
410 } 410 }
@@ -513,7 +513,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
513 state = (tpg->tpg_state == TPG_STATE_ACTIVE); 513 state = (tpg->tpg_state == TPG_STATE_ACTIVE);
514 spin_unlock(&tpg->tpg_state_lock); 514 spin_unlock(&tpg->tpg_state_lock);
515 515
516 if (state == false) { 516 if (!state) {
517 pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); 517 pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n");
518 iscsi_target_restore_sock_callbacks(conn); 518 iscsi_target_restore_sock_callbacks(conn);
519 iscsi_target_login_drop(conn, login); 519 iscsi_target_login_drop(conn, login);
@@ -528,7 +528,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
528 state = iscsi_target_sk_state_check(sk); 528 state = iscsi_target_sk_state_check(sk);
529 read_unlock_bh(&sk->sk_callback_lock); 529 read_unlock_bh(&sk->sk_callback_lock);
530 530
531 if (state == false) { 531 if (!state) {
532 pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); 532 pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n");
533 iscsi_target_restore_sock_callbacks(conn); 533 iscsi_target_restore_sock_callbacks(conn);
534 iscsi_target_login_drop(conn, login); 534 iscsi_target_login_drop(conn, login);
@@ -773,6 +773,12 @@ static int iscsi_target_handle_csg_zero(
773 } 773 }
774 774
775 goto do_auth; 775 goto do_auth;
776 } else if (!payload_length) {
777 pr_err("Initiator sent zero length security payload,"
778 " login failed\n");
779 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
780 ISCSI_LOGIN_STATUS_AUTH_FAILED);
781 return -1;
776 } 782 }
777 783
778 if (login->first_request) 784 if (login->first_request)
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 4d2e23fc76fd..02f9de26f38a 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -474,10 +474,10 @@ int iscsi_set_keys_to_negotiate(
474 if (!strcmp(param->name, AUTHMETHOD)) { 474 if (!strcmp(param->name, AUTHMETHOD)) {
475 SET_PSTATE_NEGOTIATE(param); 475 SET_PSTATE_NEGOTIATE(param);
476 } else if (!strcmp(param->name, HEADERDIGEST)) { 476 } else if (!strcmp(param->name, HEADERDIGEST)) {
477 if (iser == false) 477 if (!iser)
478 SET_PSTATE_NEGOTIATE(param); 478 SET_PSTATE_NEGOTIATE(param);
479 } else if (!strcmp(param->name, DATADIGEST)) { 479 } else if (!strcmp(param->name, DATADIGEST)) {
480 if (iser == false) 480 if (!iser)
481 SET_PSTATE_NEGOTIATE(param); 481 SET_PSTATE_NEGOTIATE(param);
482 } else if (!strcmp(param->name, MAXCONNECTIONS)) { 482 } else if (!strcmp(param->name, MAXCONNECTIONS)) {
483 SET_PSTATE_NEGOTIATE(param); 483 SET_PSTATE_NEGOTIATE(param);
@@ -497,7 +497,7 @@ int iscsi_set_keys_to_negotiate(
497 } else if (!strcmp(param->name, IMMEDIATEDATA)) { 497 } else if (!strcmp(param->name, IMMEDIATEDATA)) {
498 SET_PSTATE_NEGOTIATE(param); 498 SET_PSTATE_NEGOTIATE(param);
499 } else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) { 499 } else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
500 if (iser == false) 500 if (!iser)
501 SET_PSTATE_NEGOTIATE(param); 501 SET_PSTATE_NEGOTIATE(param);
502 } else if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) { 502 } else if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) {
503 continue; 503 continue;
@@ -528,13 +528,13 @@ int iscsi_set_keys_to_negotiate(
528 } else if (!strcmp(param->name, OFMARKINT)) { 528 } else if (!strcmp(param->name, OFMARKINT)) {
529 SET_PSTATE_NEGOTIATE(param); 529 SET_PSTATE_NEGOTIATE(param);
530 } else if (!strcmp(param->name, RDMAEXTENSIONS)) { 530 } else if (!strcmp(param->name, RDMAEXTENSIONS)) {
531 if (iser == true) 531 if (iser)
532 SET_PSTATE_NEGOTIATE(param); 532 SET_PSTATE_NEGOTIATE(param);
533 } else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) { 533 } else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
534 if (iser == true) 534 if (iser)
535 SET_PSTATE_NEGOTIATE(param); 535 SET_PSTATE_NEGOTIATE(param);
536 } else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH)) { 536 } else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH)) {
537 if (iser == true) 537 if (iser)
538 SET_PSTATE_NEGOTIATE(param); 538 SET_PSTATE_NEGOTIATE(param);
539 } 539 }
540 } 540 }
@@ -1605,7 +1605,7 @@ int iscsi_decode_text_input(
1605 1605
1606 tmpbuf = kzalloc(length + 1, GFP_KERNEL); 1606 tmpbuf = kzalloc(length + 1, GFP_KERNEL);
1607 if (!tmpbuf) { 1607 if (!tmpbuf) {
1608 pr_err("Unable to allocate memory for tmpbuf.\n"); 1608 pr_err("Unable to allocate %u + 1 bytes for tmpbuf.\n", length);
1609 return -1; 1609 return -1;
1610 } 1610 }
1611 1611
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 1431e8400d28..c3cb5c15efda 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -189,7 +189,7 @@ static void iscsit_clear_tpg_np_login_thread(
189 iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown); 189 iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown);
190} 190}
191 191
192void iscsit_clear_tpg_np_login_threads( 192static void iscsit_clear_tpg_np_login_threads(
193 struct iscsi_portal_group *tpg, 193 struct iscsi_portal_group *tpg,
194 bool shutdown) 194 bool shutdown)
195{ 195{
@@ -276,8 +276,6 @@ int iscsit_tpg_del_portal_group(
276 tpg->tpg_state = TPG_STATE_INACTIVE; 276 tpg->tpg_state = TPG_STATE_INACTIVE;
277 spin_unlock(&tpg->tpg_state_lock); 277 spin_unlock(&tpg->tpg_state_lock);
278 278
279 iscsit_clear_tpg_np_login_threads(tpg, true);
280
281 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) { 279 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) {
282 pr_err("Unable to delete iSCSI Target Portal Group:" 280 pr_err("Unable to delete iSCSI Target Portal Group:"
283 " %hu while active sessions exist, and force=0\n", 281 " %hu while active sessions exist, and force=0\n",
@@ -453,7 +451,7 @@ static bool iscsit_tpg_check_network_portal(
453 451
454 match = iscsit_check_np_match(sockaddr, np, 452 match = iscsit_check_np_match(sockaddr, np,
455 network_transport); 453 network_transport);
456 if (match == true) 454 if (match)
457 break; 455 break;
458 } 456 }
459 spin_unlock(&tpg->tpg_np_lock); 457 spin_unlock(&tpg->tpg_np_lock);
@@ -475,7 +473,7 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
475 473
476 if (!tpg_np_parent) { 474 if (!tpg_np_parent) {
477 if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr, 475 if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr,
478 network_transport) == true) { 476 network_transport)) {
479 pr_err("Network Portal: %s already exists on a" 477 pr_err("Network Portal: %s already exists on a"
480 " different TPG on %s\n", ip_str, 478 " different TPG on %s\n", ip_str,
481 tpg->tpg_tiqn->tiqn); 479 tpg->tpg_tiqn->tiqn);
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
index 0a182f2aa8a2..e7265337bc43 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.h
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -8,7 +8,6 @@ extern struct iscsi_portal_group *iscsit_get_tpg_from_np(struct iscsi_tiqn *,
8 struct iscsi_np *, struct iscsi_tpg_np **); 8 struct iscsi_np *, struct iscsi_tpg_np **);
9extern int iscsit_get_tpg(struct iscsi_portal_group *); 9extern int iscsit_get_tpg(struct iscsi_portal_group *);
10extern void iscsit_put_tpg(struct iscsi_portal_group *); 10extern void iscsit_put_tpg(struct iscsi_portal_group *);
11extern void iscsit_clear_tpg_np_login_threads(struct iscsi_portal_group *, bool);
12extern void iscsit_tpg_dump_params(struct iscsi_portal_group *); 11extern void iscsit_tpg_dump_params(struct iscsi_portal_group *);
13extern int iscsit_tpg_add_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *); 12extern int iscsit_tpg_add_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *);
14extern int iscsit_tpg_del_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *, 13extern int iscsit_tpg_del_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *,
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 73ab75ddaf42..6d2f37578b29 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -179,7 +179,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
179 struct tcm_loop_hba *tl_hba; 179 struct tcm_loop_hba *tl_hba;
180 struct tcm_loop_tpg *tl_tpg; 180 struct tcm_loop_tpg *tl_tpg;
181 struct scatterlist *sgl_bidi = NULL; 181 struct scatterlist *sgl_bidi = NULL;
182 u32 sgl_bidi_count = 0; 182 u32 sgl_bidi_count = 0, transfer_length;
183 int rc; 183 int rc;
184 184
185 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); 185 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
@@ -213,12 +213,21 @@ static void tcm_loop_submission_work(struct work_struct *work)
213 213
214 } 214 }
215 215
216 if (!scsi_prot_sg_count(sc) && scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) 216 transfer_length = scsi_transfer_length(sc);
217 if (!scsi_prot_sg_count(sc) &&
218 scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) {
217 se_cmd->prot_pto = true; 219 se_cmd->prot_pto = true;
220 /*
221 * loopback transport doesn't support
222 * WRITE_GENERATE, READ_STRIP protection
223 * information operations, go ahead unprotected.
224 */
225 transfer_length = scsi_bufflen(sc);
226 }
218 227
219 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd, 228 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
220 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun, 229 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
221 scsi_bufflen(sc), tcm_loop_sam_attr(sc), 230 transfer_length, tcm_loop_sam_attr(sc),
222 sc->sc_data_direction, 0, 231 sc->sc_data_direction, 0,
223 scsi_sglist(sc), scsi_sg_count(sc), 232 scsi_sglist(sc), scsi_sg_count(sc),
224 sgl_bidi, sgl_bidi_count, 233 sgl_bidi, sgl_bidi_count,
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index e0229592ec55..bd78d9235ac6 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -81,7 +81,7 @@ sbc_emulate_readcapacity(struct se_cmd *cmd)
81 transport_kunmap_data_sg(cmd); 81 transport_kunmap_data_sg(cmd);
82 } 82 }
83 83
84 target_complete_cmd(cmd, GOOD); 84 target_complete_cmd_with_length(cmd, GOOD, 8);
85 return 0; 85 return 0;
86} 86}
87 87
@@ -137,7 +137,7 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
137 transport_kunmap_data_sg(cmd); 137 transport_kunmap_data_sg(cmd);
138 } 138 }
139 139
140 target_complete_cmd(cmd, GOOD); 140 target_complete_cmd_with_length(cmd, GOOD, 32);
141 return 0; 141 return 0;
142} 142}
143 143
@@ -176,24 +176,6 @@ static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
176 return cmd->se_dev->dev_attrib.block_size * sectors; 176 return cmd->se_dev->dev_attrib.block_size * sectors;
177} 177}
178 178
179static int sbc_check_valid_sectors(struct se_cmd *cmd)
180{
181 struct se_device *dev = cmd->se_dev;
182 unsigned long long end_lba;
183 u32 sectors;
184
185 sectors = cmd->data_length / dev->dev_attrib.block_size;
186 end_lba = dev->transport->get_blocks(dev) + 1;
187
188 if (cmd->t_task_lba + sectors > end_lba) {
189 pr_err("target: lba %llu, sectors %u exceeds end lba %llu\n",
190 cmd->t_task_lba, sectors, end_lba);
191 return -EINVAL;
192 }
193
194 return 0;
195}
196
197static inline u32 transport_get_sectors_6(unsigned char *cdb) 179static inline u32 transport_get_sectors_6(unsigned char *cdb)
198{ 180{
199 /* 181 /*
@@ -665,8 +647,19 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
665 647
666 cmd->prot_type = dev->dev_attrib.pi_prot_type; 648 cmd->prot_type = dev->dev_attrib.pi_prot_type;
667 cmd->prot_length = dev->prot_length * sectors; 649 cmd->prot_length = dev->prot_length * sectors;
668 pr_debug("%s: prot_type=%d, prot_length=%d prot_op=%d prot_checks=%d\n", 650
669 __func__, cmd->prot_type, cmd->prot_length, 651 /**
652 * In case protection information exists over the wire
653 * we modify command data length to describe pure data.
654 * The actual transfer length is data length + protection
655 * length
656 **/
657 if (protect)
658 cmd->data_length = sectors * dev->dev_attrib.block_size;
659
660 pr_debug("%s: prot_type=%d, data_length=%d, prot_length=%d "
661 "prot_op=%d prot_checks=%d\n",
662 __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
670 cmd->prot_op, cmd->prot_checks); 663 cmd->prot_op, cmd->prot_checks);
671 664
672 return true; 665 return true;
@@ -877,15 +870,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
877 break; 870 break;
878 case SYNCHRONIZE_CACHE: 871 case SYNCHRONIZE_CACHE:
879 case SYNCHRONIZE_CACHE_16: 872 case SYNCHRONIZE_CACHE_16:
880 if (!ops->execute_sync_cache) {
881 size = 0;
882 cmd->execute_cmd = sbc_emulate_noop;
883 break;
884 }
885
886 /*
887 * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
888 */
889 if (cdb[0] == SYNCHRONIZE_CACHE) { 873 if (cdb[0] == SYNCHRONIZE_CACHE) {
890 sectors = transport_get_sectors_10(cdb); 874 sectors = transport_get_sectors_10(cdb);
891 cmd->t_task_lba = transport_lba_32(cdb); 875 cmd->t_task_lba = transport_lba_32(cdb);
@@ -893,18 +877,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
893 sectors = transport_get_sectors_16(cdb); 877 sectors = transport_get_sectors_16(cdb);
894 cmd->t_task_lba = transport_lba_64(cdb); 878 cmd->t_task_lba = transport_lba_64(cdb);
895 } 879 }
896 880 if (ops->execute_sync_cache) {
897 size = sbc_get_size(cmd, sectors); 881 cmd->execute_cmd = ops->execute_sync_cache;
898 882 goto check_lba;
899 /*
900 * Check to ensure that LBA + Range does not exceed past end of
901 * device for IBLOCK and FILEIO ->do_sync_cache() backend calls
902 */
903 if (cmd->t_task_lba || sectors) {
904 if (sbc_check_valid_sectors(cmd) < 0)
905 return TCM_ADDRESS_OUT_OF_RANGE;
906 } 883 }
907 cmd->execute_cmd = ops->execute_sync_cache; 884 size = 0;
885 cmd->execute_cmd = sbc_emulate_noop;
908 break; 886 break;
909 case UNMAP: 887 case UNMAP:
910 if (!ops->execute_unmap) 888 if (!ops->execute_unmap)
@@ -947,8 +925,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
947 break; 925 break;
948 case VERIFY: 926 case VERIFY:
949 size = 0; 927 size = 0;
928 sectors = transport_get_sectors_10(cdb);
929 cmd->t_task_lba = transport_lba_32(cdb);
950 cmd->execute_cmd = sbc_emulate_noop; 930 cmd->execute_cmd = sbc_emulate_noop;
951 break; 931 goto check_lba;
952 case REZERO_UNIT: 932 case REZERO_UNIT:
953 case SEEK_6: 933 case SEEK_6:
954 case SEEK_10: 934 case SEEK_10:
@@ -988,7 +968,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
988 dev->dev_attrib.hw_max_sectors); 968 dev->dev_attrib.hw_max_sectors);
989 return TCM_INVALID_CDB_FIELD; 969 return TCM_INVALID_CDB_FIELD;
990 } 970 }
991 971check_lba:
992 end_lba = dev->transport->get_blocks(dev) + 1; 972 end_lba = dev->transport->get_blocks(dev) + 1;
993 if (cmd->t_task_lba + sectors > end_lba) { 973 if (cmd->t_task_lba + sectors > end_lba) {
994 pr_err("cmd exceeds last lba %llu " 974 pr_err("cmd exceeds last lba %llu "
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 8653666612a8..6cd7222738fc 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -129,15 +129,10 @@ static sense_reason_t
129spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) 129spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
130{ 130{
131 struct se_device *dev = cmd->se_dev; 131 struct se_device *dev = cmd->se_dev;
132 u16 len = 0; 132 u16 len;
133 133
134 if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { 134 if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) {
135 u32 unit_serial_len; 135 len = sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial);
136
137 unit_serial_len = strlen(dev->t10_wwn.unit_serial);
138 unit_serial_len++; /* For NULL Terminator */
139
140 len += sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial);
141 len++; /* Extra Byte for NULL Terminator */ 136 len++; /* Extra Byte for NULL Terminator */
142 buf[3] = len; 137 buf[3] = len;
143 } 138 }
@@ -721,6 +716,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
721 unsigned char *buf; 716 unsigned char *buf;
722 sense_reason_t ret; 717 sense_reason_t ret;
723 int p; 718 int p;
719 int len = 0;
724 720
725 buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); 721 buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
726 if (!buf) { 722 if (!buf) {
@@ -742,6 +738,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
742 } 738 }
743 739
744 ret = spc_emulate_inquiry_std(cmd, buf); 740 ret = spc_emulate_inquiry_std(cmd, buf);
741 len = buf[4] + 5;
745 goto out; 742 goto out;
746 } 743 }
747 744
@@ -749,6 +746,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
749 if (cdb[2] == evpd_handlers[p].page) { 746 if (cdb[2] == evpd_handlers[p].page) {
750 buf[1] = cdb[2]; 747 buf[1] = cdb[2];
751 ret = evpd_handlers[p].emulate(cmd, buf); 748 ret = evpd_handlers[p].emulate(cmd, buf);
749 len = get_unaligned_be16(&buf[2]) + 4;
752 goto out; 750 goto out;
753 } 751 }
754 } 752 }
@@ -765,7 +763,7 @@ out:
765 kfree(buf); 763 kfree(buf);
766 764
767 if (!ret) 765 if (!ret)
768 target_complete_cmd(cmd, GOOD); 766 target_complete_cmd_with_length(cmd, GOOD, len);
769 return ret; 767 return ret;
770} 768}
771 769
@@ -1103,7 +1101,7 @@ set_length:
1103 transport_kunmap_data_sg(cmd); 1101 transport_kunmap_data_sg(cmd);
1104 } 1102 }
1105 1103
1106 target_complete_cmd(cmd, GOOD); 1104 target_complete_cmd_with_length(cmd, GOOD, length);
1107 return 0; 1105 return 0;
1108} 1106}
1109 1107
@@ -1279,7 +1277,7 @@ done:
1279 buf[3] = (lun_count & 0xff); 1277 buf[3] = (lun_count & 0xff);
1280 transport_kunmap_data_sg(cmd); 1278 transport_kunmap_data_sg(cmd);
1281 1279
1282 target_complete_cmd(cmd, GOOD); 1280 target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
1283 return 0; 1281 return 0;
1284} 1282}
1285EXPORT_SYMBOL(spc_emulate_report_luns); 1283EXPORT_SYMBOL(spc_emulate_report_luns);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 2179feed0d63..7fa62fc93e0b 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -504,7 +504,7 @@ void transport_deregister_session(struct se_session *se_sess)
504 * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group 504 * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
505 * removal context. 505 * removal context.
506 */ 506 */
507 if (se_nacl && comp_nacl == true) 507 if (se_nacl && comp_nacl)
508 target_put_nacl(se_nacl); 508 target_put_nacl(se_nacl);
509 509
510 transport_free_session(se_sess); 510 transport_free_session(se_sess);
@@ -562,7 +562,7 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
562 562
563 spin_unlock_irqrestore(&cmd->t_state_lock, flags); 563 spin_unlock_irqrestore(&cmd->t_state_lock, flags);
564 564
565 complete(&cmd->t_transport_stop_comp); 565 complete_all(&cmd->t_transport_stop_comp);
566 return 1; 566 return 1;
567 } 567 }
568 568
@@ -687,7 +687,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
687 if (cmd->transport_state & CMD_T_ABORTED && 687 if (cmd->transport_state & CMD_T_ABORTED &&
688 cmd->transport_state & CMD_T_STOP) { 688 cmd->transport_state & CMD_T_STOP) {
689 spin_unlock_irqrestore(&cmd->t_state_lock, flags); 689 spin_unlock_irqrestore(&cmd->t_state_lock, flags);
690 complete(&cmd->t_transport_stop_comp); 690 complete_all(&cmd->t_transport_stop_comp);
691 return; 691 return;
692 } else if (!success) { 692 } else if (!success) {
693 INIT_WORK(&cmd->work, target_complete_failure_work); 693 INIT_WORK(&cmd->work, target_complete_failure_work);
@@ -703,6 +703,23 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
703} 703}
704EXPORT_SYMBOL(target_complete_cmd); 704EXPORT_SYMBOL(target_complete_cmd);
705 705
706void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
707{
708 if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
709 if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
710 cmd->residual_count += cmd->data_length - length;
711 } else {
712 cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
713 cmd->residual_count = cmd->data_length - length;
714 }
715
716 cmd->data_length = length;
717 }
718
719 target_complete_cmd(cmd, scsi_status);
720}
721EXPORT_SYMBOL(target_complete_cmd_with_length);
722
706static void target_add_to_state_list(struct se_cmd *cmd) 723static void target_add_to_state_list(struct se_cmd *cmd)
707{ 724{
708 struct se_device *dev = cmd->se_dev; 725 struct se_device *dev = cmd->se_dev;
@@ -1761,7 +1778,7 @@ void target_execute_cmd(struct se_cmd *cmd)
1761 cmd->se_tfo->get_task_tag(cmd)); 1778 cmd->se_tfo->get_task_tag(cmd));
1762 1779
1763 spin_unlock_irq(&cmd->t_state_lock); 1780 spin_unlock_irq(&cmd->t_state_lock);
1764 complete(&cmd->t_transport_stop_comp); 1781 complete_all(&cmd->t_transport_stop_comp);
1765 return; 1782 return;
1766 } 1783 }
1767 1784
@@ -2363,7 +2380,7 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
2363 * fabric acknowledgement that requires two target_put_sess_cmd() 2380 * fabric acknowledgement that requires two target_put_sess_cmd()
2364 * invocations before se_cmd descriptor release. 2381 * invocations before se_cmd descriptor release.
2365 */ 2382 */
2366 if (ack_kref == true) { 2383 if (ack_kref) {
2367 kref_get(&se_cmd->cmd_kref); 2384 kref_get(&se_cmd->cmd_kref);
2368 se_cmd->se_cmd_flags |= SCF_ACK_KREF; 2385 se_cmd->se_cmd_flags |= SCF_ACK_KREF;
2369 } 2386 }
@@ -2407,6 +2424,10 @@ static void target_release_cmd_kref(struct kref *kref)
2407 */ 2424 */
2408int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) 2425int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
2409{ 2426{
2427 if (!se_sess) {
2428 se_cmd->se_tfo->release_cmd(se_cmd);
2429 return 1;
2430 }
2410 return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref, 2431 return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref,
2411 &se_sess->sess_cmd_lock); 2432 &se_sess->sess_cmd_lock);
2412} 2433}
@@ -2934,6 +2955,12 @@ static void target_tmr_work(struct work_struct *work)
2934int transport_generic_handle_tmr( 2955int transport_generic_handle_tmr(
2935 struct se_cmd *cmd) 2956 struct se_cmd *cmd)
2936{ 2957{
2958 unsigned long flags;
2959
2960 spin_lock_irqsave(&cmd->t_state_lock, flags);
2961 cmd->transport_state |= CMD_T_ACTIVE;
2962 spin_unlock_irqrestore(&cmd->t_state_lock, flags);
2963
2937 INIT_WORK(&cmd->work, target_tmr_work); 2964 INIT_WORK(&cmd->work, target_tmr_work);
2938 queue_work(cmd->se_dev->tmr_wq, &cmd->work); 2965 queue_work(cmd->se_dev->tmr_wq, &cmd->work);
2939 return 0; 2966 return 0;
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 669c536fd959..e9186cdf35e9 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -70,7 +70,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
70 unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn; 70 unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn;
71 int rc; 71 int rc;
72 72
73 if (src == true) 73 if (src)
74 dev_wwn = &xop->dst_tid_wwn[0]; 74 dev_wwn = &xop->dst_tid_wwn[0];
75 else 75 else
76 dev_wwn = &xop->src_tid_wwn[0]; 76 dev_wwn = &xop->src_tid_wwn[0];
@@ -88,7 +88,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
88 if (rc != 0) 88 if (rc != 0)
89 continue; 89 continue;
90 90
91 if (src == true) { 91 if (src) {
92 xop->dst_dev = se_dev; 92 xop->dst_dev = se_dev;
93 pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located" 93 pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located"
94 " se_dev\n", xop->dst_dev); 94 " se_dev\n", xop->dst_dev);
@@ -166,7 +166,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
166 return -EINVAL; 166 return -EINVAL;
167 } 167 }
168 168
169 if (src == true) { 169 if (src) {
170 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); 170 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
171 /* 171 /*
172 * Determine if the source designator matches the local device 172 * Determine if the source designator matches the local device
@@ -236,7 +236,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
236 /* 236 /*
237 * Assume target descriptors are in source -> destination order.. 237 * Assume target descriptors are in source -> destination order..
238 */ 238 */
239 if (src == true) 239 if (src)
240 src = false; 240 src = false;
241 else 241 else
242 src = true; 242 src = true;
@@ -560,7 +560,7 @@ static int target_xcopy_init_pt_lun(
560 * reservations. The pt_cmd->se_lun pointer will be setup from within 560 * reservations. The pt_cmd->se_lun pointer will be setup from within
561 * target_xcopy_setup_pt_port() 561 * target_xcopy_setup_pt_port()
562 */ 562 */
563 if (remote_port == false) { 563 if (!remote_port) {
564 pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD | SCF_CMD_XCOPY_PASSTHROUGH; 564 pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD | SCF_CMD_XCOPY_PASSTHROUGH;
565 return 0; 565 return 0;
566 } 566 }
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index f5fd515b2bee..be0c0d08c56a 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -128,6 +128,7 @@ int ft_queue_status(struct se_cmd *se_cmd)
128 struct fc_lport *lport; 128 struct fc_lport *lport;
129 struct fc_exch *ep; 129 struct fc_exch *ep;
130 size_t len; 130 size_t len;
131 int rc;
131 132
132 if (cmd->aborted) 133 if (cmd->aborted)
133 return 0; 134 return 0;
@@ -137,9 +138,10 @@ int ft_queue_status(struct se_cmd *se_cmd)
137 len = sizeof(*fcp) + se_cmd->scsi_sense_length; 138 len = sizeof(*fcp) + se_cmd->scsi_sense_length;
138 fp = fc_frame_alloc(lport, len); 139 fp = fc_frame_alloc(lport, len);
139 if (!fp) { 140 if (!fp) {
140 /* XXX shouldn't just drop it - requeue and retry? */ 141 se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
141 return 0; 142 return -ENOMEM;
142 } 143 }
144
143 fcp = fc_frame_payload_get(fp, len); 145 fcp = fc_frame_payload_get(fp, len);
144 memset(fcp, 0, len); 146 memset(fcp, 0, len);
145 fcp->resp.fr_status = se_cmd->scsi_status; 147 fcp->resp.fr_status = se_cmd->scsi_status;
@@ -170,7 +172,18 @@ int ft_queue_status(struct se_cmd *se_cmd)
170 fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP, 172 fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
171 FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0); 173 FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
172 174
173 lport->tt.seq_send(lport, cmd->seq, fp); 175 rc = lport->tt.seq_send(lport, cmd->seq, fp);
176 if (rc) {
177 pr_info_ratelimited("%s: Failed to send response frame %p, "
178 "xid <0x%x>\n", __func__, fp, ep->xid);
179 /*
180 * Generate a TASK_SET_FULL status to notify the initiator
181 * to reduce it's queue_depth after the se_cmd response has
182 * been re-queued by target-core.
183 */
184 se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
185 return -ENOMEM;
186 }
174 lport->tt.exch_done(cmd->seq); 187 lport->tt.exch_done(cmd->seq);
175 return 0; 188 return 0;
176} 189}
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index e415af32115a..97b486c3dda1 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -82,6 +82,10 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
82 82
83 if (cmd->aborted) 83 if (cmd->aborted)
84 return 0; 84 return 0;
85
86 if (se_cmd->scsi_status == SAM_STAT_TASK_SET_FULL)
87 goto queue_status;
88
85 ep = fc_seq_exch(cmd->seq); 89 ep = fc_seq_exch(cmd->seq);
86 lport = ep->lp; 90 lport = ep->lp;
87 cmd->seq = lport->tt.seq_start_next(cmd->seq); 91 cmd->seq = lport->tt.seq_start_next(cmd->seq);
@@ -178,14 +182,23 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
178 FC_TYPE_FCP, f_ctl, fh_off); 182 FC_TYPE_FCP, f_ctl, fh_off);
179 error = lport->tt.seq_send(lport, seq, fp); 183 error = lport->tt.seq_send(lport, seq, fp);
180 if (error) { 184 if (error) {
181 /* XXX For now, initiator will retry */ 185 pr_info_ratelimited("%s: Failed to send frame %p, "
182 pr_err_ratelimited("%s: Failed to send frame %p, "
183 "xid <0x%x>, remaining %zu, " 186 "xid <0x%x>, remaining %zu, "
184 "lso_max <0x%x>\n", 187 "lso_max <0x%x>\n",
185 __func__, fp, ep->xid, 188 __func__, fp, ep->xid,
186 remaining, lport->lso_max); 189 remaining, lport->lso_max);
190 /*
191 * Go ahead and set TASK_SET_FULL status ignoring the
192 * rest of the DataIN, and immediately attempt to
193 * send the response via ft_queue_status() in order
194 * to notify the initiator that it should reduce it's
195 * per LUN queue_depth.
196 */
197 se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
198 break;
187 } 199 }
188 } 200 }
201queue_status:
189 return ft_queue_status(se_cmd); 202 return ft_queue_status(se_cmd);
190} 203}
191 204