Commit 79727986 authored by Jim Harris's avatar Jim Harris Committed by Tomasz Zawadzki
Browse files

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: default avatarJim Harris <james.r.harris@intel.com>
Change-Id: I6cf7422d14f23bf02ba6c4b034b172870694b3e6
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10690


Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
parent ef8f297b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
+5 −1
Original line number Diff line number Diff line
@@ -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);

+2 −2
Original line number Diff line number Diff line
@@ -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);
+7 −1
Original line number Diff line number Diff line
@@ -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,15 +410,19 @@ nvmf_stop_listen_disconnect_qpairs(struct spdk_io_channel_iter *i)
		}

		if (!spdk_nvme_transport_id_compare(&ctx->trid, &tmp_trid)) {
			if (ctx->subsystem == NULL ||
			    ctx->subsystem == qpair->ctrlr->subsys) {
				spdk_nvmf_qpair_disconnect(qpair, NULL, NULL);
			}
		}
	}
	spdk_for_each_channel_continue(i, 0);
}

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;