lib/nvme: fix mem leak in req submit.

Signed-off-by: Seth Howell <seth.howell@intel.com>
Change-Id: If64c06177605a8f57d87ba22b86fe58ddebd6f7a
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3921
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Michael Haeuptle <michaelhaeuptle@gmail.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
Seth Howell 2020-08-24 09:22:47 -07:00 committed by Tomasz Zawadzki
parent 4803dc36fc
commit 58216dd07e
2 changed files with 42 additions and 26 deletions

View File

@ -826,7 +826,18 @@ _nvme_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *r
nvme_qpair_check_enabled(qpair);
if (nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTED) {
if (spdk_unlikely(nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTED ||
nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTING ||
nvme_qpair_get_state(qpair) == NVME_QPAIR_DESTROYING)) {
TAILQ_FOREACH_SAFE(child_req, &req->children, child_tailq, tmp) {
nvme_request_remove_child(req, child_req);
nvme_request_free_children(child_req);
nvme_free_request(child_req);
}
if (req->parent != NULL) {
nvme_request_remove_child(req->parent, req);
}
nvme_free_request(req);
return -ENXIO;
}
@ -946,16 +957,6 @@ nvme_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *re
{
int rc;
/* This prevents us from entering an infinite loop when freeing queued I/O in disconnect. */
if (spdk_unlikely(nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTING ||
nvme_qpair_get_state(qpair) == NVME_QPAIR_DESTROYING)) {
if (req->parent != NULL) {
nvme_request_remove_child(req->parent, req);
}
nvme_free_request(req);
return -ENXIO;
}
if (spdk_unlikely(!STAILQ_EMPTY(&qpair->queued_req) && req->num_children == 0)) {
/*
* requests that have no children should be sent to the transport after all

View File

@ -496,15 +496,10 @@ test_nvme_qpair_add_cmd_error_injection(void)
cleanup_submit_request_test(&qpair);
}
static void
test_nvme_qpair_submit_request(void)
static struct nvme_request *
allocate_request_tree(struct spdk_nvme_qpair *qpair)
{
int rc;
struct spdk_nvme_qpair qpair = {};
struct spdk_nvme_ctrlr ctrlr = {};
struct nvme_request *req, *req1, *req2, *req3, *req2_1, *req2_2, *req2_3;
prepare_submit_request_test(&qpair, &ctrlr);
struct nvme_request *req, *req1, *req2, *req3, *req2_1, *req2_2, *req2_3;
/*
* Build a request chain like the following:
@ -518,51 +513,71 @@ test_nvme_qpair_submit_request(void)
* | | |
* req2_1 req2_2 req2_3
*/
req = nvme_allocate_request_null(&qpair, NULL, NULL);
req = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req != NULL);
TAILQ_INIT(&req->children);
req1 = nvme_allocate_request_null(&qpair, NULL, NULL);
req1 = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req1 != NULL);
req->num_children++;
TAILQ_INSERT_TAIL(&req->children, req1, child_tailq);
req1->parent = req;
req2 = nvme_allocate_request_null(&qpair, NULL, NULL);
req2 = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req2 != NULL);
TAILQ_INIT(&req2->children);
req->num_children++;
TAILQ_INSERT_TAIL(&req->children, req2, child_tailq);
req2->parent = req;
req3 = nvme_allocate_request_null(&qpair, NULL, NULL);
req3 = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req3 != NULL);
req->num_children++;
TAILQ_INSERT_TAIL(&req->children, req3, child_tailq);
req3->parent = req;
req2_1 = nvme_allocate_request_null(&qpair, NULL, NULL);
req2_1 = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req2_1 != NULL);
req2->num_children++;
TAILQ_INSERT_TAIL(&req2->children, req2_1, child_tailq);
req2_1->parent = req2;
req2_2 = nvme_allocate_request_null(&qpair, NULL, NULL);
req2_2 = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req2_2 != NULL);
req2->num_children++;
TAILQ_INSERT_TAIL(&req2->children, req2_2, child_tailq);
req2_2->parent = req2;
req2_3 = nvme_allocate_request_null(&qpair, NULL, NULL);
req2_3 = nvme_allocate_request_null(qpair, NULL, NULL);
CU_ASSERT(req2_3 != NULL);
req2->num_children++;
TAILQ_INSERT_TAIL(&req2->children, req2_3, child_tailq);
req2_3->parent = req2;
return req;
}
static void
test_nvme_qpair_submit_request(void)
{
int rc;
struct spdk_nvme_qpair qpair = {};
struct spdk_nvme_ctrlr ctrlr = {};
struct nvme_request *req;
prepare_submit_request_test(&qpair, &ctrlr);
req = allocate_request_tree(&qpair);
ctrlr.is_failed = true;
rc = nvme_qpair_submit_request(&qpair, req);
SPDK_CU_ASSERT_FATAL(rc == -ENXIO);
req = allocate_request_tree(&qpair);
ctrlr.is_failed = false;
qpair.state = NVME_QPAIR_DISCONNECTING;
rc = nvme_qpair_submit_request(&qpair, req);
SPDK_CU_ASSERT_FATAL(rc == -ENXIO);
cleanup_submit_request_test(&qpair);
}