ctld: Refactor ioctl port handling

- Normalize ioctl port names when the port name is first added to
  the configuration.  This can catch potential duplicate port names
  sooner and helps with other parts of this change.

- When recognizing existing ioctl ports, always expand the name to
  include the physical and virtual port numbers.  This permits binding
  ioctl/0/0 or ioctl/1/0 to a target, for example.

- When adding physical ports to a target, first check for an existing
  kernel port to reuse.  This handles both ioctl and non-ioctl ports
  and removes the need for the conf::add_port method for ioctl ports
  to check in kports.

- If an existing kport isn't found when adding physical ports, check
  to see if the port name is an ioctl port.  If so, call conf::add_port
  to add an ioctl port.  This add_port method overload is now simpler
  as it always creates a new port.

NB: The kernel_port class handles CTL ports that already existed
before ctld started including existing ioctl ports, whereas the
ioctl_port class handles ioctl ports that are created and completely
managed by ctld.  This was true before this change but is perhaps more
obvious after this change.

Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D57092
This commit is contained in:
John Baldwin
2026-05-27 16:57:23 -04:00
parent 7a436d3789
commit caef3c50ac
3 changed files with 54 additions and 33 deletions
+47 -29
View File
@@ -1180,16 +1180,8 @@ conf::add_port(struct target *target, struct pport *pp)
}
bool
conf::add_port(struct kports &kports, struct target *target, int pp, int vp)
conf::add_port(struct target *target, const std::string &pname, int pp, int vp)
{
struct pport *pport;
std::string pname = freebsd::stringf("ioctl/%d/%d", pp, vp);
pport = kports.find_port(pname);
if (pport != NULL)
return (add_port(target, pport));
std::string name = pname + "-" + target->name();
const auto &pair = conf_ports.try_emplace(name,
std::make_unique<ioctl_port>(target, pp, vp));
@@ -1387,6 +1379,19 @@ target::set_auth_type(const char *type)
bool
target::add_physical_port(std::string_view pport)
{
/* Normalize ioctl port names. */
std::string pname;
if (pport.compare(0, strlen("ioctl/"), "ioctl/") == 0) {
int ret, pp, vp;
pname = std::string(pport);
ret = sscanf(pname.c_str(), "ioctl/%d/%d", &pp, &vp);
if (ret == 2) {
pname = freebsd::stringf("ioctl/%d/%d", pp, vp);
pport = pname;
}
}
for (const auto &s : t_pports) {
if (s == pport) {
log_warnx("duplicate physical port \"%s\" for target "
@@ -2643,36 +2648,49 @@ conf::add_pports(struct kports &kports)
struct target *targ = kv.second.get();
for (const auto &pport : targ->pports()) {
ret = sscanf(pport.c_str(), "ioctl/%d/%d", &i_pp,
&i_vp);
if (ret > 0) {
if (!add_port(kports, targ, i_pp, i_vp)) {
log_warnx("can't create new ioctl port "
"for %s", targ->label());
/*
* If this port is already present in the
* kernel, reuse the existing port.
*/
pp = kports.find_port(pport);
if (pp != nullptr) {
if (pp->linked()) {
log_warnx("can't link port \"%s\" to "
"%s, port already linked to some "
"target", pport.c_str(),
targ->label());
return (false);
}
if (!add_port(targ, pp)) {
log_warnx(
"can't link port \"%s\" to %s",
pport.c_str(), targ->label());
return (false);
}
continue;
}
/*
* If this port is an ioctl port, create a new
* port.
*/
ret = sscanf(pport.c_str(), "ioctl/%d/%d", &i_pp,
&i_vp);
if (ret == 2) {
if (!add_port(targ, pport, i_pp, i_vp)) {
log_warnx("can't create new port %s "
"for %s", pport.c_str(),
targ->label());
return (false);
}
continue;
}
pp = kports.find_port(pport);
if (pp == NULL) {
log_warnx("unknown port \"%s\" for %s",
pport.c_str(), targ->label());
return (false);
}
if (pp->linked()) {
log_warnx("can't link port \"%s\" to %s, "
"port already linked to some target",
pport.c_str(), targ->label());
return (false);
}
if (!add_port(targ, pp)) {
log_warnx("can't link port \"%s\" to %s",
pport.c_str(), targ->label());
return (false);
}
}
}
return (true);
}
+1 -1
View File
@@ -487,7 +487,7 @@ struct conf {
bool add_port(struct target *target, struct portal_group *pg,
uint32_t ctl_port);
bool add_port(struct target *target, struct pport *pp);
bool add_port(struct kports &kports, struct target *target, int pp,
bool add_port(struct target *target, const std::string &pname, int pp,
int vp);
bool add_pports(struct kports &kports);
+4 -1
View File
@@ -549,7 +549,10 @@ conf_new_from_kernel(struct kports &kports)
continue;
std::string name = port.port_name;
if (port.pp != 0 || port.vp != 0) {
if (port.port_frontend == "ioctl")
name += "/" + std::to_string(port.pp) + "/" +
std::to_string(port.vp);
else if (port.pp != 0 || port.vp != 0) {
name += "/" + std::to_string(port.pp);
if (port.vp != 0)
name += "/" + std::to_string(port.vp);