The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=caef3c50ac067ca751ba4950f310821a521ebf57

commit caef3c50ac067ca751ba4950f310821a521ebf57
Author:     John Baldwin <[email protected]>
AuthorDate: 2026-05-27 20:57:23 +0000
Commit:     John Baldwin <[email protected]>
CommitDate: 2026-05-27 20:57:23 +0000

    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
---
 usr.sbin/ctld/ctld.cc   | 80 ++++++++++++++++++++++++++++++-------------------
 usr.sbin/ctld/ctld.hh   |  2 +-
 usr.sbin/ctld/kernel.cc |  5 +++-
 3 files changed, 54 insertions(+), 33 deletions(-)

diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc
index 9bdf15976911..8b99bde14911 100644
--- a/usr.sbin/ctld/ctld.cc
+++ b/usr.sbin/ctld/ctld.cc
@@ -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,35 +2648,48 @@ 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;
                        }
 
-                       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);
+                       /*
+                        * 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;
                        }
+
+                       log_warnx("unknown port \"%s\" for %s",
+                           pport.c_str(), targ->label());
+                       return (false);
                }
        }
        return (true);
diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh
index 7ae033804157..8d63de06dd80 100644
--- a/usr.sbin/ctld/ctld.hh
+++ b/usr.sbin/ctld/ctld.hh
@@ -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);
 
diff --git a/usr.sbin/ctld/kernel.cc b/usr.sbin/ctld/kernel.cc
index 59a339e1c96b..8c5c447f3e80 100644
--- a/usr.sbin/ctld/kernel.cc
+++ b/usr.sbin/ctld/kernel.cc
@@ -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);

Reply via email to