diff options
| author | Josef Bacik <josef@toxicpanda.com> | 2026-10-28 10:42:16 -0600 |
|---|---|---|
| committer | Keith Busch <kbusch@kernel.org> | 2026-10-28 11:41:41 -0700 |
| commit | ece0f4e67f08792c8572080fb0fcc231554f08ca (patch) | |
| tree | 2c00bdf3ac99ffe1ccc14cf5482260d38e48c535 | |
| parent | 4a5ace11b5a367270bc86097d31c35cb61890a95 (diff) | |
nvmet-tcp: stop listening when a port is removed
nvmet_tcp_accept_work() accepts until there's nothing left. A
connection that is already dead when accepted is torn down right there,
which takes a few ms, and more can arrive meanwhile.
nvmet_tcp_remove_port() waits for the work with cancel_work_sync(), so
someone opening and closing connections in a loop keeps the removal from
finishing. It holds nvmet_config_sem for writing, so nothing can be
configured and no port answers a Connect until the flood stops. No
secret needed, just an admin removing the port at the wrong time.
Shut the listening socket down first. Pending connections are dropped,
as they were on release, and the next kernel_accept() fails and ends the
work.
Fixes: 872d26a391da ("nvmet-tcp: add NVMe over TCP target driver")
Cc: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagi@grimberg.me>
Cc: Chaitanya Kulkarni <kch@nvidia.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Keith Busch <kbusch@kernel.org>
| -rw-r--r-- | drivers/nvme/target/tcp.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 7937377436d3..84af7d1bc588 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -2191,6 +2191,8 @@ static void nvmet_tcp_remove_port(struct nvmet_port *nport) port->sock->sk->sk_data_ready = port->data_ready; port->sock->sk->sk_user_data = NULL; write_unlock_bh(&port->sock->sk->sk_callback_lock); + /* The accept work goes on for as long as there is something to accept */ + kernel_sock_shutdown(port->sock, SHUT_RDWR); cancel_work_sync(&port->accept_work); /* * Destroy the remaining queues, which are not belong to any |
