diff options
Diffstat (limited to 'lib/libnvmf')
-rw-r--r-- | lib/libnvmf/libnvmf.h | 13 | ||||
-rw-r--r-- | lib/libnvmf/nvmf_controller.c | 50 | ||||
-rw-r--r-- | lib/libnvmf/nvmf_host.c | 21 |
3 files changed, 76 insertions, 8 deletions
diff --git a/lib/libnvmf/libnvmf.h b/lib/libnvmf/libnvmf.h index 9840e190a24f..6b38fd286596 100644 --- a/lib/libnvmf/libnvmf.h +++ b/lib/libnvmf/libnvmf.h @@ -111,8 +111,13 @@ const void *nvmf_capsule_cqe(const struct nvmf_capsule *nc); /* Return a string name for a transport type. */ const char *nvmf_transport_type(uint8_t trtype); -/* Validate a NVMe Qualified Name. */ +/* + * Validate a NVMe Qualified Name. The second version enforces + * stricter checks inline with the specification. The first version + * enforces more minimal checks. + */ bool nvmf_nqn_valid(const char *nqn); +bool nvmf_nqn_valid_strict(const char *nqn); /* Controller-specific APIs. */ @@ -342,7 +347,8 @@ int nvmf_host_request_queues(struct nvmf_qpair *qp, u_int requested, */ int nvmf_handoff_host(const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata); + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout); /* * Disconnect an active host association previously handed off to the @@ -370,7 +376,8 @@ int nvmf_reconnect_params(int fd, nvlist_t **nvlp); */ int nvmf_reconnect_host(int fd, const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata); + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout); /* * Fetch connection status from an existing kernel host. diff --git a/lib/libnvmf/nvmf_controller.c b/lib/libnvmf/nvmf_controller.c index 971dccbe039e..f26f11633e03 100644 --- a/lib/libnvmf/nvmf_controller.c +++ b/lib/libnvmf/nvmf_controller.c @@ -7,6 +7,7 @@ #include <sys/utsname.h> #include <assert.h> +#include <ctype.h> #include <errno.h> #include <string.h> #include <unistd.h> @@ -15,6 +16,55 @@ #include "internal.h" #include "nvmft_subr.h" +bool +nvmf_nqn_valid_strict(const char *nqn) +{ + size_t len; + + if (!nvmf_nqn_valid(nqn)) + return (false); + + /* + * Stricter checks from the spec. Linux does not seem to + * require these. + */ + len = strlen(nqn); + + /* + * NVMF_NQN_MIN_LEN does not include '.' and require at least + * one character of a domain name. + */ + if (len < NVMF_NQN_MIN_LEN + 2) + return (false); + if (memcmp("nqn.", nqn, strlen("nqn.")) != 0) + return (false); + nqn += strlen("nqn."); + + /* Next 4 digits must be a year. */ + for (u_int i = 0; i < 4; i++) { + if (!isdigit(nqn[i])) + return (false); + } + nqn += 4; + + /* '-' between year and month. */ + if (nqn[0] != '-') + return (false); + nqn++; + + /* 2 digit month. */ + for (u_int i = 0; i < 2; i++) { + if (!isdigit(nqn[i])) + return (false); + } + nqn += 2; + + /* '.' between month and reverse domain name. */ + if (nqn[0] != '.') + return (false); + return (true); +} + void nvmf_init_cqe(void *cqe, const struct nvmf_capsule *nc, uint16_t status) { diff --git a/lib/libnvmf/nvmf_host.c b/lib/libnvmf/nvmf_host.c index 89cdd5c6bb70..3266f8898296 100644 --- a/lib/libnvmf/nvmf_host.c +++ b/lib/libnvmf/nvmf_host.c @@ -792,7 +792,8 @@ static int prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout) { const struct nvmf_association *na = admin_qp->nq_association; nvlist_t *nvl, *nvl_qp, *nvl_rparams; @@ -820,6 +821,9 @@ prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, nvlist_add_string(nvl_rparams, "hostnqn", hostnqn); nvlist_add_number(nvl_rparams, "num_io_queues", num_queues); nvlist_add_number(nvl_rparams, "kato", admin_qp->nq_kato); + nvlist_add_number(nvl_rparams, "reconnect_delay", reconnect_delay); + nvlist_add_number(nvl_rparams, "controller_loss_timeout", + controller_loss_timeout); nvlist_add_number(nvl_rparams, "io_qsize", io_queues[0]->nq_qsize); nvlist_add_bool(nvl_rparams, "sq_flow_control", na->na_params.sq_flow_control); @@ -842,6 +846,9 @@ prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, nvl = nvlist_create(0); nvlist_add_number(nvl, "trtype", na->na_trtype); nvlist_add_number(nvl, "kato", admin_qp->nq_kato); + nvlist_add_number(nvl, "reconnect_delay", reconnect_delay); + nvlist_add_number(nvl, "controller_loss_timeout", + controller_loss_timeout); nvlist_move_nvlist(nvl, "rparams", nvl_rparams); /* First, the admin queue. */ @@ -872,7 +879,8 @@ prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, int nvmf_handoff_host(const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout) { struct nvmf_ioc_nv nv; u_int i; @@ -885,7 +893,8 @@ nvmf_handoff_host(const struct nvme_discovery_log_entry *dle, } error = prepare_queues_for_handoff(&nv, dle, hostnqn, admin_qp, - num_queues, io_queues, cdata); + num_queues, io_queues, cdata, reconnect_delay, + controller_loss_timeout); if (error != 0) goto out; @@ -981,14 +990,16 @@ nvmf_reconnect_params(int fd, nvlist_t **nvlp) int nvmf_reconnect_host(int fd, const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout) { struct nvmf_ioc_nv nv; u_int i; int error; error = prepare_queues_for_handoff(&nv, dle, hostnqn, admin_qp, - num_queues, io_queues, cdata); + num_queues, io_queues, cdata, reconnect_delay, + controller_loss_timeout); if (error != 0) goto out; |