aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/iscsi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 19:11:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 19:11:45 -0400
commit48efe453e6b29561f78a1df55c7f58375259cb8c (patch)
tree53d6ac1f2010b102c15b264b13fc4c98ba634d48 /drivers/target/iscsi
parentac4de9543aca59f2b763746647577302fbedd57e (diff)
parent2999ee7fda3f670effbfa746164c525f9d1be4b8 (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: "Lots of activity again this round for I/O performance optimizations (per-cpu IDA pre-allocation for vhost + iscsi/target), and the addition of new fabric independent features to target-core (COMPARE_AND_WRITE + EXTENDED_COPY). The main highlights include: - Support for iscsi-target login multiplexing across individual network portals - Generic Per-cpu IDA logic (kent + akpm + clameter) - Conversion of vhost to use per-cpu IDA pre-allocation for descriptors, SGLs and userspace page pointer list - Conversion of iscsi-target + iser-target to use per-cpu IDA pre-allocation for descriptors - Add support for generic COMPARE_AND_WRITE (AtomicTestandSet) emulation for virtual backend drivers - Add support for generic EXTENDED_COPY (CopyOffload) emulation for virtual backend drivers. - Add support for fast memory registration mode to iser-target (Vu) The patches to add COMPARE_AND_WRITE and EXTENDED_COPY support are of particular significance, which make us the first and only open source target to support the full set of VAAI primitives. Currently Linux clients are lacking upstream support to actually utilize these primitives. However, with server side support now in place for folks like MKP + ZAB working on the client, this logic once reserved for the highest end of storage arrays, can now be run in VMs on their laptops" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (50 commits) target/iscsi: Bump versions to v4.1.0 target: Update copyright ownership/year information to 2013 iscsi-target: Bump default TCP listen backlog to 256 target: Fix >= v3.9+ regression in PR APTPL + ALUA metadata write-out iscsi-target; Bump default CmdSN Depth to 64 iscsi-target: Remove unnecessary wait_for_completion in iscsi_get_thread_set iscsi-target: Add thread_set->ts_activate_sem + use common deallocate iscsi-target: Fix race with thread_pre_handler flush_signals + ISCSI_THREAD_SET_DIE target: remove unused including <linux/version.h> iser-target: introduce fast memory registration mode (FRWR) iser-target: generalize rdma memory registration and cleanup iser-target: move rdma wr processing to a shared function target: Enable global EXTENDED_COPY setup/release target: Add Third Party Copy (3PC) bit in INQUIRY response target: Enable EXTENDED_COPY setup in spc_parse_cdb target: Add support for EXTENDED_COPY copy offload emulation target: Avoid non-existent tg_pt_gp_mem in target_alua_state_check target: Add global device list for EXTENDED_COPY target: Make helpers non static for EXTENDED_COPY command setup target: Make spc_parse_naa_6h_vendor_specific non static ...
Diffstat (limited to 'drivers/target/iscsi')
-rw-r--r--drivers/target/iscsi/iscsi_target.c83
-rw-r--r--drivers/target/iscsi/iscsi_target.h7
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c16
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h26
-rw-r--r--drivers/target/iscsi/iscsi_target_datain_values.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_device.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_erl0.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_erl2.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c186
-rw-r--r--drivers/target/iscsi/iscsi_target_login.h3
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c367
-rw-r--r--drivers/target/iscsi/iscsi_target_nodeattrib.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_seq_pdu_list.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_stat.c14
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c29
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.h4
-rw-r--r--drivers/target/iscsi/iscsi_target_tq.c167
-rw-r--r--drivers/target/iscsi/iscsi_target_tq.h5
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c45
23 files changed, 651 insertions, 343 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 3a179302b904..35b61f7d6c63 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains main functions related to the iSCSI Target Core Driver. 2 * This file contains main functions related to the iSCSI Target Core Driver.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -63,7 +61,6 @@ spinlock_t sess_idr_lock;
63 61
64struct iscsit_global *iscsit_global; 62struct iscsit_global *iscsit_global;
65 63
66struct kmem_cache *lio_cmd_cache;
67struct kmem_cache *lio_qr_cache; 64struct kmem_cache *lio_qr_cache;
68struct kmem_cache *lio_dr_cache; 65struct kmem_cache *lio_dr_cache;
69struct kmem_cache *lio_ooo_cache; 66struct kmem_cache *lio_ooo_cache;
@@ -220,11 +217,6 @@ int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
220 spin_unlock_bh(&np->np_thread_lock); 217 spin_unlock_bh(&np->np_thread_lock);
221 return -1; 218 return -1;
222 } 219 }
223 if (np->np_login_tpg) {
224 pr_err("np->np_login_tpg() is not NULL!\n");
225 spin_unlock_bh(&np->np_thread_lock);
226 return -1;
227 }
228 spin_unlock_bh(&np->np_thread_lock); 220 spin_unlock_bh(&np->np_thread_lock);
229 /* 221 /*
230 * Determine if the portal group is accepting storage traffic. 222 * Determine if the portal group is accepting storage traffic.
@@ -239,26 +231,38 @@ int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
239 /* 231 /*
240 * Here we serialize access across the TIQN+TPG Tuple. 232 * Here we serialize access across the TIQN+TPG Tuple.
241 */ 233 */
242 ret = mutex_lock_interruptible(&tpg->np_login_lock); 234 ret = down_interruptible(&tpg->np_login_sem);
243 if ((ret != 0) || signal_pending(current)) 235 if ((ret != 0) || signal_pending(current))
244 return -1; 236 return -1;
245 237
246 spin_lock_bh(&np->np_thread_lock); 238 spin_lock_bh(&tpg->tpg_state_lock);
247 np->np_login_tpg = tpg; 239 if (tpg->tpg_state != TPG_STATE_ACTIVE) {
248 spin_unlock_bh(&np->np_thread_lock); 240 spin_unlock_bh(&tpg->tpg_state_lock);
241 up(&tpg->np_login_sem);
242 return -1;
243 }
244 spin_unlock_bh(&tpg->tpg_state_lock);
249 245
250 return 0; 246 return 0;
251} 247}
252 248
253int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg) 249void iscsit_login_kref_put(struct kref *kref)
250{
251 struct iscsi_tpg_np *tpg_np = container_of(kref,
252 struct iscsi_tpg_np, tpg_np_kref);
253
254 complete(&tpg_np->tpg_np_comp);
255}
256
257int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg,
258 struct iscsi_tpg_np *tpg_np)
254{ 259{
255 struct iscsi_tiqn *tiqn = tpg->tpg_tiqn; 260 struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
256 261
257 spin_lock_bh(&np->np_thread_lock); 262 up(&tpg->np_login_sem);
258 np->np_login_tpg = NULL;
259 spin_unlock_bh(&np->np_thread_lock);
260 263
261 mutex_unlock(&tpg->np_login_lock); 264 if (tpg_np)
265 kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
262 266
263 if (tiqn) 267 if (tiqn)
264 iscsit_put_tiqn_for_login(tiqn); 268 iscsit_put_tiqn_for_login(tiqn);
@@ -410,20 +414,10 @@ struct iscsi_np *iscsit_add_np(
410int iscsit_reset_np_thread( 414int iscsit_reset_np_thread(
411 struct iscsi_np *np, 415 struct iscsi_np *np,
412 struct iscsi_tpg_np *tpg_np, 416 struct iscsi_tpg_np *tpg_np,
413 struct iscsi_portal_group *tpg) 417 struct iscsi_portal_group *tpg,
418 bool shutdown)
414{ 419{
415 spin_lock_bh(&np->np_thread_lock); 420 spin_lock_bh(&np->np_thread_lock);
416 if (tpg && tpg_np) {
417 /*
418 * The reset operation need only be performed when the
419 * passed struct iscsi_portal_group has a login in progress
420 * to one of the network portals.
421 */
422 if (tpg_np->tpg_np->np_login_tpg != tpg) {
423 spin_unlock_bh(&np->np_thread_lock);
424 return 0;
425 }
426 }
427 if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) { 421 if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) {
428 spin_unlock_bh(&np->np_thread_lock); 422 spin_unlock_bh(&np->np_thread_lock);
429 return 0; 423 return 0;
@@ -438,6 +432,12 @@ int iscsit_reset_np_thread(
438 } 432 }
439 spin_unlock_bh(&np->np_thread_lock); 433 spin_unlock_bh(&np->np_thread_lock);
440 434
435 if (tpg_np && shutdown) {
436 kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
437
438 wait_for_completion(&tpg_np->tpg_np_comp);
439 }
440
441 return 0; 441 return 0;
442} 442}
443 443
@@ -497,7 +497,6 @@ static struct iscsit_transport iscsi_target_transport = {
497 .iscsit_setup_np = iscsit_setup_np, 497 .iscsit_setup_np = iscsit_setup_np,
498 .iscsit_accept_np = iscsit_accept_np, 498 .iscsit_accept_np = iscsit_accept_np,
499 .iscsit_free_np = iscsit_free_np, 499 .iscsit_free_np = iscsit_free_np,
500 .iscsit_alloc_cmd = iscsit_alloc_cmd,
501 .iscsit_get_login_rx = iscsit_get_login_rx, 500 .iscsit_get_login_rx = iscsit_get_login_rx,
502 .iscsit_put_login_tx = iscsit_put_login_tx, 501 .iscsit_put_login_tx = iscsit_put_login_tx,
503 .iscsit_get_dataout = iscsit_build_r2ts_for_cmd, 502 .iscsit_get_dataout = iscsit_build_r2ts_for_cmd,
@@ -538,22 +537,13 @@ static int __init iscsi_target_init_module(void)
538 goto ts_out1; 537 goto ts_out1;
539 } 538 }
540 539
541 lio_cmd_cache = kmem_cache_create("lio_cmd_cache",
542 sizeof(struct iscsi_cmd), __alignof__(struct iscsi_cmd),
543 0, NULL);
544 if (!lio_cmd_cache) {
545 pr_err("Unable to kmem_cache_create() for"
546 " lio_cmd_cache\n");
547 goto ts_out2;
548 }
549
550 lio_qr_cache = kmem_cache_create("lio_qr_cache", 540 lio_qr_cache = kmem_cache_create("lio_qr_cache",
551 sizeof(struct iscsi_queue_req), 541 sizeof(struct iscsi_queue_req),
552 __alignof__(struct iscsi_queue_req), 0, NULL); 542 __alignof__(struct iscsi_queue_req), 0, NULL);
553 if (!lio_qr_cache) { 543 if (!lio_qr_cache) {
554 pr_err("nable to kmem_cache_create() for" 544 pr_err("nable to kmem_cache_create() for"
555 " lio_qr_cache\n"); 545 " lio_qr_cache\n");
556 goto cmd_out; 546 goto ts_out2;
557 } 547 }
558 548
559 lio_dr_cache = kmem_cache_create("lio_dr_cache", 549 lio_dr_cache = kmem_cache_create("lio_dr_cache",
@@ -597,8 +587,6 @@ dr_out:
597 kmem_cache_destroy(lio_dr_cache); 587 kmem_cache_destroy(lio_dr_cache);
598qr_out: 588qr_out:
599 kmem_cache_destroy(lio_qr_cache); 589 kmem_cache_destroy(lio_qr_cache);
600cmd_out:
601 kmem_cache_destroy(lio_cmd_cache);
602ts_out2: 590ts_out2:
603 iscsi_deallocate_thread_sets(); 591 iscsi_deallocate_thread_sets();
604ts_out1: 592ts_out1:
@@ -616,7 +604,6 @@ static void __exit iscsi_target_cleanup_module(void)
616 iscsi_thread_set_free(); 604 iscsi_thread_set_free();
617 iscsit_release_discovery_tpg(); 605 iscsit_release_discovery_tpg();
618 iscsit_unregister_transport(&iscsi_target_transport); 606 iscsit_unregister_transport(&iscsi_target_transport);
619 kmem_cache_destroy(lio_cmd_cache);
620 kmem_cache_destroy(lio_qr_cache); 607 kmem_cache_destroy(lio_qr_cache);
621 kmem_cache_destroy(lio_dr_cache); 608 kmem_cache_destroy(lio_dr_cache);
622 kmem_cache_destroy(lio_ooo_cache); 609 kmem_cache_destroy(lio_ooo_cache);
@@ -3447,12 +3434,10 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
3447 bool inaddr_any = iscsit_check_inaddr_any(np); 3434 bool inaddr_any = iscsit_check_inaddr_any(np);
3448 3435
3449 len = sprintf(buf, "TargetAddress=" 3436 len = sprintf(buf, "TargetAddress="
3450 "%s%s%s:%hu,%hu", 3437 "%s:%hu,%hu",
3451 (np->np_sockaddr.ss_family == AF_INET6) ? 3438 (inaddr_any == false) ?
3452 "[" : "", (inaddr_any == false) ?
3453 np->np_ip : conn->local_ip, 3439 np->np_ip : conn->local_ip,
3454 (np->np_sockaddr.ss_family == AF_INET6) ? 3440 (inaddr_any == false) ?
3455 "]" : "", (inaddr_any == false) ?
3456 np->np_port : conn->local_port, 3441 np->np_port : conn->local_port,
3457 tpg->tpgt); 3442 tpg->tpgt);
3458 len += 1; 3443 len += 1;
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index 2c437cb8ca00..e936d56fb523 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -7,13 +7,15 @@ extern void iscsit_put_tiqn_for_login(struct iscsi_tiqn *);
7extern struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *); 7extern struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *);
8extern void iscsit_del_tiqn(struct iscsi_tiqn *); 8extern void iscsit_del_tiqn(struct iscsi_tiqn *);
9extern int iscsit_access_np(struct iscsi_np *, struct iscsi_portal_group *); 9extern int iscsit_access_np(struct iscsi_np *, struct iscsi_portal_group *);
10extern int iscsit_deaccess_np(struct iscsi_np *, struct iscsi_portal_group *); 10extern void iscsit_login_kref_put(struct kref *);
11extern int iscsit_deaccess_np(struct iscsi_np *, struct iscsi_portal_group *,
12 struct iscsi_tpg_np *);
11extern bool iscsit_check_np_match(struct __kernel_sockaddr_storage *, 13extern bool iscsit_check_np_match(struct __kernel_sockaddr_storage *,
12 struct iscsi_np *, int); 14 struct iscsi_np *, int);
13extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *, 15extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,
14 char *, int); 16 char *, int);
15extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *, 17extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
16 struct iscsi_portal_group *); 18 struct iscsi_portal_group *, bool);
17extern int iscsit_del_np(struct iscsi_np *); 19extern int iscsit_del_np(struct iscsi_np *);
18extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *); 20extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *);
19extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); 21extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
@@ -37,7 +39,6 @@ extern struct target_fabric_configfs *lio_target_fabric_configfs;
37 39
38extern struct kmem_cache *lio_dr_cache; 40extern struct kmem_cache *lio_dr_cache;
39extern struct kmem_cache *lio_ooo_cache; 41extern struct kmem_cache *lio_ooo_cache;
40extern struct kmem_cache *lio_cmd_cache;
41extern struct kmem_cache *lio_qr_cache; 42extern struct kmem_cache *lio_qr_cache;
42extern struct kmem_cache *lio_r2t_cache; 43extern struct kmem_cache *lio_r2t_cache;
43 44
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index cee17543278c..7505fddca15f 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file houses the main functions for the iSCSI CHAP support 2 * This file houses the main functions for the iSCSI CHAP support
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index bbfd28893164..fd145259361d 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -2,9 +2,7 @@
2 * This file contains the configfs implementation for iSCSI Target mode 2 * This file contains the configfs implementation for iSCSI Target mode
3 * from the LIO-Target Project. 3 * from the LIO-Target Project.
4 * 4 *
5 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 5 * (c) Copyright 2007-2013 Datera, Inc.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * 6 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * 8 *
@@ -265,9 +263,9 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
265 *port_str = '\0'; /* Terminate string for IP */ 263 *port_str = '\0'; /* Terminate string for IP */
266 port_str++; /* Skip over ":" */ 264 port_str++; /* Skip over ":" */
267 265
268 ret = strict_strtoul(port_str, 0, &port); 266 ret = kstrtoul(port_str, 0, &port);
269 if (ret < 0) { 267 if (ret < 0) {
270 pr_err("strict_strtoul() failed for port_str: %d\n", ret); 268 pr_err("kstrtoul() failed for port_str: %d\n", ret);
271 return ERR_PTR(ret); 269 return ERR_PTR(ret);
272 } 270 }
273 sock_in6 = (struct sockaddr_in6 *)&sockaddr; 271 sock_in6 = (struct sockaddr_in6 *)&sockaddr;
@@ -290,9 +288,9 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
290 *port_str = '\0'; /* Terminate string for IP */ 288 *port_str = '\0'; /* Terminate string for IP */
291 port_str++; /* Skip over ":" */ 289 port_str++; /* Skip over ":" */
292 290
293 ret = strict_strtoul(port_str, 0, &port); 291 ret = kstrtoul(port_str, 0, &port);
294 if (ret < 0) { 292 if (ret < 0) {
295 pr_err("strict_strtoul() failed for port_str: %d\n", ret); 293 pr_err("kstrtoul() failed for port_str: %d\n", ret);
296 return ERR_PTR(ret); 294 return ERR_PTR(ret);
297 } 295 }
298 sock_in = (struct sockaddr_in *)&sockaddr; 296 sock_in = (struct sockaddr_in *)&sockaddr;
@@ -1481,7 +1479,7 @@ static ssize_t lio_target_wwn_show_attr_lio_version(
1481 struct target_fabric_configfs *tf, 1479 struct target_fabric_configfs *tf,
1482 char *page) 1480 char *page)
1483{ 1481{
1484 return sprintf(page, "RisingTide Systems Linux-iSCSI Target "ISCSIT_VERSION"\n"); 1482 return sprintf(page, "Datera Inc. iSCSI Target "ISCSIT_VERSION"\n");
1485} 1483}
1486 1484
1487TF_WWN_ATTR_RO(lio_target, lio_version); 1485TF_WWN_ATTR_RO(lio_target, lio_version);
@@ -1925,7 +1923,7 @@ static void lio_release_cmd(struct se_cmd *se_cmd)
1925 struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); 1923 struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
1926 1924
1927 pr_debug("Entering lio_release_cmd for se_cmd: %p\n", se_cmd); 1925 pr_debug("Entering lio_release_cmd for se_cmd: %p\n", se_cmd);
1928 cmd->release_cmd(cmd); 1926 iscsit_release_cmd(cmd);
1929} 1927}
1930 1928
1931/* End functions for target_core_fabric_ops */ 1929/* End functions for target_core_fabric_ops */
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 4f77a78edef9..9a5721b8ff96 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -9,7 +9,7 @@
9#include <scsi/iscsi_proto.h> 9#include <scsi/iscsi_proto.h>
10#include <target/target_core_base.h> 10#include <target/target_core_base.h>
11 11
12#define ISCSIT_VERSION "v4.1.0-rc2" 12#define ISCSIT_VERSION "v4.1.0"
13#define ISCSI_MAX_DATASN_MISSING_COUNT 16 13#define ISCSI_MAX_DATASN_MISSING_COUNT 16
14#define ISCSI_TX_THREAD_TCP_TIMEOUT 2 14#define ISCSI_TX_THREAD_TCP_TIMEOUT 2
15#define ISCSI_RX_THREAD_TCP_TIMEOUT 2 15#define ISCSI_RX_THREAD_TCP_TIMEOUT 2
@@ -17,6 +17,9 @@
17#define SECONDS_FOR_ASYNC_TEXT 10 17#define SECONDS_FOR_ASYNC_TEXT 10
18#define SECONDS_FOR_LOGOUT_COMP 15 18#define SECONDS_FOR_LOGOUT_COMP 15
19#define WHITE_SPACE " \t\v\f\n\r" 19#define WHITE_SPACE " \t\v\f\n\r"
20#define ISCSIT_MIN_TAGS 16
21#define ISCSIT_EXTRA_TAGS 8
22#define ISCSIT_TCP_BACKLOG 256
20 23
21/* struct iscsi_node_attrib sanity values */ 24/* struct iscsi_node_attrib sanity values */
22#define NA_DATAOUT_TIMEOUT 3 25#define NA_DATAOUT_TIMEOUT 3
@@ -47,7 +50,7 @@
47#define TA_NETIF_TIMEOUT_MAX 15 50#define TA_NETIF_TIMEOUT_MAX 15
48#define TA_NETIF_TIMEOUT_MIN 2 51#define TA_NETIF_TIMEOUT_MIN 2
49#define TA_GENERATE_NODE_ACLS 0 52#define TA_GENERATE_NODE_ACLS 0
50#define TA_DEFAULT_CMDSN_DEPTH 16 53#define TA_DEFAULT_CMDSN_DEPTH 64
51#define TA_DEFAULT_CMDSN_DEPTH_MAX 512 54#define TA_DEFAULT_CMDSN_DEPTH_MAX 512
52#define TA_DEFAULT_CMDSN_DEPTH_MIN 1 55#define TA_DEFAULT_CMDSN_DEPTH_MIN 1
53#define TA_CACHE_DYNAMIC_ACLS 0 56#define TA_CACHE_DYNAMIC_ACLS 0
@@ -489,7 +492,6 @@ struct iscsi_cmd {
489 u32 first_data_sg_off; 492 u32 first_data_sg_off;
490 u32 kmapped_nents; 493 u32 kmapped_nents;
491 sense_reason_t sense_reason; 494 sense_reason_t sense_reason;
492 void (*release_cmd)(struct iscsi_cmd *);
493} ____cacheline_aligned; 495} ____cacheline_aligned;
494 496
495struct iscsi_tmr_req { 497struct iscsi_tmr_req {
@@ -554,9 +556,19 @@ struct iscsi_conn {
554 struct completion rx_half_close_comp; 556 struct completion rx_half_close_comp;
555 /* socket used by this connection */ 557 /* socket used by this connection */
556 struct socket *sock; 558 struct socket *sock;
559 void (*orig_data_ready)(struct sock *, int);
560 void (*orig_state_change)(struct sock *);
561#define LOGIN_FLAGS_READ_ACTIVE 1
562#define LOGIN_FLAGS_CLOSED 2
563#define LOGIN_FLAGS_READY 4
564 unsigned long login_flags;
565 struct delayed_work login_work;
566 struct delayed_work login_cleanup_work;
567 struct iscsi_login *login;
557 struct timer_list nopin_timer; 568 struct timer_list nopin_timer;
558 struct timer_list nopin_response_timer; 569 struct timer_list nopin_response_timer;
559 struct timer_list transport_timer; 570 struct timer_list transport_timer;
571 struct task_struct *login_kworker;
560 /* Spinlock used for add/deleting cmd's from conn_cmd_list */ 572 /* Spinlock used for add/deleting cmd's from conn_cmd_list */
561 spinlock_t cmd_lock; 573 spinlock_t cmd_lock;
562 spinlock_t conn_usage_lock; 574 spinlock_t conn_usage_lock;
@@ -584,6 +596,7 @@ struct iscsi_conn {
584 void *context; 596 void *context;
585 struct iscsi_login_thread_s *login_thread; 597 struct iscsi_login_thread_s *login_thread;
586 struct iscsi_portal_group *tpg; 598 struct iscsi_portal_group *tpg;
599 struct iscsi_tpg_np *tpg_np;
587 /* Pointer to parent session */ 600 /* Pointer to parent session */
588 struct iscsi_session *sess; 601 struct iscsi_session *sess;
589 /* Pointer to thread_set in use for this conn's threads */ 602 /* Pointer to thread_set in use for this conn's threads */
@@ -682,6 +695,7 @@ struct iscsi_login {
682 u8 version_max; 695 u8 version_max;
683 u8 login_complete; 696 u8 login_complete;
684 u8 login_failed; 697 u8 login_failed;
698 bool zero_tsih;
685 char isid[6]; 699 char isid[6];
686 u32 cmd_sn; 700 u32 cmd_sn;
687 itt_t init_task_tag; 701 itt_t init_task_tag;
@@ -694,6 +708,7 @@ struct iscsi_login {
694 char *req_buf; 708 char *req_buf;
695 char *rsp_buf; 709 char *rsp_buf;
696 struct iscsi_conn *conn; 710 struct iscsi_conn *conn;
711 struct iscsi_np *np;
697} ____cacheline_aligned; 712} ____cacheline_aligned;
698 713
699struct iscsi_node_attrib { 714struct iscsi_node_attrib {
@@ -773,7 +788,6 @@ struct iscsi_np {
773 struct __kernel_sockaddr_storage np_sockaddr; 788 struct __kernel_sockaddr_storage np_sockaddr;
774 struct task_struct *np_thread; 789 struct task_struct *np_thread;
775 struct timer_list np_login_timer; 790 struct timer_list np_login_timer;
776 struct iscsi_portal_group *np_login_tpg;
777 void *np_context; 791 void *np_context;
778 struct iscsit_transport *np_transport; 792 struct iscsit_transport *np_transport;
779 struct list_head np_list; 793 struct list_head np_list;
@@ -788,6 +802,8 @@ struct iscsi_tpg_np {
788 struct list_head tpg_np_parent_list; 802 struct list_head tpg_np_parent_list;
789 struct se_tpg_np se_tpg_np; 803 struct se_tpg_np se_tpg_np;
790 spinlock_t tpg_np_parent_lock; 804 spinlock_t tpg_np_parent_lock;
805 struct completion tpg_np_comp;
806 struct kref tpg_np_kref;
791}; 807};
792 808
793struct iscsi_portal_group { 809struct iscsi_portal_group {
@@ -809,7 +825,7 @@ struct iscsi_portal_group {
809 spinlock_t tpg_state_lock; 825 spinlock_t tpg_state_lock;
810 struct se_portal_group tpg_se_tpg; 826 struct se_portal_group tpg_se_tpg;
811 struct mutex tpg_access_lock; 827 struct mutex tpg_access_lock;
812 struct mutex np_login_lock; 828 struct semaphore np_login_sem;
813 struct iscsi_tpg_attrib tpg_attrib; 829 struct iscsi_tpg_attrib tpg_attrib;
814 struct iscsi_node_auth tpg_demo_auth; 830 struct iscsi_node_auth tpg_demo_auth;
815 /* Pointer to default list of iSCSI parameters for TPG */ 831 /* Pointer to default list of iSCSI parameters for TPG */
diff --git a/drivers/target/iscsi/iscsi_target_datain_values.c b/drivers/target/iscsi/iscsi_target_datain_values.c
index 848fee768948..e93d5a7a3f81 100644
--- a/drivers/target/iscsi/iscsi_target_datain_values.c
+++ b/drivers/target/iscsi/iscsi_target_datain_values.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains the iSCSI Target DataIN value generation functions. 2 * This file contains the iSCSI Target DataIN value generation functions.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c
index 1b74033510a0..6c7a5104a4cd 100644
--- a/drivers/target/iscsi/iscsi_target_device.c
+++ b/drivers/target/iscsi/iscsi_target_device.c
@@ -2,9 +2,7 @@
2 * This file contains the iSCSI Virtual Device and Disk Transport 2 * This file contains the iSCSI Virtual Device and Disk Transport
3 * agnostic related functions. 3 * agnostic related functions.
4 * 4 *
5 \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 5 * (c) Copyright 2007-2013 Datera, Inc.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * 6 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * 8 *
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index 08bd87833321..41052e512d92 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -2,9 +2,7 @@
2 * This file contains error recovery level zero functions used by 2 * This file contains error recovery level zero functions used by
3 * the iSCSI Target driver. 3 * the iSCSI Target driver.
4 * 4 *
5 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 5 * (c) Copyright 2007-2013 Datera, Inc.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * 6 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * 8 *
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 586c268679a4..e048d6439f4a 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains error recovery level one used by the iSCSI Target driver. 2 * This file contains error recovery level one used by the iSCSI Target driver.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c
index 45a5afd5ea13..33be1fb1df32 100644
--- a/drivers/target/iscsi/iscsi_target_erl2.c
+++ b/drivers/target/iscsi/iscsi_target_erl2.c
@@ -2,9 +2,7 @@
2 * This file contains error recovery level two functions used by 2 * This file contains error recovery level two functions used by
3 * the iSCSI Target driver. 3 * the iSCSI Target driver.
4 * 4 *
5 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 5 * (c) Copyright 2007-2013 Datera, Inc.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * 6 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * 8 *
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index bc788c52b6cc..1794c753954a 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains the login functions used by the iSCSI Target driver. 2 * This file contains the login functions used by the iSCSI Target driver.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -50,6 +48,7 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn)
50 pr_err("Unable to allocate memory for struct iscsi_login.\n"); 48 pr_err("Unable to allocate memory for struct iscsi_login.\n");
51 return NULL; 49 return NULL;
52 } 50 }
51 conn->login = login;
53 login->conn = conn; 52 login->conn = conn;
54 login->first_request = 1; 53 login->first_request = 1;
55 54
@@ -428,7 +427,7 @@ static int iscsi_login_zero_tsih_s2(
428 ISCSI_LOGIN_STATUS_NO_RESOURCES); 427 ISCSI_LOGIN_STATUS_NO_RESOURCES);
429 return -1; 428 return -1;
430 } 429 }
431 rc = strict_strtoul(param->value, 0, &mrdsl); 430 rc = kstrtoul(param->value, 0, &mrdsl);
432 if (rc < 0) { 431 if (rc < 0) {
433 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, 432 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
434 ISCSI_LOGIN_STATUS_NO_RESOURCES); 433 ISCSI_LOGIN_STATUS_NO_RESOURCES);
@@ -684,7 +683,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
684 iscsit_start_nopin_timer(conn); 683 iscsit_start_nopin_timer(conn);
685} 684}
686 685
687static int iscsi_post_login_handler( 686int iscsi_post_login_handler(
688 struct iscsi_np *np, 687 struct iscsi_np *np,
689 struct iscsi_conn *conn, 688 struct iscsi_conn *conn,
690 u8 zero_tsih) 689 u8 zero_tsih)
@@ -872,7 +871,7 @@ int iscsit_setup_np(
872 struct __kernel_sockaddr_storage *sockaddr) 871 struct __kernel_sockaddr_storage *sockaddr)
873{ 872{
874 struct socket *sock = NULL; 873 struct socket *sock = NULL;
875 int backlog = 5, ret, opt = 0, len; 874 int backlog = ISCSIT_TCP_BACKLOG, ret, opt = 0, len;
876 875
877 switch (np->np_network_transport) { 876 switch (np->np_network_transport) {
878 case ISCSI_TCP: 877 case ISCSI_TCP:
@@ -1007,16 +1006,24 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
1007 rc = conn->sock->ops->getname(conn->sock, 1006 rc = conn->sock->ops->getname(conn->sock,
1008 (struct sockaddr *)&sock_in6, &err, 1); 1007 (struct sockaddr *)&sock_in6, &err, 1);
1009 if (!rc) { 1008 if (!rc) {
1010 snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", 1009 if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
1011 &sock_in6.sin6_addr.in6_u); 1010 snprintf(conn->login_ip, sizeof(conn->login_ip), "[%pI6c]",
1011 &sock_in6.sin6_addr.in6_u);
1012 else
1013 snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI4",
1014 &sock_in6.sin6_addr.s6_addr32[3]);
1012 conn->login_port = ntohs(sock_in6.sin6_port); 1015 conn->login_port = ntohs(sock_in6.sin6_port);
1013 } 1016 }
1014 1017
1015 rc = conn->sock->ops->getname(conn->sock, 1018 rc = conn->sock->ops->getname(conn->sock,
1016 (struct sockaddr *)&sock_in6, &err, 0); 1019 (struct sockaddr *)&sock_in6, &err, 0);
1017 if (!rc) { 1020 if (!rc) {
1018 snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", 1021 if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
1019 &sock_in6.sin6_addr.in6_u); 1022 snprintf(conn->local_ip, sizeof(conn->local_ip), "[%pI6c]",
1023 &sock_in6.sin6_addr.in6_u);
1024 else
1025 snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI4",
1026 &sock_in6.sin6_addr.s6_addr32[3]);
1020 conn->local_port = ntohs(sock_in6.sin6_port); 1027 conn->local_port = ntohs(sock_in6.sin6_port);
1021 } 1028 }
1022 } else { 1029 } else {
@@ -1116,6 +1123,77 @@ iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t)
1116 return 0; 1123 return 0;
1117} 1124}
1118 1125
1126void iscsi_target_login_sess_out(struct iscsi_conn *conn,
1127 struct iscsi_np *np, bool zero_tsih, bool new_sess)
1128{
1129 if (new_sess == false)
1130 goto old_sess_out;
1131
1132 pr_err("iSCSI Login negotiation failed.\n");
1133 iscsit_collect_login_stats(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
1134 ISCSI_LOGIN_STATUS_INIT_ERR);
1135 if (!zero_tsih || !conn->sess)
1136 goto old_sess_out;
1137 if (conn->sess->se_sess)
1138 transport_free_session(conn->sess->se_sess);
1139 if (conn->sess->session_index != 0) {
1140 spin_lock_bh(&sess_idr_lock);
1141 idr_remove(&sess_idr, conn->sess->session_index);
1142 spin_unlock_bh(&sess_idr_lock);
1143 }
1144 kfree(conn->sess->sess_ops);
1145 kfree(conn->sess);
1146
1147old_sess_out:
1148 iscsi_stop_login_thread_timer(np);
1149 /*
1150 * If login negotiation fails check if the Time2Retain timer
1151 * needs to be restarted.
1152 */
1153 if (!zero_tsih && conn->sess) {
1154 spin_lock_bh(&conn->sess->conn_lock);
1155 if (conn->sess->session_state == TARG_SESS_STATE_FAILED) {
1156 struct se_portal_group *se_tpg =
1157 &ISCSI_TPG_C(conn)->tpg_se_tpg;
1158
1159 atomic_set(&conn->sess->session_continuation, 0);
1160 spin_unlock_bh(&conn->sess->conn_lock);
1161 spin_lock_bh(&se_tpg->session_lock);
1162 iscsit_start_time2retain_handler(conn->sess);
1163 spin_unlock_bh(&se_tpg->session_lock);
1164 } else
1165 spin_unlock_bh(&conn->sess->conn_lock);
1166 iscsit_dec_session_usage_count(conn->sess);
1167 }
1168
1169 if (!IS_ERR(conn->conn_rx_hash.tfm))
1170 crypto_free_hash(conn->conn_rx_hash.tfm);
1171 if (!IS_ERR(conn->conn_tx_hash.tfm))
1172 crypto_free_hash(conn->conn_tx_hash.tfm);
1173
1174 if (conn->conn_cpumask)
1175 free_cpumask_var(conn->conn_cpumask);
1176
1177 kfree(conn->conn_ops);
1178
1179 if (conn->param_list) {
1180 iscsi_release_param_list(conn->param_list);
1181 conn->param_list = NULL;
1182 }
1183 iscsi_target_nego_release(conn);
1184
1185 if (conn->sock) {
1186 sock_release(conn->sock);
1187 conn->sock = NULL;
1188 }
1189
1190 if (conn->conn_transport->iscsit_free_conn)
1191 conn->conn_transport->iscsit_free_conn(conn);
1192
1193 iscsit_put_transport(conn->conn_transport);
1194 kfree(conn);
1195}
1196
1119static int __iscsi_target_login_thread(struct iscsi_np *np) 1197static int __iscsi_target_login_thread(struct iscsi_np *np)
1120{ 1198{
1121 u8 *buffer, zero_tsih = 0; 1199 u8 *buffer, zero_tsih = 0;
@@ -1124,6 +1202,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1124 struct iscsi_login *login; 1202 struct iscsi_login *login;
1125 struct iscsi_portal_group *tpg = NULL; 1203 struct iscsi_portal_group *tpg = NULL;
1126 struct iscsi_login_req *pdu; 1204 struct iscsi_login_req *pdu;
1205 struct iscsi_tpg_np *tpg_np;
1206 bool new_sess = false;
1127 1207
1128 flush_signals(current); 1208 flush_signals(current);
1129 1209
@@ -1264,6 +1344,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1264 tpg = conn->tpg; 1344 tpg = conn->tpg;
1265 goto new_sess_out; 1345 goto new_sess_out;
1266 } 1346 }
1347 login->zero_tsih = zero_tsih;
1267 1348
1268 tpg = conn->tpg; 1349 tpg = conn->tpg;
1269 if (!tpg) { 1350 if (!tpg) {
@@ -1279,7 +1360,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1279 goto old_sess_out; 1360 goto old_sess_out;
1280 } 1361 }
1281 1362
1282 if (iscsi_target_start_negotiation(login, conn) < 0) 1363 ret = iscsi_target_start_negotiation(login, conn);
1364 if (ret < 0)
1283 goto new_sess_out; 1365 goto new_sess_out;
1284 1366
1285 if (!conn->sess) { 1367 if (!conn->sess) {
@@ -1292,84 +1374,32 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1292 if (signal_pending(current)) 1374 if (signal_pending(current))
1293 goto new_sess_out; 1375 goto new_sess_out;
1294 1376
1295 ret = iscsi_post_login_handler(np, conn, zero_tsih); 1377 if (ret == 1) {
1378 tpg_np = conn->tpg_np;
1296 1379
1297 if (ret < 0) 1380 ret = iscsi_post_login_handler(np, conn, zero_tsih);
1298 goto new_sess_out; 1381 if (ret < 0)
1382 goto new_sess_out;
1383
1384 iscsit_deaccess_np(np, tpg, tpg_np);
1385 }
1299 1386
1300 iscsit_deaccess_np(np, tpg);
1301 tpg = NULL; 1387 tpg = NULL;
1388 tpg_np = NULL;
1302 /* Get another socket */ 1389 /* Get another socket */
1303 return 1; 1390 return 1;
1304 1391
1305new_sess_out: 1392new_sess_out:
1306 pr_err("iSCSI Login negotiation failed.\n"); 1393 new_sess = true;
1307 iscsit_collect_login_stats(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
1308 ISCSI_LOGIN_STATUS_INIT_ERR);
1309 if (!zero_tsih || !conn->sess)
1310 goto old_sess_out;
1311 if (conn->sess->se_sess)
1312 transport_free_session(conn->sess->se_sess);
1313 if (conn->sess->session_index != 0) {
1314 spin_lock_bh(&sess_idr_lock);
1315 idr_remove(&sess_idr, conn->sess->session_index);
1316 spin_unlock_bh(&sess_idr_lock);
1317 }
1318 kfree(conn->sess->sess_ops);
1319 kfree(conn->sess);
1320old_sess_out: 1394old_sess_out:
1321 iscsi_stop_login_thread_timer(np); 1395 tpg_np = conn->tpg_np;
1322 /* 1396 iscsi_target_login_sess_out(conn, np, zero_tsih, new_sess);
1323 * If login negotiation fails check if the Time2Retain timer 1397 new_sess = false;
1324 * needs to be restarted.
1325 */
1326 if (!zero_tsih && conn->sess) {
1327 spin_lock_bh(&conn->sess->conn_lock);
1328 if (conn->sess->session_state == TARG_SESS_STATE_FAILED) {
1329 struct se_portal_group *se_tpg =
1330 &ISCSI_TPG_C(conn)->tpg_se_tpg;
1331
1332 atomic_set(&conn->sess->session_continuation, 0);
1333 spin_unlock_bh(&conn->sess->conn_lock);
1334 spin_lock_bh(&se_tpg->session_lock);
1335 iscsit_start_time2retain_handler(conn->sess);
1336 spin_unlock_bh(&se_tpg->session_lock);
1337 } else
1338 spin_unlock_bh(&conn->sess->conn_lock);
1339 iscsit_dec_session_usage_count(conn->sess);
1340 }
1341
1342 if (!IS_ERR(conn->conn_rx_hash.tfm))
1343 crypto_free_hash(conn->conn_rx_hash.tfm);
1344 if (!IS_ERR(conn->conn_tx_hash.tfm))
1345 crypto_free_hash(conn->conn_tx_hash.tfm);
1346
1347 if (conn->conn_cpumask)
1348 free_cpumask_var(conn->conn_cpumask);
1349
1350 kfree(conn->conn_ops);
1351
1352 if (conn->param_list) {
1353 iscsi_release_param_list(conn->param_list);
1354 conn->param_list = NULL;
1355 }
1356 iscsi_target_nego_release(conn);
1357
1358 if (conn->sock) {
1359 sock_release(conn->sock);
1360 conn->sock = NULL;
1361 }
1362
1363 if (conn->conn_transport->iscsit_free_conn)
1364 conn->conn_transport->iscsit_free_conn(conn);
1365
1366 iscsit_put_transport(conn->conn_transport);
1367
1368 kfree(conn);
1369 1398
1370 if (tpg) { 1399 if (tpg) {
1371 iscsit_deaccess_np(np, tpg); 1400 iscsit_deaccess_np(np, tpg, tpg_np);
1372 tpg = NULL; 1401 tpg = NULL;
1402 tpg_np = NULL;
1373 } 1403 }
1374 1404
1375out: 1405out:
diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h
index 63efd2878451..29d098324b7f 100644
--- a/drivers/target/iscsi/iscsi_target_login.h
+++ b/drivers/target/iscsi/iscsi_target_login.h
@@ -12,6 +12,9 @@ extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
12extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); 12extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
13extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); 13extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
14extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); 14extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *);
15extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
16extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
17 bool, bool);
15extern int iscsi_target_login_thread(void *); 18extern int iscsi_target_login_thread(void *);
16extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *); 19extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);
17 20
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index c4675b4ceb49..14d1aed5af1d 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains main functions related to iSCSI Parameter negotiation. 2 * This file contains main functions related to iSCSI Parameter negotiation.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -377,15 +375,284 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
377 return 0; 375 return 0;
378} 376}
379 377
380static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login) 378static void iscsi_target_sk_data_ready(struct sock *sk, int count)
381{ 379{
382 if (iscsi_target_do_tx_login_io(conn, login) < 0) 380 struct iscsi_conn *conn = sk->sk_user_data;
383 return -1; 381 bool rc;
384 382
385 if (conn->conn_transport->iscsit_get_login_rx(conn, login) < 0) 383 pr_debug("Entering iscsi_target_sk_data_ready: conn: %p\n", conn);
386 return -1;
387 384
388 return 0; 385 write_lock_bh(&sk->sk_callback_lock);
386 if (!sk->sk_user_data) {
387 write_unlock_bh(&sk->sk_callback_lock);
388 return;
389 }
390 if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) {
391 write_unlock_bh(&sk->sk_callback_lock);
392 pr_debug("Got LOGIN_FLAGS_READY=0, conn: %p >>>>\n", conn);
393 return;
394 }
395 if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
396 write_unlock_bh(&sk->sk_callback_lock);
397 pr_debug("Got LOGIN_FLAGS_CLOSED=1, conn: %p >>>>\n", conn);
398 return;
399 }
400 if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) {
401 write_unlock_bh(&sk->sk_callback_lock);
402 pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p >>>>\n", conn);
403 return;
404 }
405
406 rc = schedule_delayed_work(&conn->login_work, 0);
407 if (rc == false) {
408 pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work"
409 " got false\n");
410 }
411 write_unlock_bh(&sk->sk_callback_lock);
412}
413
414static void iscsi_target_sk_state_change(struct sock *);
415
416static void iscsi_target_set_sock_callbacks(struct iscsi_conn *conn)
417{
418 struct sock *sk;
419
420 if (!conn->sock)
421 return;
422
423 sk = conn->sock->sk;
424 pr_debug("Entering iscsi_target_set_sock_callbacks: conn: %p\n", conn);
425
426 write_lock_bh(&sk->sk_callback_lock);
427 sk->sk_user_data = conn;
428 conn->orig_data_ready = sk->sk_data_ready;
429 conn->orig_state_change = sk->sk_state_change;
430 sk->sk_data_ready = iscsi_target_sk_data_ready;
431 sk->sk_state_change = iscsi_target_sk_state_change;
432 write_unlock_bh(&sk->sk_callback_lock);
433
434 sk->sk_sndtimeo = TA_LOGIN_TIMEOUT * HZ;
435 sk->sk_rcvtimeo = TA_LOGIN_TIMEOUT * HZ;
436}
437
438static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn)
439{
440 struct sock *sk;
441
442 if (!conn->sock)
443 return;
444
445 sk = conn->sock->sk;
446 pr_debug("Entering iscsi_target_restore_sock_callbacks: conn: %p\n", conn);
447
448 write_lock_bh(&sk->sk_callback_lock);
449 if (!sk->sk_user_data) {
450 write_unlock_bh(&sk->sk_callback_lock);
451 return;
452 }
453 sk->sk_user_data = NULL;
454 sk->sk_data_ready = conn->orig_data_ready;
455 sk->sk_state_change = conn->orig_state_change;
456 write_unlock_bh(&sk->sk_callback_lock);
457
458 sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
459 sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
460}
461
462static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *);
463
464static bool iscsi_target_sk_state_check(struct sock *sk)
465{
466 if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) {
467 pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE,"
468 "returning FALSE\n");
469 return false;
470 }
471 return true;
472}
473
474static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login)
475{
476 struct iscsi_np *np = login->np;
477 bool zero_tsih = login->zero_tsih;
478
479 iscsi_remove_failed_auth_entry(conn);
480 iscsi_target_nego_release(conn);
481 iscsi_target_login_sess_out(conn, np, zero_tsih, true);
482}
483
484static void iscsi_target_login_timeout(unsigned long data)
485{
486 struct iscsi_conn *conn = (struct iscsi_conn *)data;
487
488 pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
489
490 if (conn->login_kworker) {
491 pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
492 conn->login_kworker->comm, conn->login_kworker->pid);
493 send_sig(SIGINT, conn->login_kworker, 1);
494 }
495}
496
497static void iscsi_target_do_login_rx(struct work_struct *work)
498{
499 struct iscsi_conn *conn = container_of(work,
500 struct iscsi_conn, login_work.work);
501 struct iscsi_login *login = conn->login;
502 struct iscsi_np *np = login->np;
503 struct iscsi_portal_group *tpg = conn->tpg;
504 struct iscsi_tpg_np *tpg_np = conn->tpg_np;
505 struct timer_list login_timer;
506 int rc, zero_tsih = login->zero_tsih;
507 bool state;
508
509 pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n",
510 conn, current->comm, current->pid);
511
512 spin_lock(&tpg->tpg_state_lock);
513 state = (tpg->tpg_state == TPG_STATE_ACTIVE);
514 spin_unlock(&tpg->tpg_state_lock);
515
516 if (state == false) {
517 pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n");
518 iscsi_target_restore_sock_callbacks(conn);
519 iscsi_target_login_drop(conn, login);
520 iscsit_deaccess_np(np, tpg, tpg_np);
521 return;
522 }
523
524 if (conn->sock) {
525 struct sock *sk = conn->sock->sk;
526
527 read_lock_bh(&sk->sk_callback_lock);
528 state = iscsi_target_sk_state_check(sk);
529 read_unlock_bh(&sk->sk_callback_lock);
530
531 if (state == false) {
532 pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n");
533 iscsi_target_restore_sock_callbacks(conn);
534 iscsi_target_login_drop(conn, login);
535 iscsit_deaccess_np(np, tpg, tpg_np);
536 return;
537 }
538 }
539
540 conn->login_kworker = current;
541 allow_signal(SIGINT);
542
543 init_timer(&login_timer);
544 login_timer.expires = (get_jiffies_64() + TA_LOGIN_TIMEOUT * HZ);
545 login_timer.data = (unsigned long)conn;
546 login_timer.function = iscsi_target_login_timeout;
547 add_timer(&login_timer);
548 pr_debug("Starting login_timer for %s/%d\n", current->comm, current->pid);
549
550 rc = conn->conn_transport->iscsit_get_login_rx(conn, login);
551 del_timer_sync(&login_timer);
552 flush_signals(current);
553 conn->login_kworker = NULL;
554
555 if (rc < 0) {
556 iscsi_target_restore_sock_callbacks(conn);
557 iscsi_target_login_drop(conn, login);
558 iscsit_deaccess_np(np, tpg, tpg_np);
559 return;
560 }
561
562 pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n",
563 conn, current->comm, current->pid);
564
565 rc = iscsi_target_do_login(conn, login);
566 if (rc < 0) {
567 iscsi_target_restore_sock_callbacks(conn);
568 iscsi_target_login_drop(conn, login);
569 iscsit_deaccess_np(np, tpg, tpg_np);
570 } else if (!rc) {
571 if (conn->sock) {
572 struct sock *sk = conn->sock->sk;
573
574 write_lock_bh(&sk->sk_callback_lock);
575 clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags);
576 write_unlock_bh(&sk->sk_callback_lock);
577 }
578 } else if (rc == 1) {
579 iscsi_target_nego_release(conn);
580 iscsi_post_login_handler(np, conn, zero_tsih);
581 iscsit_deaccess_np(np, tpg, tpg_np);
582 }
583}
584
585static void iscsi_target_do_cleanup(struct work_struct *work)
586{
587 struct iscsi_conn *conn = container_of(work,
588 struct iscsi_conn, login_cleanup_work.work);
589 struct sock *sk = conn->sock->sk;
590 struct iscsi_login *login = conn->login;
591 struct iscsi_np *np = login->np;
592 struct iscsi_portal_group *tpg = conn->tpg;
593 struct iscsi_tpg_np *tpg_np = conn->tpg_np;
594
595 pr_debug("Entering iscsi_target_do_cleanup\n");
596
597 cancel_delayed_work_sync(&conn->login_work);
598 conn->orig_state_change(sk);
599
600 iscsi_target_restore_sock_callbacks(conn);
601 iscsi_target_login_drop(conn, login);
602 iscsit_deaccess_np(np, tpg, tpg_np);
603
604 pr_debug("iscsi_target_do_cleanup done()\n");
605}
606
607static void iscsi_target_sk_state_change(struct sock *sk)
608{
609 struct iscsi_conn *conn;
610 void (*orig_state_change)(struct sock *);
611 bool state;
612
613 pr_debug("Entering iscsi_target_sk_state_change\n");
614
615 write_lock_bh(&sk->sk_callback_lock);
616 conn = sk->sk_user_data;
617 if (!conn) {
618 write_unlock_bh(&sk->sk_callback_lock);
619 return;
620 }
621 orig_state_change = conn->orig_state_change;
622
623 if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) {
624 pr_debug("Got LOGIN_FLAGS_READY=0 sk_state_change conn: %p\n",
625 conn);
626 write_unlock_bh(&sk->sk_callback_lock);
627 orig_state_change(sk);
628 return;
629 }
630 if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) {
631 pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change"
632 " conn: %p\n", conn);
633 write_unlock_bh(&sk->sk_callback_lock);
634 orig_state_change(sk);
635 return;
636 }
637 if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
638 pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n",
639 conn);
640 write_unlock_bh(&sk->sk_callback_lock);
641 orig_state_change(sk);
642 return;
643 }
644
645 state = iscsi_target_sk_state_check(sk);
646 write_unlock_bh(&sk->sk_callback_lock);
647
648 pr_debug("iscsi_target_sk_state_change: state: %d\n", state);
649
650 if (!state) {
651 pr_debug("iscsi_target_sk_state_change got failed state\n");
652 schedule_delayed_work(&conn->login_cleanup_work, 0);
653 return;
654 }
655 orig_state_change(sk);
389} 656}
390 657
391/* 658/*
@@ -643,10 +910,11 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
643 if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { 910 if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
644 login->tsih = conn->sess->tsih; 911 login->tsih = conn->sess->tsih;
645 login->login_complete = 1; 912 login->login_complete = 1;
913 iscsi_target_restore_sock_callbacks(conn);
646 if (iscsi_target_do_tx_login_io(conn, 914 if (iscsi_target_do_tx_login_io(conn,
647 login) < 0) 915 login) < 0)
648 return -1; 916 return -1;
649 return 0; 917 return 1;
650 } 918 }
651 break; 919 break;
652 default: 920 default:
@@ -656,13 +924,29 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
656 break; 924 break;
657 } 925 }
658 926
659 if (iscsi_target_do_login_io(conn, login) < 0) 927 if (iscsi_target_do_tx_login_io(conn, login) < 0)
660 return -1; 928 return -1;
661 929
662 if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { 930 if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
663 login_rsp->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT; 931 login_rsp->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT;
664 login_rsp->flags &= ~ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; 932 login_rsp->flags &= ~ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK;
665 } 933 }
934 break;
935 }
936
937 if (conn->sock) {
938 struct sock *sk = conn->sock->sk;
939 bool state;
940
941 read_lock_bh(&sk->sk_callback_lock);
942 state = iscsi_target_sk_state_check(sk);
943 read_unlock_bh(&sk->sk_callback_lock);
944
945 if (!state) {
946 pr_debug("iscsi_target_do_login() failed state for"
947 " conn: %p\n", conn);
948 return -1;
949 }
666 } 950 }
667 951
668 return 0; 952 return 0;
@@ -695,9 +979,17 @@ int iscsi_target_locate_portal(
695 char *tmpbuf, *start = NULL, *end = NULL, *key, *value; 979 char *tmpbuf, *start = NULL, *end = NULL, *key, *value;
696 struct iscsi_session *sess = conn->sess; 980 struct iscsi_session *sess = conn->sess;
697 struct iscsi_tiqn *tiqn; 981 struct iscsi_tiqn *tiqn;
982 struct iscsi_tpg_np *tpg_np = NULL;
698 struct iscsi_login_req *login_req; 983 struct iscsi_login_req *login_req;
699 u32 payload_length; 984 struct se_node_acl *se_nacl;
700 int sessiontype = 0, ret = 0; 985 u32 payload_length, queue_depth = 0;
986 int sessiontype = 0, ret = 0, tag_num, tag_size;
987
988 INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx);
989 INIT_DELAYED_WORK(&conn->login_cleanup_work, iscsi_target_do_cleanup);
990 iscsi_target_set_sock_callbacks(conn);
991
992 login->np = np;
701 993
702 login_req = (struct iscsi_login_req *) login->req; 994 login_req = (struct iscsi_login_req *) login->req;
703 payload_length = ntoh24(login_req->dlength); 995 payload_length = ntoh24(login_req->dlength);
@@ -791,7 +1083,7 @@ int iscsi_target_locate_portal(
791 goto out; 1083 goto out;
792 } 1084 }
793 ret = 0; 1085 ret = 0;
794 goto out; 1086 goto alloc_tags;
795 } 1087 }
796 1088
797get_target: 1089get_target:
@@ -822,7 +1114,7 @@ get_target:
822 /* 1114 /*
823 * Locate Target Portal Group from Storage Node. 1115 * Locate Target Portal Group from Storage Node.
824 */ 1116 */
825 conn->tpg = iscsit_get_tpg_from_np(tiqn, np); 1117 conn->tpg = iscsit_get_tpg_from_np(tiqn, np, &tpg_np);
826 if (!conn->tpg) { 1118 if (!conn->tpg) {
827 pr_err("Unable to locate Target Portal Group" 1119 pr_err("Unable to locate Target Portal Group"
828 " on %s\n", tiqn->tiqn); 1120 " on %s\n", tiqn->tiqn);
@@ -832,12 +1124,16 @@ get_target:
832 ret = -1; 1124 ret = -1;
833 goto out; 1125 goto out;
834 } 1126 }
1127 conn->tpg_np = tpg_np;
835 pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt); 1128 pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt);
836 /* 1129 /*
837 * Setup crc32c modules from libcrypto 1130 * Setup crc32c modules from libcrypto
838 */ 1131 */
839 if (iscsi_login_setup_crypto(conn) < 0) { 1132 if (iscsi_login_setup_crypto(conn) < 0) {
840 pr_err("iscsi_login_setup_crypto() failed\n"); 1133 pr_err("iscsi_login_setup_crypto() failed\n");
1134 kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
1135 iscsit_put_tiqn_for_login(tiqn);
1136 conn->tpg = NULL;
841 ret = -1; 1137 ret = -1;
842 goto out; 1138 goto out;
843 } 1139 }
@@ -846,11 +1142,12 @@ get_target:
846 * process login attempt. 1142 * process login attempt.
847 */ 1143 */
848 if (iscsit_access_np(np, conn->tpg) < 0) { 1144 if (iscsit_access_np(np, conn->tpg) < 0) {
1145 kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put);
849 iscsit_put_tiqn_for_login(tiqn); 1146 iscsit_put_tiqn_for_login(tiqn);
850 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, 1147 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
851 ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); 1148 ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
852 ret = -1;
853 conn->tpg = NULL; 1149 conn->tpg = NULL;
1150 ret = -1;
854 goto out; 1151 goto out;
855 } 1152 }
856 1153
@@ -883,8 +1180,27 @@ get_target:
883 ret = -1; 1180 ret = -1;
884 goto out; 1181 goto out;
885 } 1182 }
1183 se_nacl = sess->se_sess->se_node_acl;
1184 queue_depth = se_nacl->queue_depth;
1185 /*
1186 * Setup pre-allocated tags based upon allowed per NodeACL CmdSN
1187 * depth for non immediate commands, plus extra tags for immediate
1188 * commands.
1189 *
1190 * Also enforce a ISCSIT_MIN_TAGS to prevent unnecessary contention
1191 * in per-cpu-ida tag allocation logic + small queue_depth.
1192 */
1193alloc_tags:
1194 tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth);
1195 tag_num += ISCSIT_EXTRA_TAGS;
1196 tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
886 1197
887 ret = 0; 1198 ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size);
1199 if (ret < 0) {
1200 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
1201 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1202 ret = -1;
1203 }
888out: 1204out:
889 kfree(tmpbuf); 1205 kfree(tmpbuf);
890 return ret; 1206 return ret;
@@ -897,10 +1213,23 @@ int iscsi_target_start_negotiation(
897 int ret; 1213 int ret;
898 1214
899 ret = iscsi_target_do_login(conn, login); 1215 ret = iscsi_target_do_login(conn, login);
900 if (ret != 0) 1216 if (!ret) {
1217 if (conn->sock) {
1218 struct sock *sk = conn->sock->sk;
1219
1220 write_lock_bh(&sk->sk_callback_lock);
1221 set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
1222 write_unlock_bh(&sk->sk_callback_lock);
1223 }
1224 } else if (ret < 0) {
1225 cancel_delayed_work_sync(&conn->login_work);
1226 cancel_delayed_work_sync(&conn->login_cleanup_work);
1227 iscsi_target_restore_sock_callbacks(conn);
901 iscsi_remove_failed_auth_entry(conn); 1228 iscsi_remove_failed_auth_entry(conn);
1229 }
1230 if (ret != 0)
1231 iscsi_target_nego_release(conn);
902 1232
903 iscsi_target_nego_release(conn);
904 return ret; 1233 return ret;
905} 1234}
906 1235
diff --git a/drivers/target/iscsi/iscsi_target_nodeattrib.c b/drivers/target/iscsi/iscsi_target_nodeattrib.c
index 11dc2936af76..93bdc475eb00 100644
--- a/drivers/target/iscsi/iscsi_target_nodeattrib.c
+++ b/drivers/target/iscsi/iscsi_target_nodeattrib.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains the main functions related to Initiator Node Attributes. 2 * This file contains the main functions related to Initiator Node Attributes.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 35fd6439eb01..4d2e23fc76fd 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains main functions related to iSCSI Parameter negotiation. 2 * This file contains main functions related to iSCSI Parameter negotiation.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -1182,7 +1180,7 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
1182 unsigned long long tmp; 1180 unsigned long long tmp;
1183 int rc; 1181 int rc;
1184 1182
1185 rc = strict_strtoull(param->value, 0, &tmp); 1183 rc = kstrtoull(param->value, 0, &tmp);
1186 if (rc < 0) 1184 if (rc < 0)
1187 return -1; 1185 return -1;
1188 1186
diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
index edb592a368ef..ca41b583f2f6 100644
--- a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
+++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
@@ -2,9 +2,7 @@
2 * This file contains main functions related to iSCSI DataSequenceInOrder=No 2 * This file contains main functions related to iSCSI DataSequenceInOrder=No
3 * and DataPDUInOrder=No. 3 * and DataPDUInOrder=No.
4 * 4 *
5 \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 5 * (c) Copyright 2007-2013 Datera, Inc.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * 6 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * 8 *
diff --git a/drivers/target/iscsi/iscsi_target_stat.c b/drivers/target/iscsi/iscsi_target_stat.c
index 464b4206a51e..f788e8b5e855 100644
--- a/drivers/target/iscsi/iscsi_target_stat.c
+++ b/drivers/target/iscsi/iscsi_target_stat.c
@@ -2,9 +2,7 @@
2 * Modern ConfigFS group context specific iSCSI statistics based on original 2 * Modern ConfigFS group context specific iSCSI statistics based on original
3 * iscsi_target_mib.c code 3 * iscsi_target_mib.c code
4 * 4 *
5 * Copyright (c) 2011 Rising Tide Systems 5 * Copyright (c) 2011-2013 Datera, Inc.
6 *
7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * 6 *
9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * 8 *
@@ -177,7 +175,7 @@ ISCSI_STAT_INSTANCE_ATTR_RO(description);
177static ssize_t iscsi_stat_instance_show_attr_vendor( 175static ssize_t iscsi_stat_instance_show_attr_vendor(
178 struct iscsi_wwn_stat_grps *igrps, char *page) 176 struct iscsi_wwn_stat_grps *igrps, char *page)
179{ 177{
180 return snprintf(page, PAGE_SIZE, "RisingTide Systems iSCSI-Target\n"); 178 return snprintf(page, PAGE_SIZE, "Datera, Inc. iSCSI-Target\n");
181} 179}
182ISCSI_STAT_INSTANCE_ATTR_RO(vendor); 180ISCSI_STAT_INSTANCE_ATTR_RO(vendor);
183 181
@@ -432,13 +430,7 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
432 int ret; 430 int ret;
433 431
434 spin_lock(&lstat->lock); 432 spin_lock(&lstat->lock);
435 if (lstat->last_intr_fail_ip_family == AF_INET6) { 433 ret = snprintf(page, PAGE_SIZE, "%s\n", lstat->last_intr_fail_ip_addr);
436 ret = snprintf(page, PAGE_SIZE, "[%s]\n",
437 lstat->last_intr_fail_ip_addr);
438 } else {
439 ret = snprintf(page, PAGE_SIZE, "%s\n",
440 lstat->last_intr_fail_ip_addr);
441 }
442 spin_unlock(&lstat->lock); 434 spin_unlock(&lstat->lock);
443 435
444 return ret; 436 return ret;
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index b997e5da47d3..78404b1cc0bf 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains the iSCSI Target specific Task Management functions. 2 * This file contains the iSCSI Target specific Task Management functions.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 439260b7d87f..4faeb47fa5e1 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains iSCSI Target Portal Group related functions. 2 * This file contains iSCSI Target Portal Group related functions.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -49,7 +47,7 @@ struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *tiqn, u1
49 INIT_LIST_HEAD(&tpg->tpg_gnp_list); 47 INIT_LIST_HEAD(&tpg->tpg_gnp_list);
50 INIT_LIST_HEAD(&tpg->tpg_list); 48 INIT_LIST_HEAD(&tpg->tpg_list);
51 mutex_init(&tpg->tpg_access_lock); 49 mutex_init(&tpg->tpg_access_lock);
52 mutex_init(&tpg->np_login_lock); 50 sema_init(&tpg->np_login_sem, 1);
53 spin_lock_init(&tpg->tpg_state_lock); 51 spin_lock_init(&tpg->tpg_state_lock);
54 spin_lock_init(&tpg->tpg_np_lock); 52 spin_lock_init(&tpg->tpg_np_lock);
55 53
@@ -129,7 +127,8 @@ void iscsit_release_discovery_tpg(void)
129 127
130struct iscsi_portal_group *iscsit_get_tpg_from_np( 128struct iscsi_portal_group *iscsit_get_tpg_from_np(
131 struct iscsi_tiqn *tiqn, 129 struct iscsi_tiqn *tiqn,
132 struct iscsi_np *np) 130 struct iscsi_np *np,
131 struct iscsi_tpg_np **tpg_np_out)
133{ 132{
134 struct iscsi_portal_group *tpg = NULL; 133 struct iscsi_portal_group *tpg = NULL;
135 struct iscsi_tpg_np *tpg_np; 134 struct iscsi_tpg_np *tpg_np;
@@ -147,6 +146,8 @@ struct iscsi_portal_group *iscsit_get_tpg_from_np(
147 spin_lock(&tpg->tpg_np_lock); 146 spin_lock(&tpg->tpg_np_lock);
148 list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) { 147 list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) {
149 if (tpg_np->tpg_np == np) { 148 if (tpg_np->tpg_np == np) {
149 *tpg_np_out = tpg_np;
150 kref_get(&tpg_np->tpg_np_kref);
150 spin_unlock(&tpg->tpg_np_lock); 151 spin_unlock(&tpg->tpg_np_lock);
151 spin_unlock(&tiqn->tiqn_tpg_lock); 152 spin_unlock(&tiqn->tiqn_tpg_lock);
152 return tpg; 153 return tpg;
@@ -175,18 +176,20 @@ void iscsit_put_tpg(struct iscsi_portal_group *tpg)
175 176
176static void iscsit_clear_tpg_np_login_thread( 177static void iscsit_clear_tpg_np_login_thread(
177 struct iscsi_tpg_np *tpg_np, 178 struct iscsi_tpg_np *tpg_np,
178 struct iscsi_portal_group *tpg) 179 struct iscsi_portal_group *tpg,
180 bool shutdown)
179{ 181{
180 if (!tpg_np->tpg_np) { 182 if (!tpg_np->tpg_np) {
181 pr_err("struct iscsi_tpg_np->tpg_np is NULL!\n"); 183 pr_err("struct iscsi_tpg_np->tpg_np is NULL!\n");
182 return; 184 return;
183 } 185 }
184 186
185 iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg); 187 iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown);
186} 188}
187 189
188void iscsit_clear_tpg_np_login_threads( 190void iscsit_clear_tpg_np_login_threads(
189 struct iscsi_portal_group *tpg) 191 struct iscsi_portal_group *tpg,
192 bool shutdown)
190{ 193{
191 struct iscsi_tpg_np *tpg_np; 194 struct iscsi_tpg_np *tpg_np;
192 195
@@ -197,7 +200,7 @@ void iscsit_clear_tpg_np_login_threads(
197 continue; 200 continue;
198 } 201 }
199 spin_unlock(&tpg->tpg_np_lock); 202 spin_unlock(&tpg->tpg_np_lock);
200 iscsit_clear_tpg_np_login_thread(tpg_np, tpg); 203 iscsit_clear_tpg_np_login_thread(tpg_np, tpg, shutdown);
201 spin_lock(&tpg->tpg_np_lock); 204 spin_lock(&tpg->tpg_np_lock);
202 } 205 }
203 spin_unlock(&tpg->tpg_np_lock); 206 spin_unlock(&tpg->tpg_np_lock);
@@ -268,6 +271,8 @@ int iscsit_tpg_del_portal_group(
268 tpg->tpg_state = TPG_STATE_INACTIVE; 271 tpg->tpg_state = TPG_STATE_INACTIVE;
269 spin_unlock(&tpg->tpg_state_lock); 272 spin_unlock(&tpg->tpg_state_lock);
270 273
274 iscsit_clear_tpg_np_login_threads(tpg, true);
275
271 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) { 276 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) {
272 pr_err("Unable to delete iSCSI Target Portal Group:" 277 pr_err("Unable to delete iSCSI Target Portal Group:"
273 " %hu while active sessions exist, and force=0\n", 278 " %hu while active sessions exist, and force=0\n",
@@ -368,7 +373,7 @@ int iscsit_tpg_disable_portal_group(struct iscsi_portal_group *tpg, int force)
368 tpg->tpg_state = TPG_STATE_INACTIVE; 373 tpg->tpg_state = TPG_STATE_INACTIVE;
369 spin_unlock(&tpg->tpg_state_lock); 374 spin_unlock(&tpg->tpg_state_lock);
370 375
371 iscsit_clear_tpg_np_login_threads(tpg); 376 iscsit_clear_tpg_np_login_threads(tpg, false);
372 377
373 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) { 378 if (iscsit_release_sessions_for_tpg(tpg, force) < 0) {
374 spin_lock(&tpg->tpg_state_lock); 379 spin_lock(&tpg->tpg_state_lock);
@@ -490,6 +495,8 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
490 INIT_LIST_HEAD(&tpg_np->tpg_np_child_list); 495 INIT_LIST_HEAD(&tpg_np->tpg_np_child_list);
491 INIT_LIST_HEAD(&tpg_np->tpg_np_parent_list); 496 INIT_LIST_HEAD(&tpg_np->tpg_np_parent_list);
492 spin_lock_init(&tpg_np->tpg_np_parent_lock); 497 spin_lock_init(&tpg_np->tpg_np_parent_lock);
498 init_completion(&tpg_np->tpg_np_comp);
499 kref_init(&tpg_np->tpg_np_kref);
493 tpg_np->tpg_np = np; 500 tpg_np->tpg_np = np;
494 tpg_np->tpg = tpg; 501 tpg_np->tpg = tpg;
495 502
@@ -520,7 +527,7 @@ static int iscsit_tpg_release_np(
520 struct iscsi_portal_group *tpg, 527 struct iscsi_portal_group *tpg,
521 struct iscsi_np *np) 528 struct iscsi_np *np)
522{ 529{
523 iscsit_clear_tpg_np_login_thread(tpg_np, tpg); 530 iscsit_clear_tpg_np_login_thread(tpg_np, tpg, true);
524 531
525 pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n", 532 pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n",
526 tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt, 533 tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt,
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
index dda48c141a8c..b77693e2c209 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.h
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -5,10 +5,10 @@ extern struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *,
5extern int iscsit_load_discovery_tpg(void); 5extern int iscsit_load_discovery_tpg(void);
6extern void iscsit_release_discovery_tpg(void); 6extern void iscsit_release_discovery_tpg(void);
7extern struct iscsi_portal_group *iscsit_get_tpg_from_np(struct iscsi_tiqn *, 7extern struct iscsi_portal_group *iscsit_get_tpg_from_np(struct iscsi_tiqn *,
8 struct iscsi_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 *); 11extern void iscsit_clear_tpg_np_login_threads(struct iscsi_portal_group *, bool);
12extern void iscsit_tpg_dump_params(struct iscsi_portal_group *); 12extern void iscsit_tpg_dump_params(struct iscsi_portal_group *);
13extern int iscsit_tpg_add_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *); 13extern 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 *, 14extern int iscsit_tpg_del_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *,
diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c
index 81289520f96b..601e9cc61e98 100644
--- a/drivers/target/iscsi/iscsi_target_tq.c
+++ b/drivers/target/iscsi/iscsi_target_tq.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains the iSCSI Login Thread and Thread Queue functions. 2 * This file contains the iSCSI Login Thread and Thread Queue functions.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -105,12 +103,11 @@ int iscsi_allocate_thread_sets(u32 thread_pair_count)
105 ts->status = ISCSI_THREAD_SET_FREE; 103 ts->status = ISCSI_THREAD_SET_FREE;
106 INIT_LIST_HEAD(&ts->ts_list); 104 INIT_LIST_HEAD(&ts->ts_list);
107 spin_lock_init(&ts->ts_state_lock); 105 spin_lock_init(&ts->ts_state_lock);
108 init_completion(&ts->rx_post_start_comp);
109 init_completion(&ts->tx_post_start_comp);
110 init_completion(&ts->rx_restart_comp); 106 init_completion(&ts->rx_restart_comp);
111 init_completion(&ts->tx_restart_comp); 107 init_completion(&ts->tx_restart_comp);
112 init_completion(&ts->rx_start_comp); 108 init_completion(&ts->rx_start_comp);
113 init_completion(&ts->tx_start_comp); 109 init_completion(&ts->tx_start_comp);
110 sema_init(&ts->ts_activate_sem, 0);
114 111
115 ts->create_threads = 1; 112 ts->create_threads = 1;
116 ts->tx_thread = kthread_run(iscsi_target_tx_thread, ts, "%s", 113 ts->tx_thread = kthread_run(iscsi_target_tx_thread, ts, "%s",
@@ -139,35 +136,44 @@ int iscsi_allocate_thread_sets(u32 thread_pair_count)
139 return allocated_thread_pair_count; 136 return allocated_thread_pair_count;
140} 137}
141 138
142void iscsi_deallocate_thread_sets(void) 139static void iscsi_deallocate_thread_one(struct iscsi_thread_set *ts)
143{ 140{
144 u32 released_count = 0; 141 spin_lock_bh(&ts->ts_state_lock);
145 struct iscsi_thread_set *ts = NULL; 142 ts->status = ISCSI_THREAD_SET_DIE;
146
147 while ((ts = iscsi_get_ts_from_inactive_list())) {
148 143
144 if (ts->rx_thread) {
145 complete(&ts->rx_start_comp);
146 spin_unlock_bh(&ts->ts_state_lock);
147 kthread_stop(ts->rx_thread);
149 spin_lock_bh(&ts->ts_state_lock); 148 spin_lock_bh(&ts->ts_state_lock);
150 ts->status = ISCSI_THREAD_SET_DIE; 149 }
150 if (ts->tx_thread) {
151 complete(&ts->tx_start_comp);
151 spin_unlock_bh(&ts->ts_state_lock); 152 spin_unlock_bh(&ts->ts_state_lock);
153 kthread_stop(ts->tx_thread);
154 spin_lock_bh(&ts->ts_state_lock);
155 }
156 spin_unlock_bh(&ts->ts_state_lock);
157 /*
158 * Release this thread_id in the thread_set_bitmap
159 */
160 spin_lock(&ts_bitmap_lock);
161 bitmap_release_region(iscsit_global->ts_bitmap,
162 ts->thread_id, get_order(1));
163 spin_unlock(&ts_bitmap_lock);
152 164
153 if (ts->rx_thread) { 165 kfree(ts);
154 send_sig(SIGINT, ts->rx_thread, 1); 166}
155 kthread_stop(ts->rx_thread);
156 }
157 if (ts->tx_thread) {
158 send_sig(SIGINT, ts->tx_thread, 1);
159 kthread_stop(ts->tx_thread);
160 }
161 /*
162 * Release this thread_id in the thread_set_bitmap
163 */
164 spin_lock(&ts_bitmap_lock);
165 bitmap_release_region(iscsit_global->ts_bitmap,
166 ts->thread_id, get_order(1));
167 spin_unlock(&ts_bitmap_lock);
168 167
168void iscsi_deallocate_thread_sets(void)
169{
170 struct iscsi_thread_set *ts = NULL;
171 u32 released_count = 0;
172
173 while ((ts = iscsi_get_ts_from_inactive_list())) {
174
175 iscsi_deallocate_thread_one(ts);
169 released_count++; 176 released_count++;
170 kfree(ts);
171 } 177 }
172 178
173 if (released_count) 179 if (released_count)
@@ -187,34 +193,13 @@ static void iscsi_deallocate_extra_thread_sets(void)
187 if (!ts) 193 if (!ts)
188 break; 194 break;
189 195
190 spin_lock_bh(&ts->ts_state_lock); 196 iscsi_deallocate_thread_one(ts);
191 ts->status = ISCSI_THREAD_SET_DIE;
192 spin_unlock_bh(&ts->ts_state_lock);
193
194 if (ts->rx_thread) {
195 send_sig(SIGINT, ts->rx_thread, 1);
196 kthread_stop(ts->rx_thread);
197 }
198 if (ts->tx_thread) {
199 send_sig(SIGINT, ts->tx_thread, 1);
200 kthread_stop(ts->tx_thread);
201 }
202 /*
203 * Release this thread_id in the thread_set_bitmap
204 */
205 spin_lock(&ts_bitmap_lock);
206 bitmap_release_region(iscsit_global->ts_bitmap,
207 ts->thread_id, get_order(1));
208 spin_unlock(&ts_bitmap_lock);
209
210 released_count++; 197 released_count++;
211 kfree(ts);
212 } 198 }
213 199
214 if (released_count) { 200 if (released_count)
215 pr_debug("Stopped %d thread set(s) (%d total threads)." 201 pr_debug("Stopped %d thread set(s) (%d total threads)."
216 "\n", released_count, released_count * 2); 202 "\n", released_count, released_count * 2);
217 }
218} 203}
219 204
220void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts) 205void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
@@ -224,37 +209,23 @@ void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set
224 spin_lock_bh(&ts->ts_state_lock); 209 spin_lock_bh(&ts->ts_state_lock);
225 conn->thread_set = ts; 210 conn->thread_set = ts;
226 ts->conn = conn; 211 ts->conn = conn;
212 ts->status = ISCSI_THREAD_SET_ACTIVE;
227 spin_unlock_bh(&ts->ts_state_lock); 213 spin_unlock_bh(&ts->ts_state_lock);
228 /* 214
229 * Start up the RX thread and wait on rx_post_start_comp. The RX
230 * Thread will then do the same for the TX Thread in
231 * iscsi_rx_thread_pre_handler().
232 */
233 complete(&ts->rx_start_comp); 215 complete(&ts->rx_start_comp);
234 wait_for_completion(&ts->rx_post_start_comp); 216 complete(&ts->tx_start_comp);
217
218 down(&ts->ts_activate_sem);
235} 219}
236 220
237struct iscsi_thread_set *iscsi_get_thread_set(void) 221struct iscsi_thread_set *iscsi_get_thread_set(void)
238{ 222{
239 int allocate_ts = 0; 223 struct iscsi_thread_set *ts;
240 struct completion comp; 224
241 struct iscsi_thread_set *ts = NULL;
242 /*
243 * If no inactive thread set is available on the first call to
244 * iscsi_get_ts_from_inactive_list(), sleep for a second and
245 * try again. If still none are available after two attempts,
246 * allocate a set ourselves.
247 */
248get_set: 225get_set:
249 ts = iscsi_get_ts_from_inactive_list(); 226 ts = iscsi_get_ts_from_inactive_list();
250 if (!ts) { 227 if (!ts) {
251 if (allocate_ts == 2) 228 iscsi_allocate_thread_sets(1);
252 iscsi_allocate_thread_sets(1);
253
254 init_completion(&comp);
255 wait_for_completion_timeout(&comp, 1 * HZ);
256
257 allocate_ts++;
258 goto get_set; 229 goto get_set;
259 } 230 }
260 231
@@ -263,6 +234,7 @@ get_set:
263 ts->thread_count = 2; 234 ts->thread_count = 2;
264 init_completion(&ts->rx_restart_comp); 235 init_completion(&ts->rx_restart_comp);
265 init_completion(&ts->tx_restart_comp); 236 init_completion(&ts->tx_restart_comp);
237 sema_init(&ts->ts_activate_sem, 0);
266 238
267 return ts; 239 return ts;
268} 240}
@@ -400,7 +372,8 @@ static void iscsi_check_to_add_additional_sets(void)
400static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts) 372static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts)
401{ 373{
402 spin_lock_bh(&ts->ts_state_lock); 374 spin_lock_bh(&ts->ts_state_lock);
403 if ((ts->status == ISCSI_THREAD_SET_DIE) || signal_pending(current)) { 375 if (ts->status == ISCSI_THREAD_SET_DIE || kthread_should_stop() ||
376 signal_pending(current)) {
404 spin_unlock_bh(&ts->ts_state_lock); 377 spin_unlock_bh(&ts->ts_state_lock);
405 return -1; 378 return -1;
406 } 379 }
@@ -419,7 +392,8 @@ struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
419 goto sleep; 392 goto sleep;
420 } 393 }
421 394
422 flush_signals(current); 395 if (ts->status != ISCSI_THREAD_SET_DIE)
396 flush_signals(current);
423 397
424 if (ts->delay_inactive && (--ts->thread_count == 0)) { 398 if (ts->delay_inactive && (--ts->thread_count == 0)) {
425 spin_unlock_bh(&ts->ts_state_lock); 399 spin_unlock_bh(&ts->ts_state_lock);
@@ -446,18 +420,19 @@ sleep:
446 if (iscsi_signal_thread_pre_handler(ts) < 0) 420 if (iscsi_signal_thread_pre_handler(ts) < 0)
447 return NULL; 421 return NULL;
448 422
423 iscsi_check_to_add_additional_sets();
424
425 spin_lock_bh(&ts->ts_state_lock);
449 if (!ts->conn) { 426 if (!ts->conn) {
450 pr_err("struct iscsi_thread_set->conn is NULL for" 427 pr_err("struct iscsi_thread_set->conn is NULL for"
451 " thread_id: %d, going back to sleep\n", ts->thread_id); 428 " RX thread_id: %s/%d\n", current->comm, current->pid);
452 goto sleep; 429 spin_unlock_bh(&ts->ts_state_lock);
430 return NULL;
453 } 431 }
454 iscsi_check_to_add_additional_sets();
455 /*
456 * The RX Thread starts up the TX Thread and sleeps.
457 */
458 ts->thread_clear |= ISCSI_CLEAR_RX_THREAD; 432 ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
459 complete(&ts->tx_start_comp); 433 spin_unlock_bh(&ts->ts_state_lock);
460 wait_for_completion(&ts->tx_post_start_comp); 434
435 up(&ts->ts_activate_sem);
461 436
462 return ts->conn; 437 return ts->conn;
463} 438}
@@ -472,7 +447,8 @@ struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
472 goto sleep; 447 goto sleep;
473 } 448 }
474 449
475 flush_signals(current); 450 if (ts->status != ISCSI_THREAD_SET_DIE)
451 flush_signals(current);
476 452
477 if (ts->delay_inactive && (--ts->thread_count == 0)) { 453 if (ts->delay_inactive && (--ts->thread_count == 0)) {
478 spin_unlock_bh(&ts->ts_state_lock); 454 spin_unlock_bh(&ts->ts_state_lock);
@@ -498,27 +474,20 @@ sleep:
498 if (iscsi_signal_thread_pre_handler(ts) < 0) 474 if (iscsi_signal_thread_pre_handler(ts) < 0)
499 return NULL; 475 return NULL;
500 476
501 if (!ts->conn) {
502 pr_err("struct iscsi_thread_set->conn is NULL for "
503 " thread_id: %d, going back to sleep\n",
504 ts->thread_id);
505 goto sleep;
506 }
507
508 iscsi_check_to_add_additional_sets(); 477 iscsi_check_to_add_additional_sets();
509 /*
510 * From the TX thread, up the tx_post_start_comp that the RX Thread is
511 * sleeping on in iscsi_rx_thread_pre_handler(), then up the
512 * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
513 */
514 ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
515 complete(&ts->tx_post_start_comp);
516 complete(&ts->rx_post_start_comp);
517 478
518 spin_lock_bh(&ts->ts_state_lock); 479 spin_lock_bh(&ts->ts_state_lock);
519 ts->status = ISCSI_THREAD_SET_ACTIVE; 480 if (!ts->conn) {
481 pr_err("struct iscsi_thread_set->conn is NULL for"
482 " TX thread_id: %s/%d\n", current->comm, current->pid);
483 spin_unlock_bh(&ts->ts_state_lock);
484 return NULL;
485 }
486 ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
520 spin_unlock_bh(&ts->ts_state_lock); 487 spin_unlock_bh(&ts->ts_state_lock);
521 488
489 up(&ts->ts_activate_sem);
490
522 return ts->conn; 491 return ts->conn;
523} 492}
524 493
diff --git a/drivers/target/iscsi/iscsi_target_tq.h b/drivers/target/iscsi/iscsi_target_tq.h
index 547d11831282..cc1eede5ab3a 100644
--- a/drivers/target/iscsi/iscsi_target_tq.h
+++ b/drivers/target/iscsi/iscsi_target_tq.h
@@ -64,10 +64,6 @@ struct iscsi_thread_set {
64 struct iscsi_conn *conn; 64 struct iscsi_conn *conn;
65 /* used for controlling ts state accesses */ 65 /* used for controlling ts state accesses */
66 spinlock_t ts_state_lock; 66 spinlock_t ts_state_lock;
67 /* Used for rx side post startup */
68 struct completion rx_post_start_comp;
69 /* Used for tx side post startup */
70 struct completion tx_post_start_comp;
71 /* used for restarting thread queue */ 67 /* used for restarting thread queue */
72 struct completion rx_restart_comp; 68 struct completion rx_restart_comp;
73 /* used for restarting thread queue */ 69 /* used for restarting thread queue */
@@ -82,6 +78,7 @@ struct iscsi_thread_set {
82 struct task_struct *tx_thread; 78 struct task_struct *tx_thread;
83 /* struct iscsi_thread_set in list list head*/ 79 /* struct iscsi_thread_set in list list head*/
84 struct list_head ts_list; 80 struct list_head ts_list;
81 struct semaphore ts_activate_sem;
85}; 82};
86 83
87#endif /*** ISCSI_THREAD_QUEUE_H ***/ 84#endif /*** ISCSI_THREAD_QUEUE_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 1df06d5e4e01..f2de28e178fd 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1,9 +1,7 @@
1/******************************************************************************* 1/*******************************************************************************
2 * This file contains the iSCSI Target specific utility functions. 2 * This file contains the iSCSI Target specific utility functions.
3 * 3 *
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 4 * (c) Copyright 2007-2013 Datera, Inc.
5 *
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7 * 5 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 * 7 *
@@ -19,6 +17,7 @@
19 ******************************************************************************/ 17 ******************************************************************************/
20 18
21#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/percpu_ida.h>
22#include <scsi/scsi_tcq.h> 21#include <scsi/scsi_tcq.h>
23#include <scsi/iscsi_proto.h> 22#include <scsi/iscsi_proto.h>
24#include <target/target_core_base.h> 23#include <target/target_core_base.h>
@@ -149,18 +148,6 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd)
149 spin_unlock_bh(&cmd->r2t_lock); 148 spin_unlock_bh(&cmd->r2t_lock);
150} 149}
151 150
152struct iscsi_cmd *iscsit_alloc_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
153{
154 struct iscsi_cmd *cmd;
155
156 cmd = kmem_cache_zalloc(lio_cmd_cache, gfp_mask);
157 if (!cmd)
158 return NULL;
159
160 cmd->release_cmd = &iscsit_release_cmd;
161 return cmd;
162}
163
164/* 151/*
165 * May be called from software interrupt (timer) context for allocating 152 * May be called from software interrupt (timer) context for allocating
166 * iSCSI NopINs. 153 * iSCSI NopINs.
@@ -168,12 +155,15 @@ struct iscsi_cmd *iscsit_alloc_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
168struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) 155struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
169{ 156{
170 struct iscsi_cmd *cmd; 157 struct iscsi_cmd *cmd;
158 struct se_session *se_sess = conn->sess->se_sess;
159 int size, tag;
171 160
172 cmd = conn->conn_transport->iscsit_alloc_cmd(conn, gfp_mask); 161 tag = percpu_ida_alloc(&se_sess->sess_tag_pool, gfp_mask);
173 if (!cmd) { 162 size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
174 pr_err("Unable to allocate memory for struct iscsi_cmd.\n"); 163 cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size));
175 return NULL; 164 memset(cmd, 0, size);
176 } 165
166 cmd->se_cmd.map_tag = tag;
177 cmd->conn = conn; 167 cmd->conn = conn;
178 INIT_LIST_HEAD(&cmd->i_conn_node); 168 INIT_LIST_HEAD(&cmd->i_conn_node);
179 INIT_LIST_HEAD(&cmd->datain_list); 169 INIT_LIST_HEAD(&cmd->datain_list);
@@ -689,6 +679,16 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
689 679
690void iscsit_release_cmd(struct iscsi_cmd *cmd) 680void iscsit_release_cmd(struct iscsi_cmd *cmd)
691{ 681{
682 struct iscsi_session *sess;
683 struct se_cmd *se_cmd = &cmd->se_cmd;
684
685 if (cmd->conn)
686 sess = cmd->conn->sess;
687 else
688 sess = cmd->sess;
689
690 BUG_ON(!sess || !sess->se_sess);
691
692 kfree(cmd->buf_ptr); 692 kfree(cmd->buf_ptr);
693 kfree(cmd->pdu_list); 693 kfree(cmd->pdu_list);
694 kfree(cmd->seq_list); 694 kfree(cmd->seq_list);
@@ -696,8 +696,9 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
696 kfree(cmd->iov_data); 696 kfree(cmd->iov_data);
697 kfree(cmd->text_in_ptr); 697 kfree(cmd->text_in_ptr);
698 698
699 kmem_cache_free(lio_cmd_cache, cmd); 699 percpu_ida_free(&sess->se_sess->sess_tag_pool, se_cmd->map_tag);
700} 700}
701EXPORT_SYMBOL(iscsit_release_cmd);
701 702
702static void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd, 703static void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd,
703 bool check_queues) 704 bool check_queues)
@@ -761,7 +762,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
761 /* Fall-through */ 762 /* Fall-through */
762 default: 763 default:
763 __iscsit_free_cmd(cmd, false, shutdown); 764 __iscsit_free_cmd(cmd, false, shutdown);
764 cmd->release_cmd(cmd); 765 iscsit_release_cmd(cmd);
765 break; 766 break;
766 } 767 }
767} 768}