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 <jacek.kalwas@intel.com>
Change-Id: Ib19f2e50838feff1c9108957ee82a42da66e54a2
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/482446
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Alexey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Jacek Kalwas 2020-01-23 01:10:36 +01:00 committed by Jim Harris
parent bad8847f7a
commit e1d1695cef
3 changed files with 12 additions and 7 deletions

View File

@ -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);

View File

@ -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");

View File

@ -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;
}