Skip to content

Commit d2c948e

Browse files
authored
DLPX-84985 target: iscsi: fix deadlock in the iSCSI login code (#22)
1 parent eaf115c commit d2c948e

File tree

5 files changed

+51
-32
lines changed

5 files changed

+51
-32
lines changed

drivers/target/iscsi/iscsi_target_login.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,7 @@ static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np)
11401140
timer_setup(&conn->nopin_response_timer,
11411141
iscsit_handle_nopin_response_timeout, 0);
11421142
timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
1143+
timer_setup(&conn->login_timer, iscsit_login_timeout, 0);
11431144

11441145
if (iscsit_conn_set_transport(conn, np->np_transport) < 0)
11451146
goto free_conn;

drivers/target/iscsi/iscsi_target_nego.c

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,18 @@ static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *);
479479

480480
static bool __iscsi_target_sk_check_close(struct sock *sk)
481481
{
482-
if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) {
483-
pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE,"
484-
"returning FALSE\n");
482+
switch (sk->sk_state) {
483+
case TCP_FIN_WAIT1:
484+
case TCP_FIN_WAIT2:
485+
case TCP_CLOSE_WAIT:
486+
case TCP_LAST_ACK:
487+
case TCP_CLOSE:
488+
pr_debug("__iscsi_target_sk_check_close: socket closing,"
489+
"returning TRUE\n");
485490
return true;
491+
default:
492+
return false;
486493
}
487-
return false;
488494
}
489495

490496
static bool iscsi_target_sk_check_close(struct iscsi_conn *conn)
@@ -542,25 +548,6 @@ static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login
542548
iscsi_target_login_sess_out(conn, zero_tsih, true);
543549
}
544550

545-
struct conn_timeout {
546-
struct timer_list timer;
547-
struct iscsi_conn *conn;
548-
};
549-
550-
static void iscsi_target_login_timeout(struct timer_list *t)
551-
{
552-
struct conn_timeout *timeout = from_timer(timeout, t, timer);
553-
struct iscsi_conn *conn = timeout->conn;
554-
555-
pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
556-
557-
if (conn->login_kworker) {
558-
pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
559-
conn->login_kworker->comm, conn->login_kworker->pid);
560-
send_sig(SIGINT, conn->login_kworker, 1);
561-
}
562-
}
563-
564551
static void iscsi_target_do_login_rx(struct work_struct *work)
565552
{
566553
struct iscsi_conn *conn = container_of(work,
@@ -569,7 +556,6 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
569556
struct iscsi_np *np = login->np;
570557
struct iscsi_portal_group *tpg = conn->tpg;
571558
struct iscsi_tpg_np *tpg_np = conn->tpg_np;
572-
struct conn_timeout timeout;
573559
int rc, zero_tsih = login->zero_tsih;
574560
bool state;
575561

@@ -607,14 +593,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
607593
conn->login_kworker = current;
608594
allow_signal(SIGINT);
609595

610-
timeout.conn = conn;
611-
timer_setup_on_stack(&timeout.timer, iscsi_target_login_timeout, 0);
612-
mod_timer(&timeout.timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
613-
pr_debug("Starting login timer for %s/%d\n", current->comm, current->pid);
614-
615596
rc = conn->conn_transport->iscsit_get_login_rx(conn, login);
616-
del_timer_sync(&timeout.timer);
617-
destroy_timer_on_stack(&timeout.timer);
618597
flush_signals(current);
619598
conn->login_kworker = NULL;
620599

@@ -631,6 +610,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
631610
if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE))
632611
goto err;
633612
} else if (rc == 1) {
613+
iscsit_stop_login_timer(conn);
634614
iscsi_target_nego_release(conn);
635615
iscsi_post_login_handler(np, conn, zero_tsih);
636616
iscsit_deaccess_np(np, tpg, tpg_np);
@@ -639,6 +619,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
639619

640620
err:
641621
iscsi_target_restore_sock_callbacks(conn);
622+
iscsit_stop_login_timer(conn);
642623
iscsi_target_login_drop(conn, login);
643624
iscsit_deaccess_np(np, tpg, tpg_np);
644625
}
@@ -1283,6 +1264,9 @@ int iscsi_target_start_negotiation(
12831264
set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags);
12841265
write_unlock_bh(&sk->sk_callback_lock);
12851266
}
1267+
1268+
iscsit_start_login_timer(conn);
1269+
12861270
/*
12871271
* If iscsi_target_do_login returns zero to signal more PDU
12881272
* exchanges are required to complete the login, go ahead and
@@ -1301,8 +1285,10 @@ int iscsi_target_start_negotiation(
13011285
iscsi_target_restore_sock_callbacks(conn);
13021286
iscsi_remove_failed_auth_entry(conn);
13031287
}
1304-
if (ret != 0)
1288+
if (ret != 0) {
1289+
iscsit_stop_login_timer(conn);
13051290
iscsi_target_nego_release(conn);
1291+
}
13061292

13071293
return ret;
13081294
}

drivers/target/iscsi/iscsi_target_util.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,34 @@ void iscsit_stop_nopin_timer(struct iscsi_conn *conn)
10561056
spin_unlock_bh(&conn->nopin_timer_lock);
10571057
}
10581058

1059+
void iscsit_login_timeout(struct timer_list *t)
1060+
{
1061+
struct iscsi_conn *conn = from_timer(conn, t, login_timer);
1062+
1063+
pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
1064+
1065+
if (conn->login_kworker) {
1066+
pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
1067+
conn->login_kworker->comm, conn->login_kworker->pid);
1068+
send_sig(SIGINT, conn->login_kworker, 1);
1069+
} else {
1070+
pr_debug("Shutting down the socket.\n");
1071+
kernel_sock_shutdown(conn->sock, SHUT_RDWR);
1072+
}
1073+
}
1074+
1075+
void iscsit_start_login_timer(struct iscsi_conn *conn)
1076+
{
1077+
pr_debug("Login timer started\n");
1078+
mod_timer(&conn->login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
1079+
}
1080+
1081+
void iscsit_stop_login_timer(struct iscsi_conn *conn)
1082+
{
1083+
pr_debug("Login timer stopped\n");
1084+
del_timer_sync(&conn->login_timer);
1085+
}
1086+
10591087
int iscsit_send_tx_data(
10601088
struct iscsi_cmd *cmd,
10611089
struct iscsi_conn *conn,

drivers/target/iscsi/iscsi_target_util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ extern void iscsit_handle_nopin_timeout(struct timer_list *t);
5656
extern void __iscsit_start_nopin_timer(struct iscsi_conn *);
5757
extern void iscsit_start_nopin_timer(struct iscsi_conn *);
5858
extern void iscsit_stop_nopin_timer(struct iscsi_conn *);
59+
extern void iscsit_login_timeout(struct timer_list *t);
60+
extern void iscsit_start_login_timer(struct iscsi_conn *);
61+
extern void iscsit_stop_login_timer(struct iscsi_conn *);
5962
extern int iscsit_send_tx_data(struct iscsi_cmd *, struct iscsi_conn *, int);
6063
extern int iscsit_fe_sendpage_sg(struct iscsi_cmd *, struct iscsi_conn *);
6164
extern int iscsit_tx_login_rsp(struct iscsi_conn *, u8, u8);

include/target/iscsi/iscsi_target_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ struct iscsi_conn {
577577
struct timer_list nopin_timer;
578578
struct timer_list nopin_response_timer;
579579
struct timer_list transport_timer;
580+
struct timer_list login_timer;
580581
struct task_struct *login_kworker;
581582
/* Spinlock used for add/deleting cmd's from conn_cmd_list */
582583
spinlock_t cmd_lock;

0 commit comments

Comments
 (0)