@@ -535,25 +535,6 @@ static void iscsi_target_login_drop(struct iscsit_conn *conn, struct iscsi_login
535535 iscsi_target_login_sess_out (conn , zero_tsih , true);
536536}
537537
538- struct conn_timeout {
539- struct timer_list timer ;
540- struct iscsit_conn * conn ;
541- };
542-
543- static void iscsi_target_login_timeout (struct timer_list * t )
544- {
545- struct conn_timeout * timeout = from_timer (timeout , t , timer );
546- struct iscsit_conn * conn = timeout -> conn ;
547-
548- pr_debug ("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n" );
549-
550- if (conn -> login_kworker ) {
551- pr_debug ("Sending SIGINT to conn->login_kworker %s/%d\n" ,
552- conn -> login_kworker -> comm , conn -> login_kworker -> pid );
553- send_sig (SIGINT , conn -> login_kworker , 1 );
554- }
555- }
556-
557538static void iscsi_target_do_login_rx (struct work_struct * work )
558539{
559540 struct iscsit_conn * conn = container_of (work ,
@@ -562,12 +543,15 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
562543 struct iscsi_np * np = login -> np ;
563544 struct iscsi_portal_group * tpg = conn -> tpg ;
564545 struct iscsi_tpg_np * tpg_np = conn -> tpg_np ;
565- struct conn_timeout timeout ;
566546 int rc , zero_tsih = login -> zero_tsih ;
567547 bool state ;
568548
569549 pr_debug ("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n" ,
570550 conn , current -> comm , current -> pid );
551+
552+ spin_lock (& conn -> login_worker_lock );
553+ set_bit (LOGIN_FLAGS_WORKER_RUNNING , & conn -> login_flags );
554+ spin_unlock (& conn -> login_worker_lock );
571555 /*
572556 * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready()
573557 * before initial PDU processing in iscsi_target_start_negotiation()
@@ -597,19 +581,16 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
597581 goto err ;
598582 }
599583
600- conn -> login_kworker = current ;
601584 allow_signal (SIGINT );
602-
603- timeout .conn = conn ;
604- timer_setup_on_stack (& timeout .timer , iscsi_target_login_timeout , 0 );
605- mod_timer (& timeout .timer , jiffies + TA_LOGIN_TIMEOUT * HZ );
606- pr_debug ("Starting login timer for %s/%d\n" , current -> comm , current -> pid );
585+ rc = iscsit_set_login_timer_kworker (conn , current );
586+ if (rc < 0 ) {
587+ /* The login timer has already expired */
588+ pr_debug ("iscsi_target_do_login_rx, login failed\n" );
589+ goto err ;
590+ }
607591
608592 rc = conn -> conn_transport -> iscsit_get_login_rx (conn , login );
609- del_timer_sync (& timeout .timer );
610- destroy_timer_on_stack (& timeout .timer );
611593 flush_signals (current );
612- conn -> login_kworker = NULL ;
613594
614595 if (rc < 0 )
615596 goto err ;
@@ -646,7 +627,17 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
646627 if (iscsi_target_sk_check_and_clear (conn ,
647628 LOGIN_FLAGS_WRITE_ACTIVE ))
648629 goto err ;
630+
631+ /*
632+ * Set the login timer thread pointer to NULL to prevent the
633+ * login process from getting stuck if the initiator
634+ * stops sending data.
635+ */
636+ rc = iscsit_set_login_timer_kworker (conn , NULL );
637+ if (rc < 0 )
638+ goto err ;
649639 } else if (rc == 1 ) {
640+ iscsit_stop_login_timer (conn );
650641 cancel_delayed_work (& conn -> login_work );
651642 iscsi_target_nego_release (conn );
652643 iscsi_post_login_handler (np , conn , zero_tsih );
@@ -656,6 +647,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
656647
657648err :
658649 iscsi_target_restore_sock_callbacks (conn );
650+ iscsit_stop_login_timer (conn );
659651 cancel_delayed_work (& conn -> login_work );
660652 iscsi_target_login_drop (conn , login );
661653 iscsit_deaccess_np (np , tpg , tpg_np );
@@ -1130,6 +1122,7 @@ int iscsi_target_locate_portal(
11301122 iscsi_target_set_sock_callbacks (conn );
11311123
11321124 login -> np = np ;
1125+ conn -> tpg = NULL ;
11331126
11341127 login_req = (struct iscsi_login_req * ) login -> req ;
11351128 payload_length = ntoh24 (login_req -> dlength );
@@ -1197,7 +1190,6 @@ int iscsi_target_locate_portal(
11971190 */
11981191 sessiontype = strncmp (s_buf , DISCOVERY , 9 );
11991192 if (!sessiontype ) {
1200- conn -> tpg = iscsit_global -> discovery_tpg ;
12011193 if (!login -> leading_connection )
12021194 goto get_target ;
12031195
@@ -1214,9 +1206,11 @@ int iscsi_target_locate_portal(
12141206 * Serialize access across the discovery struct iscsi_portal_group to
12151207 * process login attempt.
12161208 */
1209+ conn -> tpg = iscsit_global -> discovery_tpg ;
12171210 if (iscsit_access_np (np , conn -> tpg ) < 0 ) {
12181211 iscsit_tx_login_rsp (conn , ISCSI_STATUS_CLS_TARGET_ERR ,
12191212 ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE );
1213+ conn -> tpg = NULL ;
12201214 ret = -1 ;
12211215 goto out ;
12221216 }
@@ -1368,14 +1362,30 @@ int iscsi_target_start_negotiation(
13681362 * and perform connection cleanup now.
13691363 */
13701364 ret = iscsi_target_do_login (conn , login );
1371- if (!ret && iscsi_target_sk_check_and_clear (conn , LOGIN_FLAGS_INITIAL_PDU ))
1372- ret = -1 ;
1365+ if (!ret ) {
1366+ spin_lock (& conn -> login_worker_lock );
1367+
1368+ if (iscsi_target_sk_check_and_clear (conn , LOGIN_FLAGS_INITIAL_PDU ))
1369+ ret = -1 ;
1370+ else if (!test_bit (LOGIN_FLAGS_WORKER_RUNNING , & conn -> login_flags )) {
1371+ if (iscsit_set_login_timer_kworker (conn , NULL ) < 0 ) {
1372+ /*
1373+ * The timeout has expired already.
1374+ * Schedule login_work to perform the cleanup.
1375+ */
1376+ schedule_delayed_work (& conn -> login_work , 0 );
1377+ }
1378+ }
1379+
1380+ spin_unlock (& conn -> login_worker_lock );
1381+ }
13731382
13741383 if (ret < 0 ) {
13751384 iscsi_target_restore_sock_callbacks (conn );
13761385 iscsi_remove_failed_auth_entry (conn );
13771386 }
13781387 if (ret != 0 ) {
1388+ iscsit_stop_login_timer (conn );
13791389 cancel_delayed_work_sync (& conn -> login_work );
13801390 iscsi_target_nego_release (conn );
13811391 }
0 commit comments