Commit ad69e739 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

nvme/tcp: Dequeue request from outstanding list before calling completion



Each request has a callback context as cb_arg, and the callback to
nvme_complete_request() for the completed request may reuse the context
to the new request.

On the other hand, TCP transport dequeues tcp_req from
tqpair->outstanding_reqs after calling nvme_complete_request() for
the request pointe by tcp_req.

Hence while nvme_complete_request() is executed, tqpair->outstanding_reqs
may have two requests which has the same callback context, the
completed request and the new submitted request.

The upcoming patch will search all requests whose cb_arg matches to
abort them. In the above case, the search may find two requests by
mistake.

To avoid such error, move dequeueing tcp_req from tqpair->outstanding_reqs
before calling nvme_request_complete(). One exception is the case that
only nvme_tcp_req_put() is called. For the case remove tcp_req from
tqpair->outstanding_reqs before calling nvme_tcp_req_put().

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I5f2ac292c60431ac1e27b8657db92b220860a0a8
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2865


Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarMichael Haeuptle <michaelhaeuptle@gmail.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent e060285e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -187,7 +187,6 @@ nvme_tcp_req_put(struct nvme_tcp_qpair *tqpair, struct nvme_tcp_req *tcp_req)
{
	assert(tcp_req->state != NVME_TCP_REQ_FREE);
	tcp_req->state = NVME_TCP_REQ_FREE;
	TAILQ_REMOVE(&tqpair->outstanding_reqs, tcp_req, link);
	TAILQ_INSERT_TAIL(&tqpair->free_reqs, tcp_req, link);
}

@@ -603,6 +602,7 @@ nvme_tcp_qpair_submit_request(struct spdk_nvme_qpair *qpair,

	if (nvme_tcp_req_init(tqpair, req, tcp_req)) {
		SPDK_ERRLOG("nvme_tcp_req_init() failed\n");
		TAILQ_REMOVE(&tcp_req->tqpair->outstanding_reqs, tcp_req, link);
		nvme_tcp_req_put(tqpair, tcp_req);
		return -1;
	}
@@ -625,6 +625,7 @@ nvme_tcp_req_complete(struct nvme_tcp_req *tcp_req,
	assert(tcp_req->req != NULL);
	req = tcp_req->req;

	TAILQ_REMOVE(&tcp_req->tqpair->outstanding_reqs, tcp_req, link);
	nvme_complete_request(req->cb_fn, req->cb_arg, req->qpair, req, rsp);
	nvme_free_request(req);
}