Skip to content

Commit e5282a7

Browse files
committed
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "Five fixes, all in drivers. The most extensive is the target change to fix the hang in the login code, which involves changing timers from per login to per connection" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: stex: Fix gcc 13 warnings scsi: qla2xxx: Fix NULL pointer dereference in target mode scsi: target: iscsi: Prevent login threads from racing between each other scsi: target: iscsi: Remove unused transport_timer scsi: target: iscsi: Fix hang in the iSCSI login code
2 parents d1b65ed + 6d074ce commit e5282a7

File tree

11 files changed

+120
-95
lines changed

11 files changed

+120
-95
lines changed

drivers/scsi/qla2xxx/qla_def.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3796,6 +3796,7 @@ struct qla_qpair {
37963796
uint64_t retry_term_jiff;
37973797
struct qla_tgt_counters tgt_counters;
37983798
uint16_t cpuid;
3799+
bool cpu_mapped;
37993800
struct qla_fw_resources fwres ____cacheline_aligned;
38003801
struct qla_buf_pool buf_pool;
38013802
u32 cmd_cnt;

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9426,6 +9426,9 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
94269426
qpair->rsp->req = qpair->req;
94279427
qpair->rsp->qpair = qpair;
94289428

9429+
if (!qpair->cpu_mapped)
9430+
qla_cpu_update(qpair, raw_smp_processor_id());
9431+
94299432
if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
94309433
if (ha->fw_attributes & BIT_4)
94319434
qpair->difdix_supported = 1;

drivers/scsi/qla2xxx/qla_inline.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,11 +539,14 @@ qla_mapq_init_qp_cpu_map(struct qla_hw_data *ha,
539539
if (!ha->qp_cpu_map)
540540
return;
541541
mask = pci_irq_get_affinity(ha->pdev, msix->vector_base0);
542+
if (!mask)
543+
return;
542544
qpair->cpuid = cpumask_first(mask);
543545
for_each_cpu(cpu, mask) {
544546
ha->qp_cpu_map[cpu] = qpair;
545547
}
546548
msix->cpuid = qpair->cpuid;
549+
qpair->cpu_mapped = true;
547550
}
548551

549552
static inline void

drivers/scsi/qla2xxx/qla_isr.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3770,6 +3770,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
37703770

37713771
if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) {
37723772
rsp->qpair->rcv_intr = 1;
3773+
3774+
if (!rsp->qpair->cpu_mapped)
3775+
qla_cpu_update(rsp->qpair, raw_smp_processor_id());
37733776
}
37743777

37753778
#define __update_rsp_in(_is_shadow_hba, _rsp, _rsp_in) \

drivers/scsi/stex.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ enum {
109109
TASK_ATTRIBUTE_HEADOFQUEUE = 0x1,
110110
TASK_ATTRIBUTE_ORDERED = 0x2,
111111
TASK_ATTRIBUTE_ACA = 0x4,
112+
};
112113

114+
enum {
113115
SS_STS_NORMAL = 0x80000000,
114116
SS_STS_DONE = 0x40000000,
115117
SS_STS_HANDSHAKE = 0x20000000,
@@ -121,7 +123,9 @@ enum {
121123
SS_I2H_REQUEST_RESET = 0x2000,
122124

123125
SS_MU_OPERATIONAL = 0x80000000,
126+
};
124127

128+
enum {
125129
STEX_CDB_LENGTH = 16,
126130
STATUS_VAR_LEN = 128,
127131

drivers/target/iscsi/iscsi_target.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,6 @@ struct iscsi_np *iscsit_add_np(
364364
init_completion(&np->np_restart_comp);
365365
INIT_LIST_HEAD(&np->np_list);
366366

367-
timer_setup(&np->np_login_timer, iscsi_handle_login_thread_timeout, 0);
368-
369367
ret = iscsi_target_setup_login_socket(np, sockaddr);
370368
if (ret != 0) {
371369
kfree(np);

drivers/target/iscsi/iscsi_target_login.c

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -811,59 +811,6 @@ void iscsi_post_login_handler(
811811
iscsit_dec_conn_usage_count(conn);
812812
}
813813

814-
void iscsi_handle_login_thread_timeout(struct timer_list *t)
815-
{
816-
struct iscsi_np *np = from_timer(np, t, np_login_timer);
817-
818-
spin_lock_bh(&np->np_thread_lock);
819-
pr_err("iSCSI Login timeout on Network Portal %pISpc\n",
820-
&np->np_sockaddr);
821-
822-
if (np->np_login_timer_flags & ISCSI_TF_STOP) {
823-
spin_unlock_bh(&np->np_thread_lock);
824-
return;
825-
}
826-
827-
if (np->np_thread)
828-
send_sig(SIGINT, np->np_thread, 1);
829-
830-
np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
831-
spin_unlock_bh(&np->np_thread_lock);
832-
}
833-
834-
static void iscsi_start_login_thread_timer(struct iscsi_np *np)
835-
{
836-
/*
837-
* This used the TA_LOGIN_TIMEOUT constant because at this
838-
* point we do not have access to ISCSI_TPG_ATTRIB(tpg)->login_timeout
839-
*/
840-
spin_lock_bh(&np->np_thread_lock);
841-
np->np_login_timer_flags &= ~ISCSI_TF_STOP;
842-
np->np_login_timer_flags |= ISCSI_TF_RUNNING;
843-
mod_timer(&np->np_login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
844-
845-
pr_debug("Added timeout timer to iSCSI login request for"
846-
" %u seconds.\n", TA_LOGIN_TIMEOUT);
847-
spin_unlock_bh(&np->np_thread_lock);
848-
}
849-
850-
static void iscsi_stop_login_thread_timer(struct iscsi_np *np)
851-
{
852-
spin_lock_bh(&np->np_thread_lock);
853-
if (!(np->np_login_timer_flags & ISCSI_TF_RUNNING)) {
854-
spin_unlock_bh(&np->np_thread_lock);
855-
return;
856-
}
857-
np->np_login_timer_flags |= ISCSI_TF_STOP;
858-
spin_unlock_bh(&np->np_thread_lock);
859-
860-
del_timer_sync(&np->np_login_timer);
861-
862-
spin_lock_bh(&np->np_thread_lock);
863-
np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
864-
spin_unlock_bh(&np->np_thread_lock);
865-
}
866-
867814
int iscsit_setup_np(
868815
struct iscsi_np *np,
869816
struct sockaddr_storage *sockaddr)
@@ -1123,10 +1070,13 @@ static struct iscsit_conn *iscsit_alloc_conn(struct iscsi_np *np)
11231070
spin_lock_init(&conn->nopin_timer_lock);
11241071
spin_lock_init(&conn->response_queue_lock);
11251072
spin_lock_init(&conn->state_lock);
1073+
spin_lock_init(&conn->login_worker_lock);
1074+
spin_lock_init(&conn->login_timer_lock);
11261075

11271076
timer_setup(&conn->nopin_response_timer,
11281077
iscsit_handle_nopin_response_timeout, 0);
11291078
timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
1079+
timer_setup(&conn->login_timer, iscsit_login_timeout, 0);
11301080

11311081
if (iscsit_conn_set_transport(conn, np->np_transport) < 0)
11321082
goto free_conn;
@@ -1304,7 +1254,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
13041254
goto new_sess_out;
13051255
}
13061256

1307-
iscsi_start_login_thread_timer(np);
1257+
iscsit_start_login_timer(conn, current);
13081258

13091259
pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
13101260
conn->conn_state = TARG_CONN_STATE_XPT_UP;
@@ -1417,8 +1367,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
14171367
if (ret < 0)
14181368
goto new_sess_out;
14191369

1420-
iscsi_stop_login_thread_timer(np);
1421-
14221370
if (ret == 1) {
14231371
tpg_np = conn->tpg_np;
14241372

@@ -1434,7 +1382,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
14341382
new_sess_out:
14351383
new_sess = true;
14361384
old_sess_out:
1437-
iscsi_stop_login_thread_timer(np);
1385+
iscsit_stop_login_timer(conn);
14381386
tpg_np = conn->tpg_np;
14391387
iscsi_target_login_sess_out(conn, zero_tsih, new_sess);
14401388
new_sess = false;
@@ -1448,7 +1396,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
14481396
return 1;
14491397

14501398
exit:
1451-
iscsi_stop_login_thread_timer(np);
14521399
spin_lock_bh(&np->np_thread_lock);
14531400
np->np_thread_state = ISCSI_NP_THREAD_EXIT;
14541401
spin_unlock_bh(&np->np_thread_lock);

drivers/target/iscsi/iscsi_target_nego.c

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
557538
static 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

657648
err:
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
}

drivers/target/iscsi/iscsi_target_util.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,57 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn)
10401040
spin_unlock_bh(&conn->nopin_timer_lock);
10411041
}
10421042

1043+
void iscsit_login_timeout(struct timer_list *t)
1044+
{
1045+
struct iscsit_conn *conn = from_timer(conn, t, login_timer);
1046+
struct iscsi_login *login = conn->login;
1047+
1048+
pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
1049+
1050+
spin_lock_bh(&conn->login_timer_lock);
1051+
login->login_failed = 1;
1052+
1053+
if (conn->login_kworker) {
1054+
pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
1055+
conn->login_kworker->comm, conn->login_kworker->pid);
1056+
send_sig(SIGINT, conn->login_kworker, 1);
1057+
} else {
1058+
schedule_delayed_work(&conn->login_work, 0);
1059+
}
1060+
spin_unlock_bh(&conn->login_timer_lock);
1061+
}
1062+
1063+
void iscsit_start_login_timer(struct iscsit_conn *conn, struct task_struct *kthr)
1064+
{
1065+
pr_debug("Login timer started\n");
1066+
1067+
conn->login_kworker = kthr;
1068+
mod_timer(&conn->login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
1069+
}
1070+
1071+
int iscsit_set_login_timer_kworker(struct iscsit_conn *conn, struct task_struct *kthr)
1072+
{
1073+
struct iscsi_login *login = conn->login;
1074+
int ret = 0;
1075+
1076+
spin_lock_bh(&conn->login_timer_lock);
1077+
if (login->login_failed) {
1078+
/* The timer has already expired */
1079+
ret = -1;
1080+
} else {
1081+
conn->login_kworker = kthr;
1082+
}
1083+
spin_unlock_bh(&conn->login_timer_lock);
1084+
1085+
return ret;
1086+
}
1087+
1088+
void iscsit_stop_login_timer(struct iscsit_conn *conn)
1089+
{
1090+
pr_debug("Login timer stopped\n");
1091+
timer_delete_sync(&conn->login_timer);
1092+
}
1093+
10431094
int iscsit_send_tx_data(
10441095
struct iscsit_cmd *cmd,
10451096
struct iscsit_conn *conn,

0 commit comments

Comments
 (0)