mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
nvmet-rdma: fix double puts after a failed RDMA WRITE
For a read with T10-PI the RDMA WRITE is posted alone and
nvmet_rdma_write_data_done() posts the SEND once the metadata check
result is known. By then the request has been completed and its
references put: __nvmet_req_complete() put ns->ref and the pc_ref, and
nvmet_req_complete() sq->ref, right after queuing the response. The
error branch of nvmet_rdma_write_data_done() copies the one from
nvmet_rdma_read_data_done() and calls nvmet_req_uninit(), which puts
all three again. A WRITE fails whenever the connection ends with reads
in flight, which is up to the host. Depending on timing the sq->ref
count goes to zero early and the queue is freed under the remaining
completions, or never reaches zero and nvmet_sq_destroy() sleeps
forever, or percpu_ref_put() dereferences NULL after percpu_ref_exit().
ns->ref stays too low for good, so disabling the namespace hangs too.
Reproduced with KASAN over rxe with a test patch forcing the PI path.
Drop the nvmet_req_uninit(). The branch still releases the RDMA context
and the response, which is all the request owns at that point.
Fixes: b09160c399 ("nvmet-rdma: add metadata/T10-PI support")
Cc: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagi@grimberg.me>
Cc: Chaitanya Kulkarni <kch@nvidia.com>
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
parent
14e4e09443
commit
f1dac2a2e7
|
|
@ -803,7 +803,10 @@ static void nvmet_rdma_write_data_done(struct ib_cq *cq, struct ib_wc *wc)
|
|||
|
||||
if (unlikely(wc->status != IB_WC_SUCCESS)) {
|
||||
nvmet_rdma_rw_ctx_destroy(rsp);
|
||||
nvmet_req_uninit(&rsp->req);
|
||||
/*
|
||||
* Unlike in nvmet_rdma_read_data_done(), the request has been
|
||||
* completed and its references are put: no nvmet_req_uninit().
|
||||
*/
|
||||
nvmet_rdma_release_rsp(rsp);
|
||||
if (wc->status != IB_WC_WR_FLUSH_ERR) {
|
||||
pr_info("RDMA WRITE for CQE failed with status %s (%d).\n",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user