The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=6acc7afa34aa5da8d9132e927f2026e594e73701
commit 6acc7afa34aa5da8d9132e927f2026e594e73701 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 port to a hierarchy of C++ classes The existing C struct port was used to describe three types of ports: iSCSI ports associated with a portal_group, ioctl ports, and "physical" ports associated with a kernel device. This change chooses to split these out into separate sub-classes of an abstract port base class. Virtual methods are used in a few places such as sending the class-specific CTL ioctls for creating and removing CTL kernel ports. For ownership purposes, a struct conf instance "owns" each port via a std::unique_ptr<> in a std::unordered_map<> indexed by name. Other objects such as targets and portal_groups can also contain collections of ports (targets hold a std::list of pointers, portal groups hold a std::unordered_map<> indexed by target names). One not-so-straightforward case is that if a new port fails to register, it is removed from the configuration. In that case, these other references also have to be removed explicitly. Sponsored by: Chelsio Communications Pull Request: https://github.com/freebsd/freebsd-src/pull/1794 --- usr.sbin/ctld/conf.cc | 5 +- usr.sbin/ctld/ctld.cc | 332 ++++++++++++++++++++----------------------- usr.sbin/ctld/ctld.hh | 112 ++++++++++----- usr.sbin/ctld/discovery.cc | 24 ++-- usr.sbin/ctld/kernel.cc | 342 ++++++++++++++++++++++++--------------------- usr.sbin/ctld/login.cc | 6 +- 6 files changed, 435 insertions(+), 386 deletions(-) diff --git a/usr.sbin/ctld/conf.cc b/usr.sbin/ctld/conf.cc index a30bf72c0469..2bf7b99409de 100644 --- a/usr.sbin/ctld/conf.cc +++ b/usr.sbin/ctld/conf.cc @@ -571,7 +571,6 @@ target_add_portal_group(const char *pg_name, const char *ag_name) { struct portal_group *pg; auth_group_sp ag; - struct port *p; pg = portal_group_find(conf, pg_name); if (pg == NULL) { @@ -589,13 +588,11 @@ target_add_portal_group(const char *pg_name, const char *ag_name) } } - p = port_new(conf, target, pg); - if (p == NULL) { + if (!port_new(conf, target, pg, std::move(ag))) { log_warnx("can't link portal-group \"%s\" to target \"%s\"", pg_name, target->t_name); return (false); } - p->p_auth_group = std::move(ag); return (true); } diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc index 07592a07c019..e8770cb9315d 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_ports); TAILQ_INIT(&conf->conf_portal_groups); TAILQ_INIT(&conf->conf_isns); @@ -134,7 +133,6 @@ conf_delete(struct conf *conf) portal_group_delete(pg); TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp) isns_delete(is); - assert(TAILQ_EMPTY(&conf->conf_ports)); free(conf->conf_pidfile_path); delete conf; } @@ -455,7 +453,6 @@ portal_group_new(struct conf *conf, const char *name) pg = new portal_group(); pg->pg_name = checked_strdup(name); pg->pg_options = nvlist_create(0); - TAILQ_INIT(&pg->pg_ports); pg->pg_conf = conf; pg->pg_tag = 0; /* Assigned later in conf_apply(). */ pg->pg_dscp = -1; @@ -468,10 +465,6 @@ portal_group_new(struct conf *conf, const char *name) void portal_group_delete(struct portal_group *pg) { - struct port *port, *tport; - - TAILQ_FOREACH_SAFE(port, &pg->pg_ports, p_pgs, tport) - port_delete(port); TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next); nvlist_destroy(pg->pg_options); @@ -625,7 +618,6 @@ isns_do_register(struct isns *isns, int s, const char *hostname) struct conf *conf = isns->i_conf; struct target *target; struct portal_group *pg; - struct port *port; uint32_t error; isns_req req(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT); @@ -647,8 +639,9 @@ isns_do_register(struct isns *isns, int s, const char *hostname) req.add_32(33, 1); /* 1 -- Target*/ if (target->t_alias != NULL) req.add_str(34, target->t_alias); - TAILQ_FOREACH(port, &target->t_ports, p_ts) { - if ((pg = port->p_portal_group) == NULL) + for (const port *port : target->t_ports) { + pg = port->portal_group(); + if (pg == nullptr) continue; req.add_32(51, pg->pg_tag); for (const portal_up &portal : pg->pg_portals) { @@ -801,12 +794,6 @@ isns_deregister(struct isns *isns) set_timeout(0, false); } -pport::~pport() -{ - if (pp_port != nullptr) - port_delete(pp_port); -} - bool kports::add_port(const char *name, uint32_t ctl_port) { @@ -834,151 +821,129 @@ kports::find_port(std::string_view name) return (&it->second); } -struct port * -port_new(struct conf *conf, struct target *target, struct portal_group *pg) -{ - struct port *port; - char *name; - int ret; - - ret = asprintf(&name, "%s-%s", pg->pg_name, target->t_name); - if (ret <= 0) - log_err(1, "asprintf"); - if (port_find(conf, name) != NULL) { - log_warnx("duplicate port \"%s\"", name); - free(name); - return (NULL); - } - port = new struct port(); - port->p_conf = conf; - port->p_name = name; - TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next); - TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts); - port->p_target = target; - TAILQ_INSERT_TAIL(&pg->pg_ports, port, p_pgs); - port->p_portal_group = pg; - return (port); +port::port(struct target *target) : + p_target(target) +{ + target->t_ports.push_back(this); } -struct port * -port_new_ioctl(struct conf *conf, struct kports &kports, struct target *target, - int pp, int vp) +void +port::clear_references() { - struct pport *pport; - struct port *port; - char *pname; - char *name; - int ret; - - ret = asprintf(&pname, "ioctl/%d/%d", pp, vp); - if (ret <= 0) { - log_err(1, "asprintf"); - return (NULL); - } - - pport = kports.find_port(pname); - if (pport != NULL) { - free(pname); - return (port_new_pp(conf, target, pport)); - } - - ret = asprintf(&name, "%s-%s", pname, target->t_name); - free(pname); + p_target->t_ports.remove(this); +} - if (ret <= 0) - log_err(1, "asprintf"); - if (port_find(conf, name) != NULL) { - log_warnx("duplicate port \"%s\"", name); - free(name); - return (NULL); - } - port = new struct port(); - port->p_conf = conf; - port->p_name = name; - port->p_ioctl_port = true; - port->p_ioctl_pp = pp; - port->p_ioctl_vp = vp; - TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next); - TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts); - port->p_target = target; - return (port); +portal_group_port::portal_group_port(struct target *target, + struct portal_group *pg, auth_group_sp ag) : + port(target), p_auth_group(ag), p_portal_group(pg) +{ + pg->pg_ports.emplace(target->t_name, this); } -struct port * -port_new_pp(struct conf *conf, struct target *target, struct pport *pp) +portal_group_port::portal_group_port(struct target *target, + struct portal_group *pg, uint32_t ctl_port) : + port(target), p_portal_group(pg) { - struct port *port; - char *name; - int ret; + p_ctl_port = ctl_port; + pg->pg_ports.emplace(target->t_name, this); +} - ret = asprintf(&name, "%s-%s", pp->name(), target->t_name); - if (ret <= 0) - log_err(1, "asprintf"); - if (port_find(conf, name) != NULL) { - log_warnx("duplicate port \"%s\"", name); - free(name); - return (NULL); - } - port = new struct port(); - port->p_conf = conf; - port->p_name = name; - TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next); - TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts); - port->p_target = target; - pp->link(port); - return (port); +bool +portal_group_port::is_dummy() const +{ + if (p_portal_group->pg_foreign) + return (true); + if (p_portal_group->pg_portals.empty()) + return (true); + return (false); } -struct port * -port_find(const struct conf *conf, const char *name) +void +portal_group_port::clear_references() { - struct port *port; + auto it = p_portal_group->pg_ports.find(p_target->t_name); + p_portal_group->pg_ports.erase(it); + port::clear_references(); +} - TAILQ_FOREACH(port, &conf->conf_ports, p_next) { - if (strcasecmp(port->p_name, name) == 0) - return (port); +bool +port_new(struct conf *conf, struct target *target, struct portal_group *pg, + auth_group_sp ag) +{ + std::string name = freebsd::stringf("%s-%s", pg->pg_name, + target->t_name); + const auto &pair = conf->conf_ports.try_emplace(name, + std::make_unique<portal_group_port>(target, pg, ag)); + if (!pair.second) { + log_warnx("duplicate port \"%s\"", name.c_str()); + return (false); } - return (NULL); + return (true); } -struct port * -port_find_in_pg(const struct portal_group *pg, const char *target) +bool +port_new(struct conf *conf, struct target *target, struct portal_group *pg, + uint32_t ctl_port) { - struct port *port; - - TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) { - if (strcasecmp(port->p_target->t_name, target) == 0) - return (port); + std::string name = freebsd::stringf("%s-%s", pg->pg_name, + target->t_name); + const auto &pair = conf->conf_ports.try_emplace(name, + std::make_unique<portal_group_port>(target, pg, ctl_port)); + if (!pair.second) { + log_warnx("duplicate port \"%s\"", name.c_str()); + return (false); } - return (NULL); + return (true); } -void -port_delete(struct port *port) +static bool +port_new_pp(struct conf *conf, struct target *target, struct pport *pp) { + std::string name = freebsd::stringf("%s-%s", pp->name(), + target->t_name); + const auto &pair = conf->conf_ports.try_emplace(name, + std::make_unique<kernel_port>(target, pp)); + if (!pair.second) { + log_warnx("duplicate port \"%s\"", name.c_str()); + return (false); + } - if (port->p_portal_group) - TAILQ_REMOVE(&port->p_portal_group->pg_ports, port, p_pgs); - if (port->p_target) - TAILQ_REMOVE(&port->p_target->t_ports, port, p_ts); - TAILQ_REMOVE(&port->p_conf->conf_ports, port, p_next); - free(port->p_name); - free(port); + pp->link(); + return (true); } -bool -port_is_dummy(struct port *port) +static bool +port_new_ioctl(struct conf *conf, struct kports &kports, struct target *target, + int pp, int vp) { + struct pport *pport; - if (port->p_portal_group) { - if (port->p_portal_group->pg_foreign) - return (true); - if (port->p_portal_group->pg_portals.empty()) - return (true); + std::string pname = freebsd::stringf("ioctl/%d/%d", pp, vp); + + pport = kports.find_port(pname); + if (pport != NULL) + return (port_new_pp(conf, target, pport)); + + std::string name = pname + "-" + target->t_name; + const auto &pair = conf->conf_ports.try_emplace(name, + std::make_unique<ioctl_port>(target, pp, vp)); + if (!pair.second) { + log_warnx("duplicate port \"%s\"", name.c_str()); + return (false); } - return (false); + + return (true); +} + +struct port * +port_find_in_pg(const struct portal_group *pg, const char *target) +{ + auto it = pg->pg_ports.find(target); + if (it == pg->pg_ports.end()) + return (nullptr); + return (it->second); } struct target * @@ -1006,7 +971,6 @@ target_new(struct conf *conf, const char *name) targ->t_name[i] = tolower(targ->t_name[i]); targ->t_conf = conf; - TAILQ_INIT(&targ->t_ports); TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next); return (targ); @@ -1015,10 +979,6 @@ target_new(struct conf *conf, const char *name) void target_delete(struct target *targ) { - struct port *port, *tport; - - TAILQ_FOREACH_SAFE(port, &targ->t_ports, p_ts, tport) - port_delete(port); TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next); free(targ->t_pport); @@ -1261,10 +1221,10 @@ conf_verify(struct conf *conf) "default"); assert(targ->t_auth_group != NULL); } - if (TAILQ_EMPTY(&targ->t_ports)) { + if (targ->t_ports.empty()) { pg = portal_group_find(conf, "default"); assert(pg != NULL); - port_new(conf, targ, pg); + port_new(conf, targ, pg, nullptr); } found = false; for (i = 0; i < MAX_LUNS; i++) { @@ -1293,14 +1253,14 @@ conf_verify(struct conf *conf) pg->pg_discovery_filter = PG_FILTER_NONE; if (pg->pg_redirection != NULL) { - if (!TAILQ_EMPTY(&pg->pg_ports)) { + if (!pg->pg_ports.empty()) { log_debugx("portal-group \"%s\" assigned " "to target, but configured " "for redirection", pg->pg_name); } pg->pg_unassigned = false; - } else if (!TAILQ_EMPTY(&pg->pg_ports)) { + } else if (!pg->pg_ports.empty()) { pg->pg_unassigned = false; } else { if (strcmp(pg->pg_name, "default") != 0) @@ -1453,7 +1413,6 @@ conf_apply(struct conf *oldconf, struct conf *newconf) { struct lun *oldlun, *newlun, *tmplun; struct portal_group *oldpg, *newpg; - struct port *oldport, *newport, *tmpport; struct isns *oldns, *newns; int changed, cumulated_error = 0, error; @@ -1517,17 +1476,19 @@ conf_apply(struct conf *oldconf, struct conf *newconf) * First, remove any ports present in the old configuration * and missing in the new one. */ - TAILQ_FOREACH_SAFE(oldport, &oldconf->conf_ports, p_next, tmpport) { - if (port_is_dummy(oldport)) + for (const auto &kv : oldconf->conf_ports) { + const std::string &name = kv.first; + port *oldport = kv.second.get(); + + if (oldport->is_dummy()) continue; - newport = port_find(newconf, oldport->p_name); - if (newport != NULL && !port_is_dummy(newport)) + const auto it = newconf->conf_ports.find(name); + if (it != newconf->conf_ports.end() && + !it->second->is_dummy()) continue; - log_debugx("removing port \"%s\"", oldport->p_name); - error = kernel_port_remove(oldport); - if (error != 0) { - log_warnx("failed to remove port %s", - oldport->p_name); + log_debugx("removing port \"%s\"", name.c_str()); + if (!oldport->kernel_remove()) { + log_warnx("failed to remove port %s", name.c_str()); /* * XXX: Uncomment after fixing the root cause. * @@ -1640,30 +1601,46 @@ conf_apply(struct conf *oldconf, struct conf *newconf) /* * Now add new ports or modify existing ones. */ - TAILQ_FOREACH_SAFE(newport, &newconf->conf_ports, p_next, tmpport) { - if (port_is_dummy(newport)) - continue; - oldport = port_find(oldconf, newport->p_name); + for (auto it = newconf->conf_ports.begin(); + it != newconf->conf_ports.end(); ) { + const std::string &name = it->first; + port *newport = it->second.get(); - if (oldport == NULL || port_is_dummy(oldport)) { - log_debugx("adding port \"%s\"", newport->p_name); - error = kernel_port_add(newport); - } else { - log_debugx("updating port \"%s\"", newport->p_name); - newport->p_ctl_port = oldport->p_ctl_port; - error = kernel_port_update(newport, oldport); + if (newport->is_dummy()) { + it++; + continue; } - if (error != 0) { - log_warnx("failed to %s port %s", - (oldport == NULL) ? "add" : "update", - newport->p_name); - if (oldport == NULL || port_is_dummy(oldport)) - port_delete(newport); - /* - * XXX: Uncomment after fixing the root cause. - * - * cumulated_error++; - */ + const auto oldit = oldconf->conf_ports.find(name); + if (oldit == oldconf->conf_ports.end() || + oldit->second->is_dummy()) { + log_debugx("adding port \"%s\"", name.c_str()); + if (!newport->kernel_add()) { + log_warnx("failed to add port %s", + name.c_str()); + + /* + * XXX: Uncomment after fixing the + * root cause. + * + * cumulated_error++; + */ + + /* + * conf "owns" the port, but other + * objects contain pointers to this + * port that must be removed before + * deleting the port. + */ + newport->clear_references(); + it = newconf->conf_ports.erase(it); + } else + it++; + } else { + log_debugx("updating port \"%s\"", name.c_str()); + if (!newport->kernel_update(oldit->second.get())) + log_warnx("failed to update port %s", + name.c_str()); + it++; } } @@ -2134,7 +2111,6 @@ new_pports_from_conf(struct conf *conf, struct kports &kports) { struct target *targ; struct pport *pp; - struct port *tp; int ret, i_pp, i_vp; TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { @@ -2143,8 +2119,7 @@ new_pports_from_conf(struct conf *conf, struct kports &kports) ret = sscanf(targ->t_pport, "ioctl/%d/%d", &i_pp, &i_vp); if (ret > 0) { - tp = port_new_ioctl(conf, kports, targ, i_pp, i_vp); - if (tp == NULL) { + if (!port_new_ioctl(conf, kports, targ, i_pp, i_vp)) { log_warnx("can't create new ioctl port " "for target \"%s\"", targ->t_name); return (false); @@ -2165,8 +2140,7 @@ new_pports_from_conf(struct conf *conf, struct kports &kports) targ->t_pport, targ->t_name); return (false); } - tp = port_new_pp(conf, targ, pp); - if (tp == NULL) { + if (!port_new_pp(conf, targ, pp)) { log_warnx("can't link port \"%s\" to target \"%s\"", targ->t_pport, targ->t_name); return (false); diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh index ee50acf1f3e8..3d9c30b31977 100644 --- a/usr.sbin/ctld/ctld.hh +++ b/usr.sbin/ctld/ctld.hh @@ -57,6 +57,8 @@ #define MAX_LUNS 1024 #define SOCKBUF_SIZE 1048576 +struct port; + struct auth { auth(std::string_view secret) : a_secret(secret) {} auth(std::string_view secret, std::string_view mutual_user, @@ -168,7 +170,7 @@ struct portal_group { bool pg_foreign = false; bool pg_unassigned = false; std::list<portal_up> pg_portals; - TAILQ_HEAD(, port) pg_ports; + std::unordered_map<std::string, port *> pg_ports; char *pg_offload = nullptr; char *pg_redirection = nullptr; int pg_dscp; @@ -178,22 +180,79 @@ struct portal_group { }; struct port { - TAILQ_ENTRY(port) p_next; - TAILQ_ENTRY(port) p_pgs; - TAILQ_ENTRY(port) p_ts; - struct conf *p_conf; - char *p_name; - auth_group_sp p_auth_group; - struct portal_group *p_portal_group = nullptr; - struct pport *p_pport = nullptr; + port(struct target *target); + virtual ~port() = default; + + struct target *target() const { return p_target; } + virtual struct auth_group *auth_group() const { return nullptr; } + virtual struct portal_group *portal_group() const { return nullptr; } + + virtual bool is_dummy() const { return true; } + + virtual void clear_references(); + + bool kernel_add(); + bool kernel_update(const port *oport); + bool kernel_remove(); + + virtual bool kernel_create_port() = 0; + virtual bool kernel_remove_port() = 0; + +protected: struct target *p_target; - bool p_ioctl_port = false; - int p_ioctl_pp = 0; - int p_ioctl_vp = 0; uint32_t p_ctl_port = 0; }; +struct portal_group_port final : public port { + portal_group_port(struct target *target, struct portal_group *pg, + auth_group_sp ag); + portal_group_port(struct target *target, struct portal_group *pg, + uint32_t ctl_port); + ~portal_group_port() override = default; + + struct auth_group *auth_group() const override + { return p_auth_group.get(); } + struct portal_group *portal_group() const override + { return p_portal_group; } + + bool is_dummy() const override; + + void clear_references() override; + + bool kernel_create_port() override; + bool kernel_remove_port() override; + +private: + auth_group_sp p_auth_group; + struct portal_group *p_portal_group; +}; + +struct ioctl_port final : public port { + ioctl_port(struct target *target, int pp, int vp) : + port(target), p_ioctl_pp(pp), p_ioctl_vp(vp) {} + ~ioctl_port() override = default; + + bool kernel_create_port() override; + bool kernel_remove_port() override; + +private: + int p_ioctl_pp; + int p_ioctl_vp; +}; + +struct kernel_port final : public port { + kernel_port(struct target *target, struct pport *pp) : + port(target), p_pport(pp) {} + ~kernel_port() override = default; + + bool kernel_create_port() override; + bool kernel_remove_port() override; + +private: + struct pport *p_pport; +}; + struct lun { TAILQ_ENTRY(lun) l_next; struct conf *l_conf; @@ -216,7 +275,7 @@ struct target { struct conf *t_conf; struct lun *t_luns[MAX_LUNS] = {}; auth_group_sp t_auth_group; - TAILQ_HEAD(, port) t_ports; + std::list<port *> t_ports; char *t_name; char *t_alias; char *t_redirection; @@ -237,7 +296,7 @@ struct conf { TAILQ_HEAD(, lun) conf_luns; TAILQ_HEAD(, target) conf_targets; std::unordered_map<std::string, auth_group_sp> conf_auth_groups; - TAILQ_HEAD(, port) conf_ports; + std::unordered_map<std::string, std::unique_ptr<port>> conf_ports; TAILQ_HEAD(, portal_group) conf_portal_groups; TAILQ_HEAD(, isns) conf_isns; int conf_isns_period; @@ -264,19 +323,17 @@ private: struct pport { pport(std::string_view name, uint32_t ctl_port) : pp_name(name), pp_ctl_port(ctl_port) {} - ~pport(); const char *name() const { return pp_name.c_str(); } uint32_t ctl_port() const { return pp_ctl_port; } - bool linked() const { return pp_port != nullptr; } - void link(struct port *port) { pp_port = port; } + bool linked() const { return pp_linked; } + void link() { pp_linked = true; } private: - struct port *pp_port; std::string pp_name; - uint32_t pp_ctl_port; + bool pp_linked; }; struct kports { @@ -341,18 +398,12 @@ void isns_register(struct isns *isns, struct isns *oldisns); void isns_check(struct isns *isns); void isns_deregister(struct isns *isns); -struct port *port_new(struct conf *conf, struct target *target, - struct portal_group *pg); -struct port *port_new_ioctl(struct conf *conf, - struct kports &kports, struct target *target, - int pp, int vp); -struct port *port_new_pp(struct conf *conf, struct target *target, - struct pport *pp); -struct port *port_find(const struct conf *conf, const char *name); +bool port_new(struct conf *conf, struct target *target, + struct portal_group *pg, auth_group_sp ag); +bool port_new(struct conf *conf, struct target *target, + struct portal_group *pg, uint32_t ctl_port); struct port *port_find_in_pg(const struct portal_group *pg, const char *target); -void port_delete(struct port *port); -bool port_is_dummy(struct port *port); struct target *target_new(struct conf *conf, const char *name); void target_delete(struct target *target); @@ -372,9 +423,6 @@ int kernel_lun_add(struct lun *lun); int kernel_lun_modify(struct lun *lun); int kernel_lun_remove(struct lun *lun); void kernel_handoff(struct ctld_connection *conn); -int kernel_port_add(struct port *port); -int kernel_port_update(struct port *port, struct port *old); -int kernel_port_remove(struct port *port); void kernel_capsicate(void); #ifdef ICL_KERNEL_PROXY diff --git a/usr.sbin/ctld/discovery.cc b/usr.sbin/ctld/discovery.cc index 59bdadb29eb2..d52d4919ddc5 100644 --- a/usr.sbin/ctld/discovery.cc +++ b/usr.sbin/ctld/discovery.cc @@ -101,17 +101,17 @@ logout_new_response(struct pdu *request) static void discovery_add_target(struct keys *response_keys, const struct target *targ) { - struct port *port; char *buf; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; const struct addrinfo *ai; int ret; keys_add(response_keys, "TargetName", targ->t_name); - TAILQ_FOREACH(port, &targ->t_ports, p_ts) { - if (port->p_portal_group == NULL) + for (const port *port : targ->t_ports) { + const struct portal_group *pg = port->portal_group(); + if (pg == nullptr) continue; - for (portal_up &portal : port->p_portal_group->pg_portals) { + for (const portal_up &portal : pg->pg_portals) { ai = portal->ai(); ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), @@ -125,13 +125,13 @@ discovery_add_target(struct keys *response_keys, const struct target *targ) if (strcmp(hbuf, "0.0.0.0") == 0) continue; ret = asprintf(&buf, "%s:%s,%d", hbuf, sbuf, - port->p_portal_group->pg_tag); + pg->pg_tag); break; case AF_INET6: if (strcmp(hbuf, "::") == 0) continue; ret = asprintf(&buf, "[%s]:%s,%d", hbuf, sbuf, - port->p_portal_group->pg_tag); + pg->pg_tag); break; default: continue; @@ -154,8 +154,8 @@ discovery_target_filtered_out(const struct ctld_connection *conn, const struct auth *auth; int error; - targ = port->p_target; - ag = port->p_auth_group.get(); + targ = port->target(); + ag = port->auth_group(); if (ag == nullptr) ag = targ->t_auth_group.get(); pg = conn->conn_portal->portal_group(); @@ -228,12 +228,13 @@ discovery(struct ctld_connection *conn) response_keys = keys_new(); if (strcmp(send_targets, "All") == 0) { - TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) { + for (const auto &kv : pg->pg_ports) { + port = kv.second; if (discovery_target_filtered_out(conn, port)) { /* Ignore this target. */ continue; } - discovery_add_target(response_keys, port->p_target); + discovery_add_target(response_keys, port->target()); } } else { port = port_find_in_pg(pg, send_targets); @@ -244,7 +245,8 @@ discovery(struct ctld_connection *conn) if (discovery_target_filtered_out(conn, port)) { /* Ignore this target. */ } else { - discovery_add_target(response_keys, port->p_target); + discovery_add_target(response_keys, + port->target()); } } } diff --git a/usr.sbin/ctld/kernel.cc b/usr.sbin/ctld/kernel.cc index eb3bfa1dc760..2325895a31fd 100644 --- a/usr.sbin/ctld/kernel.cc +++ b/usr.sbin/ctld/kernel.cc @@ -401,7 +401,6 @@ conf_new_from_kernel(struct kports &kports) struct conf *conf = NULL; struct target *targ; struct portal_group *pg; - struct port *cp; struct lun *cl; struct ctl_lun_list list; struct cctl_devlist_data devlist; @@ -575,12 +574,10 @@ retry_port: } } pg->pg_tag = port->cfiscsi_portal_group_tag; - cp = port_new(conf, targ, pg); - if (cp == NULL) { + if (!port_new(conf, targ, pg, port->port_id)) { log_warnx("port_new failed"); continue; } - cp->p_ctl_port = port->port_id; } while ((port = STAILQ_FIRST(&devlist.port_list))) { STAILQ_REMOVE_HEAD(&devlist.port_list, links); @@ -895,100 +892,118 @@ kernel_handoff(struct ctld_connection *conn) } } -int -kernel_port_add(struct port *port) +static bool +ctl_create_port(const char *driver, const nvlist_t *nvl, uint32_t *ctl_port) { - struct ctl_port_entry entry; struct ctl_req req; - struct ctl_lun_map lm; - struct target *targ = port->p_target; - struct portal_group *pg = port->p_portal_group; char result_buf[NVLIST_BUFSIZE]; - int error, i; + int error; - /* Create iSCSI port. */ - if (port->p_portal_group || port->p_ioctl_port) { - bzero(&req, sizeof(req)); - req.reqtype = CTL_REQ_CREATE; - - if (port->p_portal_group) { - strlcpy(req.driver, "iscsi", sizeof(req.driver)); - req.args_nvl = nvlist_clone(pg->pg_options); - nvlist_add_string(req.args_nvl, "cfiscsi_target", - targ->t_name); - nvlist_add_string(req.args_nvl, - "ctld_portal_group_name", pg->pg_name); - nvlist_add_stringf(req.args_nvl, - "cfiscsi_portal_group_tag", "%u", pg->pg_tag); - - if (targ->t_alias) { - nvlist_add_string(req.args_nvl, - "cfiscsi_target_alias", targ->t_alias); - } - } + bzero(&req, sizeof(req)); + req.reqtype = CTL_REQ_CREATE; - if (port->p_ioctl_port) { - strlcpy(req.driver, "ioctl", sizeof(req.driver)); - req.args_nvl = nvlist_create(0); - nvlist_add_stringf(req.args_nvl, "pp", "%d", - port->p_ioctl_pp); - nvlist_add_stringf(req.args_nvl, "vp", "%d", - port->p_ioctl_vp); - } + strlcpy(req.driver, driver, sizeof(req.driver)); + req.args = nvlist_pack(nvl, &req.args_len); + if (req.args == NULL) { + log_warn("error packing nvlist"); + return (false); + } - req.args = nvlist_pack(req.args_nvl, &req.args_len); - if (req.args == NULL) { - nvlist_destroy(req.args_nvl); - log_warn("error packing nvlist"); - return (1); - } + req.result = result_buf; + req.result_len = sizeof(result_buf); + error = ioctl(ctl_fd, CTL_PORT_REQ, &req); + free(req.args); - req.result = result_buf; - req.result_len = sizeof(result_buf); - error = ioctl(ctl_fd, CTL_PORT_REQ, &req); - free(req.args); - nvlist_destroy(req.args_nvl); + if (error != 0) { + log_warn("error issuing CTL_PORT_REQ ioctl"); + return (false); + } + if (req.status == CTL_LUN_ERROR) { + log_warnx("error returned from port creation request: %s", + req.error_str); + return (false); + } + if (req.status != CTL_LUN_OK) { + log_warnx("unknown port creation request status %d", + req.status); + return (false); + } - if (error != 0) { - log_warn("error issuing CTL_PORT_REQ ioctl"); - return (1); - } - if (req.status == CTL_LUN_ERROR) { - log_warnx("error returned from port creation request: %s", - req.error_str); - return (1); - } - if (req.status != CTL_LUN_OK) { - log_warnx("unknown port creation request status %d", - req.status); - return (1); - } + freebsd::nvlist_up result_nvl(nvlist_unpack(result_buf, req.result_len, + 0)); + if (result_nvl == NULL) { + log_warnx("error unpacking result nvlist"); + return (false); + } - req.result_nvl = nvlist_unpack(result_buf, req.result_len, 0); - if (req.result_nvl == NULL) { - log_warnx("error unpacking result nvlist"); - return (1); - } + *ctl_port = nvlist_get_number(result_nvl.get(), "port_id"); + return (true); +} - port->p_ctl_port = nvlist_get_number(req.result_nvl, "port_id"); - nvlist_destroy(req.result_nvl); - } else if (port->p_pport) { - port->p_ctl_port = port->p_pport->ctl_port(); - - if (strncmp(targ->t_name, "naa.", 4) == 0 && - strlen(targ->t_name) == 20) { - bzero(&entry, sizeof(entry)); - entry.port_type = CTL_PORT_NONE; *** 305 LINES SKIPPED ***