Add duplicate_connect option for ctlr connect requests
Subsystems (2)
v2 cover Add duplicate_connect option for ctlr connect requests
This patch adds a duplicate_connect option option to those supported by fabric connection requests. When set to true (1), duplicate connections are allowed. When set to false (0), duplicate connections are rejected.
The option is set in the fabrics layer and acted upon by each transport.
This patch set came about as of this prior patch review:
http://lists.infradead.org/pipermail/linux-nvme/2017-September/012783.html
---
v2:
split compare for hostnqn, hostid, subnqn to a helper function duplicate_connection converted to a boolean option (presence means true)
James Smart (4):
nvme: add duplicate_connect option
nvme: add helper to compare options to controller
nvme_fc: add support for duplicate_connect option
RFC: nvme-rdma: add support for duplicate_connect option
drivers/nvme/host/fabrics.c | 7 +++- drivers/nvme/host/fabrics.h | 14 ++++++++ drivers/nvme/host/fc.c | 33 ++++++++++++++++++ drivers/nvme/host/rdma.c | 82 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 1 deletion(-)
Signature · 1 line
2.13.1
PATCH v2 1/4 nvme: add duplicate_connect option
Add the "duplicate_connect" boolean option (presence means true). Default is false.
When false, the transport should validate whether a new controller request is targeted for the same host transport addressing and target transport addressing as an existing controller. If so, the new controller request should be rejected.
When true, the callee is explicitly requesting a duplicate controller connection to be made and the new request should be attempted.
--
v2:
duplicate_connect option converted to a boolean
--- drivers/nvme/host/fabrics.c | 7 ++++++- drivers/nvme/host/fabrics.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-)
drivers/nvme/host/fabrics.c +6 -1
@@ -548,6 +548,7 @@ static const match_table_t opt_tokens = { { NVMF_OPT_HOSTNQN, "hostnqn=%s" }, { NVMF_OPT_HOST_TRADDR, "host_traddr=%s" }, { NVMF_OPT_HOST_ID, "hostid=%s" }, + { NVMF_OPT_DUP_CONNECT, "duplicate_connect" }, { NVMF_OPT_ERR, NULL } };
@@ -566,6 +567,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, opts->nr_io_queues =num_online_cpus (); opts->reconnect_delay =NVMF_DEF_RECONNECT_DELAY ; opts->kato =NVME_DEFAULT_KATO ; + opts->duplicate_connect = false; options = o =kstrdup (buf,GFP_KERNEL );if (!options)
@@ -742,6 +744,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, goto out; }break ; +case NVMF_OPT_DUP_CONNECT : + opts->duplicate_connect = true; +break ;default :pr_warn ("unknown parameter or missing value '%s' in ctrl creation request\n" , p);
@@ -823,7 +828,7 @@ EXPORT_SYMBOL_GPL(nvmf_free_options);#define NVMF_REQUIRED_OPTS (NVMF_OPT_TRANSPORT | NVMF_OPT_NQN)#define NVMF_ALLOWED_OPTS (NVMF_OPT_QUEUE_SIZE | NVMF_OPT_NR_IO_QUEUES | \ NVMF_OPT_KATO | NVMF_OPT_HOSTNQN | \ - NVMF_OPT_HOST_ID) + NVMF_OPT_HOST_ID | NVMF_OPT_DUP_CONNECT)static struct nvme_ctrl *nvmf_create_ctrl (struct device *dev,const char *buf,size_t count)
drivers/nvme/host/fabrics.h +2 -0
@@ -57,6 +57,7 @@ enum {NVMF_OPT_HOST_TRADDR =1 <<10 ,NVMF_OPT_CTRL_LOSS_TMO =1 <<11 ,NVMF_OPT_HOST_ID =1 <<12 , + NVMF_OPT_DUP_CONNECT = 1 << 13, };/**
@@ -96,6 +97,7 @@ struct nvmf_ctrl_options {unsigned int nr_io_queues;unsigned int reconnect_delay;bool discovery_nqn; +bool duplicate_connect;unsigned int kato;struct nvmf_host *host;int max_reconnects;
Signature · 1 line
2.13.1
PATCH v2 1/4 nvme: add duplicate_connect option
Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn at suse.de>
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
PATCH v2 2/4 nvme: add helper to compare options to controller
In reply to James SmartAdds a helper function that compares the host and subsytem specified in a connect options list vs a controller.
--- drivers/nvme/host/fabrics.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/nvme/host/fabrics.h +12 -0
@@ -133,6 +133,18 @@ struct nvmf_transport_ops { struct nvmf_ctrl_options *opts); }; +static inline bool +nvmf_ctlr_matches_baseopts (struct nvme_ctrl *ctrl, +struct nvmf_ctrl_options *opts) +{ +if (strcmp (opts->subsysnqn, ctrl->opts->subsysnqn) || +strcmp (opts->host->nqn, ctrl->opts->host->nqn) || +memcmp (&opts->host->id, &ctrl->opts->host->id,sizeof (uuid_t))) +return false; + +return true; +} +int nvmf_reg_read32 (struct nvme_ctrl *ctrl,u32 off,u32 *val);int nvmf_reg_read64 (struct nvme_ctrl *ctrl,u32 off,u64 *val);int nvmf_reg_write32 (struct nvme_ctrl *ctrl,u32 off,u32 val);
Signature · 1 line
2.13.1
PATCH v2 2/4 nvme: add helper to compare options to controller
Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn at suse.de>
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
PATCH v2 3/4 nvme_fc: add support for duplicate_connect option
In reply to James SmartAdds support for the duplicate_connect option. When set to true, checks whether there's an existing controller via the same host port and target port for the same host (hostnqn, hostid) to the same subsystem. Fails the connection request if an existing controller.
--- drivers/nvme/host/fc.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/nvme/host/fc.c +33 -0
@@ -2785,6 +2785,33 @@ static const struct blk_mq_ops nvme_fc_admin_mq_ops = { }; +/* +* Fails a controller request if it matches an existing controller +* (association) with the same tuple: +* <Host NQN, Host ID, local FC port, remote FC port, SUBSYS NQN> +* +* The ports don't need to be compared as they are intrinsically +* already matched by the port pointers supplied. +*/ +static bool +nvme_fc_existing_controller (struct nvme_fc_rport *rport, +struct nvmf_ctrl_options *opts) +{ +struct nvme_fc_ctrl *ctrl; +unsigned long flags; +bool found = false; + +spin_lock_irqsave (&rport->lock, flags); +list_for_each_entry (ctrl, &rport->ctrl_list, ctrl_list) { + found =nvmf_ctlr_matches_baseopts (&ctrl->ctrl, opts); +if (found) +break ; + } +spin_unlock_irqrestore (&rport->lock, flags); + +return found; +} +static struct nvme_ctrl *nvme_fc_init_ctrl (struct device *dev,struct nvmf_ctrl_options *opts,struct nvme_fc_lport *lport,struct nvme_fc_rport *rport)
@@ -2799,6 +2826,12 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, goto out_fail; } +if (!opts->duplicate_connect && +nvme_fc_existing_controller (rport, opts)) { + ret = -EALREADY ; + goto out_fail; + } + ctrl =kzalloc (sizeof (*ctrl),GFP_KERNEL );if (!ctrl) { ret = -ENOMEM ;
Signature · 1 line
2.13.1
PATCH v2 3/4 nvme_fc: add support for duplicate_connect option
Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn at suse.de>
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
PATCH v2 3/4 nvme_fc: add support for duplicate_connect option
In reply to James SmartLooks good,
Reviewed-by: Johannes Thumshirn <jthumshirn at suse.de>
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
PATCH v2 4/4 nvme-rdma: add support for duplicate_connect option
In reply to James SmartAdds support for the duplicate_connect option. When set to true, checks whether there's an existing controller via the same target address (traddr), target port (trsvcid), and if specified, host address (host_traddr). Fails the connection request if there is an existing controller.
--- drivers/nvme/host/rdma.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
drivers/nvme/host/rdma.c +82 -0
@@ -1848,6 +1848,83 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = { .reinit_request = nvme_rdma_reinit_request, }; +static inline bool +__nvme_rdma_options_match (struct nvme_rdma_ctrl *ctrl, +struct nvmf_ctrl_options *opts) +{ +char *stdport =__stringify (NVME_RDMA_IP_PORT ); + + +if (!nvmf_ctlr_matches_baseopts (&ctrl->ctrl, opts) || +strcmp (opts->traddr, ctrl->ctrl.opts->traddr)) +return false; + +if (opts->mask &NVMF_OPT_TRSVCID && + ctrl->ctrl.opts->mask &NVMF_OPT_TRSVCID ) { +if (strcmp (opts->trsvcid, ctrl->ctrl.opts->trsvcid)) +return false; + }else if (opts->mask &NVMF_OPT_TRSVCID ) { +if (strcmp (opts->trsvcid, stdport)) +return false; + }else if (ctrl->ctrl.opts->mask &NVMF_OPT_TRSVCID ) { +if (strcmp (stdport, ctrl->ctrl.opts->trsvcid)) +return false; + } +/* else, it's a match as both have stdport. Fall to next checks */ + +/* +* checking the local address is rough. In most cases, one +* is not specified and the host port is selected by the stack. +* +* Assume no match if: +* local address is specified and address is not the same +* local address is not specified but remote is, or vice versa +* (admin using specific host_traddr when it matters). +*/ +if (opts->mask &NVMF_OPT_HOST_TRADDR && + ctrl->ctrl.opts->mask &NVMF_OPT_HOST_TRADDR ) { +if (strcmp (opts->host_traddr, ctrl->ctrl.opts->host_traddr)) +return false; + }else if (opts->mask &NVMF_OPT_HOST_TRADDR || + ctrl->ctrl.opts->mask &NVMF_OPT_HOST_TRADDR ) +return false; +/* +* if neither controller had an host port specified, assume it's +* a match as everything else matched. +*/ + +return true; +} + +/* +* Fails a connection request if it matches an existing controller +* (association) with the same tuple: +* <Host NQN, Host ID, local address, remote address, remote port, SUBSYS NQN> +* +* if local address is not specified in the request, it will match an +* existing controller with all the other parameters the same and no +* local port address specified as well. +* +* The ports don't need to be compared as they are intrinsically +* already matched by the port pointers supplied. +*/ +static bool +nvme_rdma_existing_controller (struct nvmf_ctrl_options *opts) +{ +struct nvme_rdma_ctrl *ctrl; +bool found = false; + +mutex_lock (&nvme_rdma_ctrl_mutex); +list_for_each_entry (ctrl, &nvme_rdma_ctrl_list, list) { + found =__nvme_rdma_options_match (ctrl, opts); +if (found) +break ; + } +mutex_unlock (&nvme_rdma_ctrl_mutex); + +return found; +} +static struct nvme_ctrl *nvme_rdma_create_ctrl (struct device *dev,struct nvmf_ctrl_options *opts) {
@@ -1884,6 +1961,11 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, } } +if (!opts->duplicate_connect &&nvme_rdma_existing_controller (opts)) { + ret = -EALREADY ; + goto out_free_ctrl; + } + ret =nvme_init_ctrl (&ctrl->ctrl, dev, &nvme_rdma_ctrl_ops,0 /* no quirks, we're perfect! */ );if (ret)
Signature · 1 line
2.13.1
PATCH v2 4/4 nvme-rdma: add support for duplicate_connect option
Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn at suse.de>
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850