Skip to content

Commit 6825bdd

Browse files
sagigrimbergkeithbusch
authored andcommitted
nvmet-tcp: fix possible memory leak when tearing down a controller
When we teardown the controller, we wait for pending I/Os to complete (sq->ref on all queues to drop to zero) and then we go over the commands, and free their command buffers in case they are still fetching data from the host (e.g. processing nvme writes) and have yet to take a reference on the sq. However, we may miss the case where commands have failed before executing and are queued for sending a response, but will never occur because the queue socket is already down. In this case we may miss deallocating command buffers. Solve this by freeing all commands buffers as nvmet_tcp_free_cmd_buffers is idempotent anyways. Reported-by: Yi Zhang <yi.zhang@redhat.com> Tested-by: Yi Zhang <yi.zhang@redhat.com> Signed-off-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent 25bb353 commit 6825bdd

File tree

1 file changed

+4
-7
lines changed

1 file changed

+4
-7
lines changed

drivers/nvme/target/tcp.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ static int nvmet_tcp_check_ddgst(struct nvmet_tcp_queue *queue, void *pdu)
348348
return 0;
349349
}
350350

351+
/* If cmd buffers are NULL, no operation is performed */
351352
static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
352353
{
353354
kfree(cmd->iov);
@@ -1581,13 +1582,9 @@ static void nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue *queue)
15811582
struct nvmet_tcp_cmd *cmd = queue->cmds;
15821583
int i;
15831584

1584-
for (i = 0; i < queue->nr_cmds; i++, cmd++) {
1585-
if (nvmet_tcp_need_data_in(cmd))
1586-
nvmet_tcp_free_cmd_buffers(cmd);
1587-
}
1588-
1589-
if (!queue->nr_cmds && nvmet_tcp_need_data_in(&queue->connect))
1590-
nvmet_tcp_free_cmd_buffers(&queue->connect);
1585+
for (i = 0; i < queue->nr_cmds; i++, cmd++)
1586+
nvmet_tcp_free_cmd_buffers(cmd);
1587+
nvmet_tcp_free_cmd_buffers(&queue->connect);
15911588
}
15921589

15931590
static void nvmet_tcp_release_queue_work(struct work_struct *w)

0 commit comments

Comments
 (0)