From f000aae84023b4a7673d6384298d050daa6d934a Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Mon, 11 Oct 2021 13:35:39 -0700 Subject: [PATCH] bdev/nvme: bdev_nvme_detach_controller now understands host parameters You can now detach specific paths based on the host parameters. This is useful for two paths to the same target that use different local NICs. Change-Id: I4858bfda7d940052ca77ffb0bbe764a688fb315d Signed-off-by: Ben Walker Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9827 Reviewed-by: Changpeng Liu Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris Tested-by: SPDK CI Jenkins Community-CI: Broadcom CI --- doc/jsonrpc.md | 2 ++ module/bdev/nvme/bdev_nvme.c | 16 ++++++++++++++++ module/bdev/nvme/bdev_nvme.h | 1 + module/bdev/nvme/bdev_nvme_rpc.c | 28 ++++++++++++++++++++++++++++ scripts/rpc.py | 8 +++++++- scripts/rpc/bdev.py | 11 ++++++++++- 6 files changed, 64 insertions(+), 2 deletions(-) diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 9fd29af8a..a3525251e 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -2994,6 +2994,8 @@ traddr | Optional | string | NVMe-oF target address: ip or adrfam | Optional | string | NVMe-oF target adrfam: ipv4, ipv6, ib, fc, intra_host trsvcid | Optional | string | NVMe-oF target trsvcid: port number subnqn | Optional | string | NVMe-oF target subnqn +hostaddr | Optional | string | NVMe-oF host address: ip +hostsvcid | Optional | string | NVMe-oF host svcid: port number #### Example diff --git a/module/bdev/nvme/bdev_nvme.c b/module/bdev/nvme/bdev_nvme.c index cdcb25fa6..61a1fa0a1 100644 --- a/module/bdev/nvme/bdev_nvme.c +++ b/module/bdev/nvme/bdev_nvme.c @@ -2995,6 +2995,10 @@ nvme_ctrlr_create(struct spdk_nvme_ctrlr *ctrlr, } path_id->trid = *trid; + if (ctx != NULL) { + memcpy(path_id->hostid.hostaddr, ctx->opts.src_addr, sizeof(path_id->hostid.hostaddr)); + memcpy(path_id->hostid.hostsvcid, ctx->opts.src_svcid, sizeof(path_id->hostid.hostsvcid)); + } nvme_ctrlr->active_path_id = path_id; TAILQ_INSERT_HEAD(&nvme_ctrlr->trids, path_id, link); @@ -3604,6 +3608,18 @@ bdev_nvme_delete(const char *name, const struct nvme_path_id *path_id) } } + if (!spdk_mem_all_zero(path_id->hostid.hostaddr, sizeof(path_id->hostid.hostaddr))) { + if (strcmp(path_id->hostid.hostaddr, p->hostid.hostaddr) != 0) { + continue; + } + } + + if (!spdk_mem_all_zero(path_id->hostid.hostsvcid, sizeof(path_id->hostid.hostsvcid))) { + if (strcmp(path_id->hostid.hostsvcid, p->hostid.hostsvcid) != 0) { + continue; + } + } + /* If we made it here, then this path is a match! Now we need to remove it. */ if (p == nvme_ctrlr->active_path_id) { /* This is the active path in use right now. The active path is always the first in the list. */ diff --git a/module/bdev/nvme/bdev_nvme.h b/module/bdev/nvme/bdev_nvme.h index b024b5117..40a363a28 100644 --- a/module/bdev/nvme/bdev_nvme.h +++ b/module/bdev/nvme/bdev_nvme.h @@ -84,6 +84,7 @@ struct nvme_bdev; struct nvme_path_id { struct spdk_nvme_transport_id trid; + struct spdk_nvme_host_id hostid; TAILQ_ENTRY(nvme_path_id) link; bool is_failed; }; diff --git a/module/bdev/nvme/bdev_nvme_rpc.c b/module/bdev/nvme/bdev_nvme_rpc.c index 583892466..1d8ad776f 100644 --- a/module/bdev/nvme/bdev_nvme_rpc.c +++ b/module/bdev/nvme/bdev_nvme_rpc.c @@ -593,6 +593,8 @@ struct rpc_bdev_nvme_detach_controller { char *traddr; char *trsvcid; char *subnqn; + char *hostaddr; + char *hostsvcid; }; static void @@ -604,6 +606,8 @@ free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req free(req->traddr); free(req->trsvcid); free(req->subnqn); + free(req->hostaddr); + free(req->hostsvcid); } static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = { @@ -613,6 +617,8 @@ static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_dec {"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true}, {"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true}, {"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true}, + {"hostaddr", offsetof(struct rpc_bdev_nvme_detach_controller, hostaddr), spdk_json_decode_string, true}, + {"hostsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, hostsvcid), spdk_json_decode_string, true}, }; static void @@ -694,6 +700,28 @@ rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request, memcpy(path.trid.subnqn, req.subnqn, len + 1); } + if (req.hostaddr) { + maxlen = sizeof(path.hostid.hostaddr); + len = strnlen(req.hostaddr, maxlen); + if (len == maxlen) { + spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s", + req.hostaddr); + goto cleanup; + } + snprintf(path.hostid.hostaddr, maxlen, "%s", req.hostaddr); + } + + if (req.hostsvcid) { + maxlen = sizeof(path.hostid.hostsvcid); + len = strnlen(req.hostsvcid, maxlen); + if (len == maxlen) { + spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s", + req.hostsvcid); + goto cleanup; + } + snprintf(path.hostid.hostsvcid, maxlen, "%s", req.hostsvcid); + } + rc = bdev_nvme_delete(req.name, &path); if (rc != 0) { diff --git a/scripts/rpc.py b/scripts/rpc.py index 953a415b0..35fec3a95 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -577,7 +577,9 @@ if __name__ == "__main__": traddr=args.traddr, adrfam=args.adrfam, trsvcid=args.trsvcid, - subnqn=args.subnqn) + subnqn=args.subnqn, + hostaddr=args.hostaddr, + hostsvcid=args.hostsvcid) p = subparsers.add_parser('bdev_nvme_detach_controller', aliases=['delete_nvme_controller'], help='Detach an NVMe controller and delete any associated bdevs') @@ -591,6 +593,10 @@ if __name__ == "__main__": p.add_argument('-s', '--trsvcid', help='NVMe-oF target trsvcid: e.g., a port number') p.add_argument('-n', '--subnqn', help='NVMe-oF target subnqn') + p.add_argument('-i', '--hostaddr', + help='NVMe-oF host address: e.g., an ip address') + p.add_argument('-c', '--hostsvcid', + help='NVMe-oF host svcid: e.g., a port number') p.set_defaults(func=bdev_nvme_detach_controller) def bdev_nvme_reset_controller(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index d7e02c1d1..a2b1992c2 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -583,7 +583,8 @@ def bdev_nvme_attach_controller(client, name, trtype, traddr, adrfam=None, trsvc @deprecated_alias('delete_nvme_controller') def bdev_nvme_detach_controller(client, name, trtype=None, traddr=None, - adrfam=None, trsvcid=None, subnqn=None): + adrfam=None, trsvcid=None, subnqn=None, + hostaddr=None, hostsvcid=None): """Detach NVMe controller and delete any associated bdevs. Optionally, If all of the transport ID options are specified, only remove that transport path from the specified controller. If that is the only @@ -597,6 +598,8 @@ def bdev_nvme_detach_controller(client, name, trtype=None, traddr=None, adrfam: address family ("IPv4", "IPv6", "IB", or "FC") trsvcid: transport service ID (port number for IP-based addresses) subnqn: subsystem NQN to connect to (optional) + hostaddr: Host address (IP address) + hostsvcid: transport service ID on host side (port number) """ params = {'name': name} @@ -616,6 +619,12 @@ def bdev_nvme_detach_controller(client, name, trtype=None, traddr=None, if subnqn: params['subnqn'] = subnqn + if hostaddr: + params['hostaddr'] = hostaddr + + if hostsvcid: + params['hostsvcid'] = hostsvcid + return client.call('bdev_nvme_detach_controller', params)