Commit 2fa8961d authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Keith Busch
Browse files

nvmet-tcp: fixup hang in nvmet_tcp_listen_data_ready()

When the socket is closed while in TCP_LISTEN a callback is run to
flush all outstanding packets, which in turns calls
nvmet_tcp_listen_data_ready() with the sk_callback_lock held.
So we need to check if we are in TCP_LISTEN before attempting
to get the sk_callback_lock() to avoid a deadlock.

Link: https://lore.kernel.org/linux-nvme/CAHj4cs-zu7eVB78yUpFjVe2UqMWFkLk8p+DaS3qj+uiGCXBAoA@mail.gmail.com/


Tested-by: default avatarYi Zhang <yi.zhang@redhat.com>
Reviewed-by: default avatarSagi Grimberg <sagi@grimberg.me>
Signed-off-by: default avatarHannes Reinecke <hare@kernel.org>
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
parent d1877cc7
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -2004,14 +2004,13 @@ static void nvmet_tcp_listen_data_ready(struct sock *sk)

	trace_sk_data_ready(sk);

	if (sk->sk_state != TCP_LISTEN)
		return;

	read_lock_bh(&sk->sk_callback_lock);
	port = sk->sk_user_data;
	if (!port)
		goto out;

	if (sk->sk_state == TCP_LISTEN)
	if (port)
		queue_work(nvmet_wq, &port->accept_work);
out:
	read_unlock_bh(&sk->sk_callback_lock);
}