From 79727986e0e9d698d492572e1d4594ba27520683 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Wed, 8 Dec 2021 10:22:24 +0000 Subject: [PATCH] nvmf: fix disconnect logic for remove_listener RPC Currently if we remove a listener from a subsystem, we disconnect *all* qpairs that have the same transport ID as the listener being removed. Fix that, since we should only disconnect qpairs from controllers associated with the subsystem that had the listener removed. Signed-off-by: Jim Harris Change-Id: I6cf7422d14f23bf02ba6c4b034b172870694b3e6 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10690 Community-CI: Mellanox Build Bot Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins Reviewed-by: Changpeng Liu Reviewed-by: Aleksey Marchuk --- CHANGELOG.md | 5 +++++ include/spdk/nvmf.h | 6 +++++- lib/nvmf/nvmf_rpc.c | 4 ++-- lib/nvmf/transport.c | 8 +++++++- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fe38792d..2c059a2c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,11 @@ they did not account for PCI devices being inserted or removed while the caller returned from these APIs. Existing users of these APIs should switch to spdk_pci_for_each_device instead. +### nvmf + +Added a 'subsystem' parameter to spdk_nvmf_transport_stop_listen_async. When not NULL, +it will only disconnect qpairs for controllers associated with the specified subsystem. + ## v21.10 Structure `spdk_nvmf_target_opts` has been extended with new member `discovery_filter` which allows to specify diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index 085fbcc10..13e9f1308 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -1109,12 +1109,15 @@ spdk_nvmf_transport_stop_listen(struct spdk_nvmf_transport *transport, * Stop accepting new connections at the provided address. * * This is a counterpart to spdk_nvmf_tgt_listen_ext(). It differs - * from spdk_nvmf_transport_stop_listen() in that it also destroys all + * from spdk_nvmf_transport_stop_listen() in that it also destroys * qpairs that are connected to the specified listener. Because * this function disconnects the qpairs, it has to be asynchronous. * * \param transport The transport associated with the listen address. * \param trid The address to stop listening at. + * \param subsystem The subsystem to match for qpairs with the specified + * trid. If NULL, it will disconnect all qpairs with the + * specified trid. * \param cb_fn The function to call on completion. * \param cb_arg The argument to pass to the cb_fn. * @@ -1122,6 +1125,7 @@ spdk_nvmf_transport_stop_listen(struct spdk_nvmf_transport *transport, */ int spdk_nvmf_transport_stop_listen_async(struct spdk_nvmf_transport *transport, const struct spdk_nvme_transport_id *trid, + struct spdk_nvmf_subsystem *subsystem, spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg); diff --git a/lib/nvmf/nvmf_rpc.c b/lib/nvmf/nvmf_rpc.c index d9518552f..a9d6a3b87 100644 --- a/lib/nvmf/nvmf_rpc.c +++ b/lib/nvmf/nvmf_rpc.c @@ -792,8 +792,8 @@ nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem, } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) { rc = spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid); if (rc == 0) { - spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, nvmf_rpc_stop_listen_async_done, - ctx); + spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, subsystem, + nvmf_rpc_stop_listen_async_done, ctx); return; } SPDK_ERRLOG("Unable to remove listener, rc %d\n", rc); diff --git a/lib/nvmf/transport.c b/lib/nvmf/transport.c index d255e7290..a261b565a 100644 --- a/lib/nvmf/transport.c +++ b/lib/nvmf/transport.c @@ -363,6 +363,7 @@ spdk_nvmf_transport_stop_listen(struct spdk_nvmf_transport *transport, struct nvmf_stop_listen_ctx { struct spdk_nvmf_transport *transport; struct spdk_nvme_transport_id trid; + struct spdk_nvmf_subsystem *subsystem; spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn; void *cb_arg; }; @@ -409,7 +410,10 @@ nvmf_stop_listen_disconnect_qpairs(struct spdk_io_channel_iter *i) } if (!spdk_nvme_transport_id_compare(&ctx->trid, &tmp_trid)) { - spdk_nvmf_qpair_disconnect(qpair, NULL, NULL); + if (ctx->subsystem == NULL || + ctx->subsystem == qpair->ctrlr->subsys) { + spdk_nvmf_qpair_disconnect(qpair, NULL, NULL); + } } } spdk_for_each_channel_continue(i, 0); @@ -418,6 +422,7 @@ nvmf_stop_listen_disconnect_qpairs(struct spdk_io_channel_iter *i) int spdk_nvmf_transport_stop_listen_async(struct spdk_nvmf_transport *transport, const struct spdk_nvme_transport_id *trid, + struct spdk_nvmf_subsystem *subsystem, spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg) { @@ -429,6 +434,7 @@ spdk_nvmf_transport_stop_listen_async(struct spdk_nvmf_transport *transport, } ctx->trid = *trid; + ctx->subsystem = subsystem; ctx->transport = transport; ctx->cb_fn = cb_fn; ctx->cb_arg = cb_arg;