diff options
Diffstat (limited to 'drivers/target/iscsi/iscsi_target_login.c')
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 284 |
1 files changed, 88 insertions, 196 deletions
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index ae3209efd0e0..53aca059dc16 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /******************************************************************************* * This file contains the login functions used by the iSCSI Target driver. * @@ -5,24 +6,15 @@ * * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. ******************************************************************************/ -#include <crypto/hash.h> #include <linux/module.h> #include <linux/string.h> #include <linux/kthread.h> #include <linux/sched/signal.h> #include <linux/idr.h> #include <linux/tcp.h> /* TCP_NODELAY */ +#include <net/ip.h> #include <net/ipv6.h> /* ipv6_addr_v4mapped() */ #include <scsi/iscsi_proto.h> #include <target/target_core_base.h> @@ -42,7 +34,7 @@ #include <target/iscsi/iscsi_transport.h> -static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn) +static struct iscsi_login *iscsi_login_init_conn(struct iscsit_conn *conn) { struct iscsi_login *login; @@ -78,48 +70,8 @@ out_login: return NULL; } -/* - * Used by iscsi_target_nego.c:iscsi_target_locate_portal() to setup - * per struct iscsi_conn libcrypto contexts for crc32c and crc32-intel - */ -int iscsi_login_setup_crypto(struct iscsi_conn *conn) -{ - struct crypto_ahash *tfm; - - /* - * Setup slicing by CRC32C algorithm for RX and TX libcrypto contexts - * which will default to crc32c_intel.ko for cpu_has_xmm4_2, or fallback - * to software 1x8 byte slicing from crc32c.ko - */ - tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - pr_err("crypto_alloc_ahash() failed\n"); - return -ENOMEM; - } - - conn->conn_rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); - if (!conn->conn_rx_hash) { - pr_err("ahash_request_alloc() failed for conn_rx_hash\n"); - crypto_free_ahash(tfm); - return -ENOMEM; - } - ahash_request_set_callback(conn->conn_rx_hash, 0, NULL, NULL); - - conn->conn_tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); - if (!conn->conn_tx_hash) { - pr_err("ahash_request_alloc() failed for conn_tx_hash\n"); - ahash_request_free(conn->conn_rx_hash); - conn->conn_rx_hash = NULL; - crypto_free_ahash(tfm); - return -ENOMEM; - } - ahash_request_set_callback(conn->conn_tx_hash, 0, NULL, NULL); - - return 0; -} - static int iscsi_login_check_initiator_version( - struct iscsi_conn *conn, + struct iscsit_conn *conn, u8 version_max, u8 version_min) { @@ -135,12 +87,12 @@ static int iscsi_login_check_initiator_version( return 0; } -int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) +int iscsi_check_for_session_reinstatement(struct iscsit_conn *conn) { int sessiontype; struct iscsi_param *initiatorname_param = NULL, *sessiontype_param = NULL; struct iscsi_portal_group *tpg = conn->tpg; - struct iscsi_session *sess = NULL, *sess_p = NULL; + struct iscsit_session *sess = NULL, *sess_p = NULL; struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; struct se_session *se_sess, *se_sess_tmp; @@ -164,6 +116,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) spin_lock(&sess_p->conn_lock); if (atomic_read(&sess_p->session_fall_back_to_erl0) || atomic_read(&sess_p->session_logout) || + atomic_read(&sess_p->session_close) || (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED)) { spin_unlock(&sess_p->conn_lock); continue; @@ -174,6 +127,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) (sess_p->sess_ops->SessionType == sessiontype))) { atomic_set(&sess_p->session_reinstatement, 1); atomic_set(&sess_p->session_fall_back_to_erl0, 1); + atomic_set(&sess_p->session_close, 1); spin_unlock(&sess_p->conn_lock); iscsit_inc_session_usage_count(sess_p); iscsit_stop_time2retain_timer(sess_p); @@ -198,7 +152,6 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) if (sess->session_state == TARG_SESS_STATE_FAILED) { spin_unlock_bh(&sess->conn_lock); iscsit_dec_session_usage_count(sess); - iscsit_close_session(sess); return 0; } spin_unlock_bh(&sess->conn_lock); @@ -206,13 +159,12 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) iscsit_stop_session(sess, 1, 1); iscsit_dec_session_usage_count(sess); - iscsit_close_session(sess); return 0; } static int iscsi_login_set_conn_values( - struct iscsi_session *sess, - struct iscsi_conn *conn, + struct iscsit_session *sess, + struct iscsit_conn *conn, __be16 cid) { int ret; @@ -233,7 +185,7 @@ static int iscsi_login_set_conn_values( } __printf(2, 3) int iscsi_change_param_sprintf( - struct iscsi_conn *conn, + struct iscsit_conn *conn, const char *fmt, ...) { va_list args; @@ -260,14 +212,14 @@ EXPORT_SYMBOL(iscsi_change_param_sprintf); * or session reinstatement. */ static int iscsi_login_zero_tsih_s1( - struct iscsi_conn *conn, + struct iscsit_conn *conn, unsigned char *buf) { - struct iscsi_session *sess = NULL; + struct iscsit_session *sess = NULL; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; int ret; - sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); + sess = kzalloc(sizeof(struct iscsit_session), GFP_KERNEL); if (!sess) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); @@ -344,10 +296,11 @@ free_sess: } static int iscsi_login_zero_tsih_s2( - struct iscsi_conn *conn) + struct iscsit_conn *conn) { struct iscsi_node_attrib *na; - struct iscsi_session *sess = conn->sess; + struct iscsit_session *sess = conn->sess; + struct iscsi_param *param; bool iser = false; sess->tpg = conn->tpg; @@ -382,6 +335,18 @@ static int iscsi_login_zero_tsih_s2( na = iscsit_tpg_get_node_attrib(sess); /* + * If ACL allows non-authorized access in TPG with CHAP, + * then set None to AuthMethod. + */ + param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); + if (param && !strstr(param->value, NONE)) { + if (!iscsi_conn_auth_required(conn)) + if (iscsi_change_param_sprintf(conn, "AuthMethod=%s", + NONE)) + return -1; + } + + /* * Need to send TargetPortalGroupTag back in first login response * on any iSCSI connection where the Initiator provides TargetName. * See 5.3.1. Login Phase Start @@ -465,7 +430,7 @@ check_prot: } static int iscsi_login_non_zero_tsih_s1( - struct iscsi_conn *conn, + struct iscsit_conn *conn, unsigned char *buf) { struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; @@ -477,11 +442,11 @@ static int iscsi_login_non_zero_tsih_s1( * Add a new connection to an existing session. */ static int iscsi_login_non_zero_tsih_s2( - struct iscsi_conn *conn, + struct iscsit_conn *conn, unsigned char *buf) { struct iscsi_portal_group *tpg = conn->tpg; - struct iscsi_session *sess = NULL, *sess_p = NULL; + struct iscsit_session *sess = NULL, *sess_p = NULL; struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; struct se_session *se_sess, *se_sess_tmp; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; @@ -491,9 +456,10 @@ static int iscsi_login_non_zero_tsih_s2( list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list, sess_list) { - sess_p = (struct iscsi_session *)se_sess->fabric_sess_ptr; + sess_p = (struct iscsit_session *)se_sess->fabric_sess_ptr; if (atomic_read(&sess_p->session_fall_back_to_erl0) || atomic_read(&sess_p->session_logout) || + atomic_read(&sess_p->session_close) || (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED)) continue; if (!memcmp(sess_p->isid, pdu->isid, 6) && @@ -552,13 +518,13 @@ static int iscsi_login_non_zero_tsih_s2( } int iscsi_login_post_auth_non_zero_tsih( - struct iscsi_conn *conn, + struct iscsit_conn *conn, u16 cid, u32 exp_statsn) { - struct iscsi_conn *conn_ptr = NULL; + struct iscsit_conn *conn_ptr = NULL; struct iscsi_conn_recovery *cr = NULL; - struct iscsi_session *sess = conn->sess; + struct iscsit_session *sess = conn->sess; /* * By following item 5 in the login table, if we have found @@ -618,9 +584,9 @@ int iscsi_login_post_auth_non_zero_tsih( return 0; } -static void iscsi_post_login_start_timers(struct iscsi_conn *conn) +static void iscsi_post_login_start_timers(struct iscsit_conn *conn) { - struct iscsi_session *sess = conn->sess; + struct iscsit_session *sess = conn->sess; /* * FIXME: Unsolicited NopIN support for ISER */ @@ -631,7 +597,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) iscsit_start_nopin_timer(conn); } -int iscsit_start_kthreads(struct iscsi_conn *conn) +int iscsit_start_kthreads(struct iscsit_conn *conn) { int ret = 0; @@ -679,11 +645,11 @@ out_bitmap: void iscsi_post_login_handler( struct iscsi_np *np, - struct iscsi_conn *conn, + struct iscsit_conn *conn, u8 zero_tsih) { int stop_timer = 0; - struct iscsi_session *sess = conn->sess; + struct iscsit_session *sess = conn->sess; struct se_session *se_sess = sess->se_sess; struct iscsi_portal_group *tpg = sess->tpg; struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; @@ -721,7 +687,7 @@ void iscsi_post_login_handler( list_add_tail(&conn->conn_list, &sess->sess_conn_list); atomic_inc(&sess->nconn); - pr_debug("Incremented iSCSI Connection count to %hu" + pr_debug("Incremented iSCSI Connection count to %d" " from node: %s\n", atomic_read(&sess->nconn), sess->sess_ops->InitiatorName); spin_unlock_bh(&sess->conn_lock); @@ -736,7 +702,7 @@ void iscsi_post_login_handler( conn->conn_tx_reset_cpumask = 1; /* * Wakeup the sleeping iscsi_target_rx_thread() now that - * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. + * iscsit_conn is in TARG_CONN_STATE_LOGGED_IN state. */ complete(&conn->rx_login_comp); iscsit_dec_conn_usage_count(conn); @@ -769,7 +735,7 @@ void iscsi_post_login_handler( spin_lock_bh(&sess->conn_lock); list_add_tail(&conn->conn_list, &sess->sess_conn_list); atomic_inc(&sess->nconn); - pr_debug("Incremented iSCSI Connection count to %hu from node:" + pr_debug("Incremented iSCSI Connection count to %d from node:" " %s\n", atomic_read(&sess->nconn), sess->sess_ops->InitiatorName); spin_unlock_bh(&sess->conn_lock); @@ -798,71 +764,18 @@ void iscsi_post_login_handler( conn->conn_tx_reset_cpumask = 1; /* * Wakeup the sleeping iscsi_target_rx_thread() now that - * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. + * iscsit_conn is in TARG_CONN_STATE_LOGGED_IN state. */ complete(&conn->rx_login_comp); iscsit_dec_conn_usage_count(conn); } -void iscsi_handle_login_thread_timeout(struct timer_list *t) -{ - struct iscsi_np *np = from_timer(np, t, np_login_timer); - - spin_lock_bh(&np->np_thread_lock); - pr_err("iSCSI Login timeout on Network Portal %pISpc\n", - &np->np_sockaddr); - - if (np->np_login_timer_flags & ISCSI_TF_STOP) { - spin_unlock_bh(&np->np_thread_lock); - return; - } - - if (np->np_thread) - send_sig(SIGINT, np->np_thread, 1); - - np->np_login_timer_flags &= ~ISCSI_TF_RUNNING; - spin_unlock_bh(&np->np_thread_lock); -} - -static void iscsi_start_login_thread_timer(struct iscsi_np *np) -{ - /* - * This used the TA_LOGIN_TIMEOUT constant because at this - * point we do not have access to ISCSI_TPG_ATTRIB(tpg)->login_timeout - */ - spin_lock_bh(&np->np_thread_lock); - np->np_login_timer_flags &= ~ISCSI_TF_STOP; - np->np_login_timer_flags |= ISCSI_TF_RUNNING; - mod_timer(&np->np_login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ); - - pr_debug("Added timeout timer to iSCSI login request for" - " %u seconds.\n", TA_LOGIN_TIMEOUT); - spin_unlock_bh(&np->np_thread_lock); -} - -static void iscsi_stop_login_thread_timer(struct iscsi_np *np) -{ - spin_lock_bh(&np->np_thread_lock); - if (!(np->np_login_timer_flags & ISCSI_TF_RUNNING)) { - spin_unlock_bh(&np->np_thread_lock); - return; - } - np->np_login_timer_flags |= ISCSI_TF_STOP; - spin_unlock_bh(&np->np_thread_lock); - - del_timer_sync(&np->np_login_timer); - - spin_lock_bh(&np->np_thread_lock); - np->np_login_timer_flags &= ~ISCSI_TF_RUNNING; - spin_unlock_bh(&np->np_thread_lock); -} - int iscsit_setup_np( struct iscsi_np *np, struct sockaddr_storage *sockaddr) { struct socket *sock = NULL; - int backlog = ISCSIT_TCP_BACKLOG, ret, opt = 0, len; + int backlog = ISCSIT_TCP_BACKLOG, ret, len; switch (np->np_network_transport) { case ISCSI_TCP: @@ -883,9 +796,6 @@ int iscsit_setup_np( return -EINVAL; } - np->np_ip_proto = IPPROTO_TCP; - np->np_sock_type = SOCK_STREAM; - ret = sock_create(sockaddr->ss_family, np->np_sock_type, np->np_ip_proto, &sock); if (ret < 0) { @@ -905,38 +815,14 @@ int iscsit_setup_np( else len = sizeof(struct sockaddr_in); /* - * Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY. + * Set SO_REUSEADDR, and disable Nagle Algorithm with TCP_NODELAY. */ - /* FIXME: Someone please explain why this is endian-safe */ - opt = 1; - if (np->np_network_transport == ISCSI_TCP) { - ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (char *)&opt, sizeof(opt)); - if (ret < 0) { - pr_err("kernel_setsockopt() for TCP_NODELAY" - " failed: %d\n", ret); - goto fail; - } - } - - /* FIXME: Someone please explain why this is endian-safe */ - ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char *)&opt, sizeof(opt)); - if (ret < 0) { - pr_err("kernel_setsockopt() for SO_REUSEADDR" - " failed\n"); - goto fail; - } - - ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND, - (char *)&opt, sizeof(opt)); - if (ret < 0) { - pr_err("kernel_setsockopt() for IP_FREEBIND" - " failed\n"); - goto fail; - } + if (np->np_network_transport == ISCSI_TCP) + tcp_sock_set_nodelay(sock->sk); + sock_set_reuseaddr(sock->sk); + ip_sock_set_freebind(sock->sk); - ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len); + ret = kernel_bind(sock, (struct sockaddr_unsized *)&np->np_sockaddr, len); if (ret < 0) { pr_err("kernel_bind() failed: %d\n", ret); goto fail; @@ -977,7 +863,7 @@ int iscsi_target_setup_login_socket( return 0; } -int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) +int iscsit_accept_np(struct iscsi_np *np, struct iscsit_conn *conn) { struct socket *new_sock, *sock = np->np_socket; struct sockaddr_in sock_in; @@ -1038,7 +924,7 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) return 0; } -int iscsit_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) +int iscsit_get_login_rx(struct iscsit_conn *conn, struct iscsi_login *login) { struct iscsi_login_req *login_req; u32 padding = 0, payload_length; @@ -1083,7 +969,7 @@ int iscsit_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) return 0; } -int iscsit_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, +int iscsit_put_login_tx(struct iscsit_conn *conn, struct iscsi_login *login, u32 length) { if (iscsi_login_tx_data(conn, login->rsp, login->rsp_buf, length) < 0) @@ -1093,7 +979,7 @@ int iscsit_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, } static int -iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t) +iscsit_conn_set_transport(struct iscsit_conn *conn, struct iscsit_transport *t) { int rc; @@ -1112,11 +998,11 @@ iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t) return 0; } -static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np) +static struct iscsit_conn *iscsit_alloc_conn(struct iscsi_np *np) { - struct iscsi_conn *conn; + struct iscsit_conn *conn; - conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); + conn = kzalloc(sizeof(struct iscsit_conn), GFP_KERNEL); if (!conn) { pr_err("Could not allocate memory for new connection\n"); return NULL; @@ -1143,10 +1029,13 @@ static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np) spin_lock_init(&conn->nopin_timer_lock); spin_lock_init(&conn->response_queue_lock); spin_lock_init(&conn->state_lock); + spin_lock_init(&conn->login_worker_lock); + spin_lock_init(&conn->login_timer_lock); timer_setup(&conn->nopin_response_timer, iscsit_handle_nopin_response_timeout, 0); timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0); + timer_setup(&conn->login_timer, iscsit_login_timeout, 0); if (iscsit_conn_set_transport(conn, np->np_transport) < 0) goto free_conn; @@ -1159,13 +1048,26 @@ static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np) if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) { pr_err("Unable to allocate conn->conn_cpumask\n"); - goto free_mask; + goto free_conn_ops; + } + + if (!zalloc_cpumask_var(&conn->allowed_cpumask, GFP_KERNEL)) { + pr_err("Unable to allocate conn->allowed_cpumask\n"); + goto free_conn_cpumask; } + conn->cmd_cnt = target_alloc_cmd_counter(); + if (!conn->cmd_cnt) + goto free_conn_allowed_cpumask; + return conn; -free_mask: +free_conn_allowed_cpumask: + free_cpumask_var(conn->allowed_cpumask); +free_conn_cpumask: free_cpumask_var(conn->conn_cpumask); +free_conn_ops: + kfree(conn->conn_ops); put_transport: iscsit_put_transport(conn->conn_transport); free_conn: @@ -1173,16 +1075,18 @@ free_conn: return NULL; } -void iscsit_free_conn(struct iscsi_conn *conn) +void iscsit_free_conn(struct iscsit_conn *conn) { + target_free_cmd_counter(conn->cmd_cnt); + free_cpumask_var(conn->allowed_cpumask); free_cpumask_var(conn->conn_cpumask); kfree(conn->conn_ops); iscsit_put_transport(conn->conn_transport); kfree(conn); } -void iscsi_target_login_sess_out(struct iscsi_conn *conn, - struct iscsi_np *np, bool zero_tsih, bool new_sess) +void iscsi_target_login_sess_out(struct iscsit_conn *conn, + bool zero_tsih, bool new_sess) { if (!new_sess) goto old_sess_out; @@ -1200,7 +1104,6 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn, conn->sess = NULL; old_sess_out: - iscsi_stop_login_thread_timer(np); /* * If login negotiation fails check if the Time2Retain timer * needs to be restarted. @@ -1221,15 +1124,6 @@ old_sess_out: iscsit_dec_session_usage_count(conn->sess); } - ahash_request_free(conn->conn_tx_hash); - if (conn->conn_rx_hash) { - struct crypto_ahash *tfm; - - tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); - ahash_request_free(conn->conn_rx_hash); - crypto_free_ahash(tfm); - } - if (conn->param_list) { iscsi_release_param_list(conn->param_list); conn->param_list = NULL; @@ -1254,7 +1148,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) { u8 *buffer, zero_tsih = 0; int ret = 0, rc; - struct iscsi_conn *conn = NULL; + struct iscsit_conn *conn = NULL; struct iscsi_login *login; struct iscsi_portal_group *tpg = NULL; struct iscsi_login_req *pdu; @@ -1310,7 +1204,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) goto new_sess_out; } - iscsi_start_login_thread_timer(np); + iscsit_start_login_timer(conn, current); pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n"); conn->conn_state = TARG_CONN_STATE_XPT_UP; @@ -1397,7 +1291,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) tpg = conn->tpg; if (!tpg) { - pr_err("Unable to locate struct iscsi_conn->tpg\n"); + pr_err("Unable to locate struct iscsit_conn->tpg\n"); goto new_sess_out; } @@ -1423,8 +1317,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) if (ret < 0) goto new_sess_out; - iscsi_stop_login_thread_timer(np); - if (ret == 1) { tpg_np = conn->tpg_np; @@ -1440,8 +1332,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) new_sess_out: new_sess = true; old_sess_out: + iscsit_stop_login_timer(conn); tpg_np = conn->tpg_np; - iscsi_target_login_sess_out(conn, np, zero_tsih, new_sess); + iscsi_target_login_sess_out(conn, zero_tsih, new_sess); new_sess = false; if (tpg) { @@ -1453,7 +1346,6 @@ old_sess_out: return 1; exit: - iscsi_stop_login_thread_timer(np); spin_lock_bh(&np->np_thread_lock); np->np_thread_state = ISCSI_NP_THREAD_EXIT; spin_unlock_bh(&np->np_thread_lock); |
