From e1d1695cef25400d8370d8aaa5d877b5a66aacc3 Mon Sep 17 00:00:00 2001 From: Jacek Kalwas Date: Thu, 23 Jan 2020 01:10:36 +0100 Subject: [PATCH] nvmf: check if listener already exists in subsystem earlier It fixes memory leak e.g. when add_listener rpc called twice with the same trid on the same subsystem (ref = 2). In such case kill or remove_listener decrements ref only once. Signed-off-by: Jacek Kalwas Change-Id: Ib19f2e50838feff1c9108957ee82a42da66e54a2 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/482446 Tested-by: SPDK CI Jenkins Community-CI: Broadcom SPDK FC-NVMe CI Reviewed-by: Alexey Marchuk Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/nvmf/nvmf_internal.h | 3 +++ lib/nvmf/nvmf_rpc.c | 6 ++++-- lib/nvmf/subsystem.c | 10 +++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 3ff83a67c..dbed700a0 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -447,6 +447,9 @@ void spdk_nvmf_subsystem_remove_all_listeners(struct spdk_nvmf_subsystem *subsys bool stop); struct spdk_nvmf_ctrlr *spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid); +struct spdk_nvmf_listener *spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, + const struct spdk_nvme_transport_id *trid); + int spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr); void spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr); void spdk_nvmf_ns_reservation_request(void *ctx); diff --git a/lib/nvmf/nvmf_rpc.c b/lib/nvmf/nvmf_rpc.c index 061de38d5..9855c942a 100644 --- a/lib/nvmf/nvmf_rpc.c +++ b/lib/nvmf/nvmf_rpc.c @@ -655,8 +655,10 @@ nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem, struct nvmf_rpc_listener_ctx *ctx = cb_arg; if (ctx->op == NVMF_RPC_LISTEN_ADD) { - spdk_nvmf_tgt_listen(ctx->tgt, &ctx->trid, nvmf_rpc_tgt_listen, ctx); - return; + if (!spdk_nvmf_subsystem_find_listener(subsystem, &ctx->trid)) { + spdk_nvmf_tgt_listen(ctx->tgt, &ctx->trid, nvmf_rpc_tgt_listen, ctx); + return; + } } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) { if (spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid)) { SPDK_ERRLOG("Unable to remove listener.\n"); diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index eace99f97..c62797d6d 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -732,9 +732,9 @@ spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host) return host->nqn; } -static struct spdk_nvmf_listener * -_spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, - const struct spdk_nvme_transport_id *trid) +struct spdk_nvmf_listener * +spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem, + const struct spdk_nvme_transport_id *trid) { struct spdk_nvmf_listener *listener; @@ -759,7 +759,7 @@ spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, return -EAGAIN; } - if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) { + if (spdk_nvmf_subsystem_find_listener(subsystem, trid)) { /* Listener already exists in this subsystem */ return 0; } @@ -795,7 +795,7 @@ spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, return -EAGAIN; } - listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid); + listener = spdk_nvmf_subsystem_find_listener(subsystem, trid); if (listener == NULL) { return -ENOENT; }