diff --git a/sbin/nvmecontrol/fabrics.c b/sbin/nvmecontrol/fabrics.c --- a/sbin/nvmecontrol/fabrics.c +++ b/sbin/nvmecontrol/fabrics.c @@ -148,7 +148,8 @@ static bool tcp_qpair_params(struct nvmf_qpair_params *params, int adrfam, - const char *address, const char *port) + const char *address, const char *port, struct addrinfo **aip, + struct addrinfo **listp) { struct addrinfo hints, *ai, *list; int error, s; @@ -173,7 +174,11 @@ } params->tcp.fd = s; - freeaddrinfo(list); + if (listp != NULL) { + *aip = ai; + *listp = list; + } else + freeaddrinfo(list); return (true); } warn("Failed to connect to controller at %s:%s", address, port); @@ -181,6 +186,24 @@ return (false); } +static bool +tcp_qpair_params_ai(struct nvmf_qpair_params *params, struct addrinfo *ai) +{ + int s; + + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s == -1) + return (false); + + if (connect(s, ai->ai_addr, ai->ai_addrlen) != 0) { + close(s); + return (false); + } + + params->tcp.fd = s; + return (true); +} + static void tcp_discovery_association_params(struct nvmf_association_params *params) { @@ -228,7 +251,7 @@ err(EX_IOERR, "Failed to create discovery association"); memset(&qparams, 0, sizeof(qparams)); qparams.admin = true; - if (!tcp_qpair_params(&qparams, AF_UNSPEC, address, port)) + if (!tcp_qpair_params(&qparams, AF_UNSPEC, address, port, NULL, NULL)) exit(EX_NOHOST); qp = nvmf_connect(na, &qparams, 0, NVME_MIN_ADMIN_ENTRIES, hostid, NVMF_CNTLID_DYNAMIC, NVMF_DISCOVERY_NQN, hostnqn, 0); @@ -417,6 +440,7 @@ { struct nvmf_qpair_params qparams; struct nvmf_association *na; + struct addrinfo *ai, *list; u_int queues; int error; uint16_t mqes; @@ -446,7 +470,7 @@ /* Admin queue. */ memset(&qparams, 0, sizeof(qparams)); qparams.admin = true; - if (!tcp_qpair_params(&qparams, adrfam, address, port)) { + if (!tcp_qpair_params(&qparams, adrfam, address, port, &ai, &list)) { nvmf_free_association(na); return (EX_NOHOST); } @@ -454,6 +478,7 @@ kato, &mqes); if (error != 0) { nvmf_free_association(na); + freeaddrinfo(list); return (error); } @@ -463,6 +488,7 @@ else if (queue_size > (u_int)mqes + 1) { shutdown_controller(*admin); nvmf_free_association(na); + freeaddrinfo(list); warnx("I/O queue size exceeds controller maximum (%u)", mqes + 1); return (EX_USAGE); @@ -473,6 +499,7 @@ if (error != 0) { shutdown_controller(*admin); nvmf_free_association(na); + freeaddrinfo(list); warnc(error, "Failed to fetch controller data for %s", subnqn); return (EX_IOERR); } @@ -483,12 +510,14 @@ if (error != 0) { shutdown_controller(*admin); nvmf_free_association(na); + freeaddrinfo(list); warnc(error, "Failed to request I/O queues"); return (EX_IOERR); } if (queues < num_io_queues) { shutdown_controller(*admin); nvmf_free_association(na); + freeaddrinfo(list); warnx("Controller enabled fewer I/O queues (%u) than requested (%u)", queues, num_io_queues); return (EX_PROTOCOL); @@ -499,7 +528,9 @@ for (u_int i = 0; i < num_io_queues; i++) { memset(&qparams, 0, sizeof(qparams)); qparams.admin = false; - if (!tcp_qpair_params(&qparams, adrfam, address, port)) { + if (!tcp_qpair_params_ai(&qparams, ai)) { + warn("Failed to connect to controller at %s:%s", + address, port); error = EX_NOHOST; goto out; } @@ -513,11 +544,13 @@ } } nvmf_free_association(na); + freeaddrinfo(list); return (0); out: disconnect_nvm_queues(*admin, io, num_io_queues); nvmf_free_association(na); + freeaddrinfo(list); return (error); }