mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-02-18 19:01:44 +00:00
iscsi-target: fix iscsit_del_np deadlock on unload
On uniprocessor preemptible kernel, target core deadlocks on unload. The following events happen: * iscsit_del_np is called * it calls send_sig(SIGINT, np->np_thread, 1); * the scheduler switches to the np_thread * the np_thread is woken up, it sees that kthread_should_stop() returns false, so it doesn't terminate * the np_thread clears signals with flush_signals(current); and goes back to sleep in iscsit_accept_np * the scheduler switches back to iscsit_del_np * iscsit_del_np calls kthread_stop(np->np_thread); * the np_thread is waiting in iscsit_accept_np and it doesn't respond to kthread_stop The deadlock could be resolved if the administrator sends SIGINT signal to the np_thread with killall -INT iscsi_np The reproducible deadlock was introduced in commit db6077fd0b7dd41dc6ff18329cec979379071f87, but the thread-stopping code was racy even before. This patch fixes the problem. Using kthread_should_stop to stop the np_thread is unreliable, so we test np_thread_state instead. If np_thread_state equals ISCSI_NP_THREAD_SHUTDOWN, the thread exits. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
ac5ccdba3a
commit
81a9c5e72b
@ -1216,7 +1216,7 @@ old_sess_out:
|
||||
static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
{
|
||||
u8 *buffer, zero_tsih = 0;
|
||||
int ret = 0, rc, stop;
|
||||
int ret = 0, rc;
|
||||
struct iscsi_conn *conn = NULL;
|
||||
struct iscsi_login *login;
|
||||
struct iscsi_portal_group *tpg = NULL;
|
||||
@ -1230,6 +1230,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
|
||||
np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
|
||||
complete(&np->np_restart_comp);
|
||||
} else if (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN) {
|
||||
spin_unlock_bh(&np->np_thread_lock);
|
||||
goto exit;
|
||||
} else {
|
||||
np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
|
||||
}
|
||||
@ -1422,10 +1425,8 @@ old_sess_out:
|
||||
}
|
||||
|
||||
out:
|
||||
stop = kthread_should_stop();
|
||||
/* Wait for another socket.. */
|
||||
if (!stop)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
exit:
|
||||
iscsi_stop_login_thread_timer(np);
|
||||
spin_lock_bh(&np->np_thread_lock);
|
||||
@ -1442,7 +1443,7 @@ int iscsi_target_login_thread(void *arg)
|
||||
|
||||
allow_signal(SIGINT);
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
while (1) {
|
||||
ret = __iscsi_target_login_thread(np);
|
||||
/*
|
||||
* We break and exit here unless another sock_accept() call
|
||||
|
Loading…
x
Reference in New Issue
Block a user