The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=0aa09b7a2a37a437525d1b803ceb7342f37b3034
commit 0aa09b7a2a37a437525d1b803ceb7342f37b3034 Author: John Baldwin <j...@freebsd.org> AuthorDate: 2025-08-04 19:38:07 +0000 Commit: John Baldwin <j...@freebsd.org> CommitDate: 2025-08-04 19:38:07 +0000 ctld: Convert struct isns to a C++ class - Use std::string and freebsd::addrinfo_up for members. - Add methods to open a connection and to send a request and parse its response. - Refactor existing isns_do_* functions to just construct requests from a configuration. Sponsored by: Chelsio Communications Pull Request: https://github.com/freebsd/freebsd-src/pull/1794 --- usr.sbin/ctld/ctld.cc | 224 +++++++++++++++++++------------------------------- usr.sbin/ctld/ctld.hh | 27 ++++-- usr.sbin/ctld/isns.cc | 3 +- usr.sbin/ctld/isns.hh | 5 +- 4 files changed, 110 insertions(+), 149 deletions(-) diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc index 8815034930b4..29bbea126273 100644 --- a/usr.sbin/ctld/ctld.cc +++ b/usr.sbin/ctld/ctld.cc @@ -103,7 +103,6 @@ conf_new(void) conf = new struct conf(); TAILQ_INIT(&conf->conf_luns); TAILQ_INIT(&conf->conf_targets); - TAILQ_INIT(&conf->conf_isns); conf->conf_isns_period = 900; conf->conf_isns_timeout = 5; @@ -119,7 +118,6 @@ conf_delete(struct conf *conf) { struct lun *lun, *ltmp; struct target *targ, *tmp; - struct isns *is, *istmp; assert(conf->conf_pidfh == NULL); @@ -127,8 +125,6 @@ conf_delete(struct conf *conf) lun_delete(lun); TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp) target_delete(targ); - TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp) - isns_delete(is); free(conf->conf_pidfile_path); delete conf; } @@ -769,19 +765,14 @@ portal_group::close_sockets() bool isns_new(struct conf *conf, const char *addr) { - struct isns *isns; - - isns = reinterpret_cast<struct isns *>(calloc(1, sizeof(*isns))); - if (isns == NULL) - log_err(1, "calloc"); - isns->i_conf = conf; - TAILQ_INSERT_TAIL(&conf->conf_isns, isns, i_next); - isns->i_addr = checked_strdup(addr); + if (conf->conf_isns.count(addr) > 0) { + log_warnx("duplicate iSNS address %s", addr); + return (false); + } - freebsd::addrinfo_up ai = parse_addr_port(isns->i_addr, "3205"); + freebsd::addrinfo_up ai = parse_addr_port(addr, "3205"); if (!ai) { - log_warnx("invalid iSNS address %s", isns->i_addr); - isns_delete(isns); + log_warnx("invalid iSNS address %s", addr); return (false); } @@ -790,49 +781,54 @@ isns_new(struct conf *conf, const char *addr) * those into multiple servers. */ - isns->i_ai = ai.release(); + conf->conf_isns.emplace(addr, isns(addr, std::move(ai))); return (true); } -void -isns_delete(struct isns *isns) +freebsd::fd_up +isns::connect() { + freebsd::fd_up s; - TAILQ_REMOVE(&isns->i_conf->conf_isns, isns, i_next); - free(isns->i_addr); - if (isns->i_ai != NULL) - freeaddrinfo(isns->i_ai); - free(isns); + s = socket(i_ai->ai_family, i_ai->ai_socktype, i_ai->ai_protocol); + if (!s) { + log_warn("socket(2) failed for %s", addr()); + return (s); + } + if (::connect(s, i_ai->ai_addr, i_ai->ai_addrlen)) { + log_warn("connect(2) failed for %s", addr()); + s.reset(); + } + return (s); } -static int -isns_do_connect(struct isns *isns) +bool +isns::send_request(int s, struct isns_req req) { - int s; - - s = socket(isns->i_ai->ai_family, isns->i_ai->ai_socktype, - isns->i_ai->ai_protocol); - if (s < 0) { - log_warn("socket(2) failed for %s", isns->i_addr); - return (-1); + if (!req.send(s)) { + log_warn("send(2) failed for %s", addr()); + return (false); } - if (connect(s, isns->i_ai->ai_addr, isns->i_ai->ai_addrlen)) { - log_warn("connect(2) failed for %s", isns->i_addr); - close(s); - return (-1); + if (!req.receive(s)) { + log_warn("receive(2) failed for %s", addr()); + return (false); } - return(s); + uint32_t error = req.get_status(); + if (error != 0) { + log_warnx("iSNS %s error %u for %s", req.descr(), error, + addr()); + return (false); + } + return (true); } -static void -isns_do_register(struct isns *isns, int s, const char *hostname) +static struct isns_req +isns_register_request(struct conf *conf, const char *hostname) { - struct conf *conf = isns->i_conf; struct target *target; const struct portal_group *pg; - uint32_t error; - isns_req req(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT); + isns_req req(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT, "register"); req.add_str(32, TAILQ_FIRST(&conf->conf_targets)->t_name); req.add_delim(); req.add_str(1, hostname); @@ -864,84 +860,43 @@ isns_do_register(struct isns *isns, int s, const char *hostname) } } } - if (!req.send(s)) { - log_warn("send(2) failed for %s", isns->i_addr); - return; - } - if (!req.receive(s)) { - log_warn("receive(2) failed for %s", isns->i_addr); - return; - } - error = req.get_status(); - if (error != 0) { - log_warnx("iSNS register error %d for %s", error, isns->i_addr); - } + return (req); } -static bool -isns_do_check(struct isns *isns, int s, const char *hostname) +static struct isns_req +isns_check_request(struct conf *conf, const char *hostname) { - struct conf *conf = isns->i_conf; - uint32_t error; - - isns_req req(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT); + isns_req req(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT, "check"); req.add_str(32, TAILQ_FIRST(&conf->conf_targets)->t_name); req.add_str(1, hostname); req.add_delim(); req.add(2, 0, NULL); - if (!req.send(s)) { - log_warn("send(2) failed for %s", isns->i_addr); - return (false); - } - if (!req.receive(s)) { - log_warn("receive(2) failed for %s", isns->i_addr); - return (false); - } - error = req.get_status(); - if (error != 0) { - log_warnx("iSNS check error %d for %s", error, isns->i_addr); - return (false); - } - return (true); + return (req); } -static void -isns_do_deregister(struct isns *isns, int s, const char *hostname) +static struct isns_req +isns_deregister_request(struct conf *conf, const char *hostname) { - struct conf *conf = isns->i_conf; - uint32_t error; - - isns_req req(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT); + isns_req req(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT, "deregister"); req.add_str(32, TAILQ_FIRST(&conf->conf_targets)->t_name); req.add_delim(); req.add_str(1, hostname); - if (!req.send(s)) { - log_warn("send(2) failed for %s", isns->i_addr); - return; - } - if (!req.receive(s)) { - log_warn("receive(2) failed for %s", isns->i_addr); - return; - } - error = req.get_status(); - if (error != 0) { - log_warnx("iSNS deregister error %d for %s", error, isns->i_addr); - } + return (req); } void -isns_register(struct isns *isns, struct isns *oldisns) +isns_register_targets(struct conf *conf, struct isns *isns, + struct conf *oldconf) { - struct conf *conf = isns->i_conf; - int error, s; + int error; char hostname[256]; if (TAILQ_EMPTY(&conf->conf_targets) || conf->conf_portal_groups.empty()) return; set_timeout(conf->conf_isns_timeout, false); - s = isns_do_connect(isns); - if (s < 0) { + freebsd::fd_up s = isns->connect(); + if (!s) { set_timeout(0, false); return; } @@ -949,27 +904,26 @@ isns_register(struct isns *isns, struct isns *oldisns) if (error != 0) log_err(1, "gethostname"); - if (oldisns == NULL || TAILQ_EMPTY(&oldisns->i_conf->conf_targets)) - oldisns = isns; - isns_do_deregister(oldisns, s, hostname); - isns_do_register(isns, s, hostname); - close(s); + if (oldconf == NULL || TAILQ_EMPTY(&oldconf->conf_targets)) + oldconf = conf; + isns->send_request(s, isns_deregister_request(oldconf, hostname)); + isns->send_request(s, isns_register_request(conf, hostname)); + s.reset(); set_timeout(0, false); } void -isns_check(struct isns *isns) +isns_check(struct conf *conf, struct isns *isns) { - struct conf *conf = isns->i_conf; - int error, s; + int error; char hostname[256]; if (TAILQ_EMPTY(&conf->conf_targets) || conf->conf_portal_groups.empty()) return; set_timeout(conf->conf_isns_timeout, false); - s = isns_do_connect(isns); - if (s < 0) { + freebsd::fd_up s = isns->connect(); + if (!s) { set_timeout(0, false); return; } @@ -977,34 +931,33 @@ isns_check(struct isns *isns) if (error != 0) log_err(1, "gethostname"); - if (!isns_do_check(isns, s, hostname)) { - isns_do_deregister(isns, s, hostname); - isns_do_register(isns, s, hostname); + if (!isns->send_request(s, isns_check_request(conf, hostname))) { + isns->send_request(s, isns_deregister_request(conf, hostname)); + isns->send_request(s, isns_register_request(conf, hostname)); } - close(s); + s.reset(); set_timeout(0, false); } void -isns_deregister(struct isns *isns) +isns_deregister_targets(struct conf *conf, struct isns *isns) { - struct conf *conf = isns->i_conf; - int error, s; + int error; char hostname[256]; if (TAILQ_EMPTY(&conf->conf_targets) || conf->conf_portal_groups.empty()) return; set_timeout(conf->conf_isns_timeout, false); - s = isns_do_connect(isns); - if (s < 0) + freebsd::fd_up s = isns->connect(); + if (!s) return; error = gethostname(hostname, sizeof(hostname)); if (error != 0) log_err(1, "gethostname"); - isns_do_deregister(isns, s, hostname); - close(s); + isns->send_request(s, isns_deregister_request(conf, hostname)); + s.reset(); set_timeout(0, false); } @@ -1608,7 +1561,6 @@ static int conf_apply(struct conf *oldconf, struct conf *newconf) { struct lun *oldlun, *newlun, *tmplun; - struct isns *oldns, *newns; int changed, cumulated_error = 0, error; if (oldconf->conf_debug != newconf->conf_debug) { @@ -1653,13 +1605,9 @@ conf_apply(struct conf *oldconf, struct conf *newconf) } /* Deregister on removed iSNS servers. */ - TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) { - TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) { - if (strcmp(oldns->i_addr, newns->i_addr) == 0) - break; - } - if (newns == NULL) - isns_deregister(oldns); + for (auto &kv : oldconf->conf_isns) { + if (newconf->conf_isns.count(kv.first) == 0) + isns_deregister_targets(oldconf, &kv.second); } /* @@ -1856,16 +1804,16 @@ conf_apply(struct conf *oldconf, struct conf *newconf) } /* (Re-)Register on remaining/new iSNS servers. */ - TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) { - TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) { - if (strcmp(oldns->i_addr, newns->i_addr) == 0) - break; - } - isns_register(newns, oldns); + for (auto &kv : newconf->conf_isns) { + auto it = oldconf->conf_isns.find(kv.first); + if (it == oldconf->conf_isns.end()) + isns_register_targets(newconf, &kv.second, nullptr); + else + isns_register_targets(newconf, &kv.second, oldconf); } /* Schedule iSNS update */ - if (!TAILQ_EMPTY(&newconf->conf_isns)) + if (!newconf->conf_isns.empty()) set_timeout((newconf->conf_isns_period + 2) / 3, false); return (cumulated_error); @@ -2316,7 +2264,6 @@ main(int argc, char **argv) { struct kports kports; struct conf *oldconf, *newconf, *tmpconf; - struct isns *newns; const char *config_path = DEFAULT_CONFIG_PATH; int debug = 0, ch, error; pid_t otherpid; @@ -2416,7 +2363,7 @@ main(int argc, char **argv) pidfile_write(newconf->conf_pidfh); /* Schedule iSNS update */ - if (!TAILQ_EMPTY(&newconf->conf_isns)) + if (!newconf->conf_isns.empty()) set_timeout((newconf->conf_isns_period + 2) / 3, false); for (;;) { @@ -2475,10 +2422,11 @@ main(int argc, char **argv) assert(nchildren >= 0); if (timed_out()) { set_timeout(0, false); - TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) - isns_check(newns); + for (auto &kv : newconf->conf_isns) + isns_check(newconf, &kv.second); + /* Schedule iSNS update */ - if (!TAILQ_EMPTY(&newconf->conf_isns)) { + if (!newconf->conf_isns.empty()) { set_timeout((newconf->conf_isns_period + 2) / 3, false); diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh index afd49d172d15..5ccb24160eac 100644 --- a/usr.sbin/ctld/ctld.hh +++ b/usr.sbin/ctld/ctld.hh @@ -57,6 +57,7 @@ #define MAX_LUNS 1024 #define SOCKBUF_SIZE 1048576 +struct isns_req; struct port; struct auth { @@ -333,10 +334,17 @@ struct target { }; struct isns { - TAILQ_ENTRY(isns) i_next; - struct conf *i_conf; - char *i_addr; - struct addrinfo *i_ai; + isns(std::string_view addr, freebsd::addrinfo_up ai) : + i_addr(addr), i_ai(std::move(ai)) {} + + const char *addr() const { return i_addr.c_str(); } + + freebsd::fd_up connect(); + bool send_request(int s, struct isns_req req); + +private: + std::string i_addr; + freebsd::addrinfo_up i_ai; }; struct conf { @@ -348,7 +356,7 @@ struct conf { std::unordered_map<std::string, auth_group_sp> conf_auth_groups; std::unordered_map<std::string, std::unique_ptr<port>> conf_ports; std::unordered_map<std::string, portal_group_up> conf_portal_groups; - TAILQ_HEAD(, isns) conf_isns; + std::unordered_map<std::string, isns> conf_isns; int conf_isns_period; int conf_isns_timeout; int conf_debug; @@ -439,10 +447,11 @@ struct portal_group *portal_group_new(struct conf *conf, const char *name); struct portal_group *portal_group_find(struct conf *conf, const char *name); bool isns_new(struct conf *conf, const char *addr); -void isns_delete(struct isns *is); -void isns_register(struct isns *isns, struct isns *oldisns); -void isns_check(struct isns *isns); -void isns_deregister(struct isns *isns); +void isns_check(struct conf *conf, struct isns *isns); +void isns_deregister_targets(struct conf *conf, + struct isns *isns); +void isns_register_targets(struct conf *conf, + struct isns *isns, struct conf *oldconf); bool port_new(struct conf *conf, struct target *target, struct portal_group *pg, auth_group_sp ag); diff --git a/usr.sbin/ctld/isns.cc b/usr.sbin/ctld/isns.cc index 9e27999d2bf9..9877a4bc000d 100644 --- a/usr.sbin/ctld/isns.cc +++ b/usr.sbin/ctld/isns.cc @@ -43,7 +43,8 @@ #include "ctld.hh" #include "isns.hh" -isns_req::isns_req(uint16_t func, uint16_t flags) +isns_req::isns_req(uint16_t func, uint16_t flags, const char *descr) + : ir_descr(descr) { struct isns_hdr hdr; diff --git a/usr.sbin/ctld/isns.hh b/usr.sbin/ctld/isns.hh index 79a288f7d133..08a479626338 100644 --- a/usr.sbin/ctld/isns.hh +++ b/usr.sbin/ctld/isns.hh @@ -71,7 +71,9 @@ struct isns_tlv { struct isns_req { isns_req() {} - isns_req(uint16_t func, uint16_t flags); + isns_req(uint16_t func, uint16_t flags, const char *descr); + + const char *descr() const { return ir_descr; } void add(uint32_t tag, uint32_t len, const void *value); void add_delim(); @@ -87,6 +89,7 @@ private: void append(const void *buf, size_t len); std::vector<char> ir_buf; + const char *ir_descr; }; #endif /* __ISNS_HH__ */