git: 6acc7afa34aa - main - ctld: Convert struct port to a hierarchy of C++ classes
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 04 Aug 2025 19:46:56 UTC
The branch main has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=6acc7afa34aa5da8d9132e927f2026e594e73701
commit 6acc7afa34aa5da8d9132e927f2026e594e73701
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-08-04 19:38:07 +0000
Commit: John Baldwin <jhb@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 ***