The branch stable/15 has been updated by jhb:

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

commit 8071cdf83451f112ce17da3f429c8ae86699d7e5
Author:     John Baldwin <[email protected]>
AuthorDate: 2026-04-20 17:19:25 +0000
Commit:     John Baldwin <[email protected]>
CommitDate: 2026-06-23 16:05:37 +0000

    ctld: Support multiple physical ports in a target
    
    PR:             293076
    Reported by:    Ken J. Thomson <[email protected]>
    Reviewed by:    asomers
    Fixes:          969876fcee57 ("ctld: parse config file independently of 
getting kernel info")
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D55767
    (cherry picked from commit 7bb2b3801554a58039ed9d1fd05b65ce24c6c661)
---
 usr.sbin/ctld/conf.cc     |  4 +--
 usr.sbin/ctld/conf.h      |  2 +-
 usr.sbin/ctld/ctld.cc     | 72 ++++++++++++++++++++++++-----------------------
 usr.sbin/ctld/ctld.hh     | 11 ++++----
 usr.sbin/ctld/parse.y     |  2 +-
 usr.sbin/ctld/uclparse.cc |  2 +-
 6 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/usr.sbin/ctld/conf.cc b/usr.sbin/ctld/conf.cc
index 56a149a58a25..a2c00525826b 100644
--- a/usr.sbin/ctld/conf.cc
+++ b/usr.sbin/ctld/conf.cc
@@ -404,9 +404,9 @@ target_set_auth_type(const char *type)
 }
 
 bool
-target_set_physical_port(const char *pport)
+target_add_physical_port(const char *pport)
 {
-       return (target->set_physical_port(pport));
+       return (target->add_physical_port(pport));
 }
 
 bool
diff --git a/usr.sbin/ctld/conf.h b/usr.sbin/ctld/conf.h
index 642c8f234d30..7eaee4f9871c 100644
--- a/usr.sbin/ctld/conf.h
+++ b/usr.sbin/ctld/conf.h
@@ -83,11 +83,11 @@ bool        target_add_chap_mutual(const char *user, const 
char *secret,
 bool   target_add_initiator_name(const char *name);
 bool   target_add_initiator_portal(const char *addr);
 bool   target_add_lun(u_int id, const char *name);
+bool   target_add_physical_port(const char *pport);
 bool   target_add_portal_group(const char *pg_name, const char *ag_name);
 bool   target_set_alias(const char *alias);
 bool   target_set_auth_group(const char *name);
 bool   target_set_auth_type(const char *type);
-bool   target_set_physical_port(const char *pport);
 bool   target_set_redirection(const char *addr);
 bool   target_start_lun(u_int id);
 
diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc
index 336aedd68aab..2dda88f97b73 100644
--- a/usr.sbin/ctld/ctld.cc
+++ b/usr.sbin/ctld/ctld.cc
@@ -1097,9 +1097,9 @@ kports::has_port(std::string_view name)
 }
 
 struct pport *
-kports::find_port(std::string_view name)
+kports::find_port(const std::string &name)
 {
-       auto it = pports.find(std::string(name));
+       auto it = pports.find(name);
        if (it == pports.end())
                return (nullptr);
        return (&it->second);
@@ -1398,14 +1398,16 @@ target::set_auth_type(const char *type)
 }
 
 bool
-target::set_physical_port(std::string_view pport)
+target::add_physical_port(std::string_view pport)
 {
-       if (!t_pport.empty()) {
-               log_warnx("cannot set multiple physical ports for target "
-                   "\"%s\"", name());
-               return (false);
+       for (const auto &s : t_pports) {
+               if (s == pport) {
+                       log_warnx("duplicate physical port \"%s\" for target "
+                           "\"%s\"", s.c_str(), name());
+                       return (false);
+               }
        }
-       t_pport = pport;
+       t_pports.emplace_back(pport);
        return (true);
 }
 
@@ -2634,36 +2636,36 @@ conf::add_pports(struct kports &kports)
        for (auto &kv : conf_targets) {
                struct target *targ = kv.second.get();
 
-               if (!targ->has_pport())
-                       continue;
+               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());
+                                       return (false);
+                               }
 
-               ret = sscanf(targ->pport(), "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());
-                               return (false);
+                               continue;
                        }
 
-                       continue;
-               }
-
-               pp = kports.find_port(targ->pport());
-               if (pp == NULL) {
-                       log_warnx("unknown port \"%s\" for %s",
-                           targ->pport(), targ->label());
-                       return (false);
-               }
-               if (pp->linked()) {
-                       log_warnx("can't link port \"%s\" to %s, "
-                           "port already linked to some target",
-                           targ->pport(), targ->label());
-                       return (false);
-               }
-               if (!add_port(targ, pp)) {
-                       log_warnx("can't link port \"%s\" to %s",
-                           targ->pport(), targ->label());
-                       return (false);
+                       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);
diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh
index 2e1ee7869ceb..a88ef7eac96e 100644
--- a/usr.sbin/ctld/ctld.hh
+++ b/usr.sbin/ctld/ctld.hh
@@ -383,17 +383,16 @@ struct target {
        virtual ~target() = default;
 
        bool has_alias() const { return !t_alias.empty(); }
-       bool has_pport() const { return !t_pport.empty(); }
        bool has_redirection() const { return !t_redirection.empty(); }
        const char *alias() const { return t_alias.c_str(); }
        const char *name() const { return t_name.c_str(); }
        const char *label() const { return t_label.c_str(); }
-       const char *pport() const { return t_pport.c_str(); }
        bool private_auth() const { return t_private_auth; }
        const char *redirection() const { return t_redirection.c_str(); }
 
        struct auth_group *auth_group() const { return t_auth_group.get(); }
        const std::list<port *> &ports() const { return t_ports; }
+       const std::list<std::string> &pports() const { return t_pports; }
        const struct lun *lun(int idx) const { return t_luns[idx]; }
 
        bool add_chap(const char *user, const char *secret);
@@ -405,12 +404,12 @@ struct target {
        virtual bool add_initiator_portal(const char *) { return false; }
        virtual bool add_lun(u_int, const char *) { return false; }
        virtual bool add_namespace(u_int, const char *) { return false; }
+       bool add_physical_port(std::string_view pport);
        virtual bool add_portal_group(const char *pg_name,
            const char *ag_name) = 0;
        bool set_alias(std::string_view alias);
        bool set_auth_group(const char *ag_name);
        bool set_auth_type(const char *type);
-       bool set_physical_port(std::string_view pport);
        bool set_redirection(const char *addr);
        virtual struct lun *start_lun(u_int) { return nullptr; }
        virtual struct lun *start_namespace(u_int) { return nullptr; }
@@ -435,8 +434,8 @@ protected:
        std::string                     t_label;
        std::string                     t_alias;
        std::string                     t_redirection;
-       /* Name of this target's physical port, if any, i.e. "isp0" */
-       std::string                     t_pport;
+       /* Names of this target's physical ports, e.g. "isp0" */
+       std::list<std::string>          t_pports;
        bool                            t_private_auth = false;
 };
 
@@ -584,7 +583,7 @@ private:
 struct kports {
        bool add_port(std::string &name, uint32_t ctl_port);
        bool has_port(std::string_view name);
-       struct pport *find_port(std::string_view name);
+       struct pport *find_port(const std::string &name);
 
 private:
        std::unordered_map<std::string, struct pport> pports;
diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y
index 5725c16b459a..05171d3aa159 100644
--- a/usr.sbin/ctld/parse.y
+++ b/usr.sbin/ctld/parse.y
@@ -774,7 +774,7 @@ target_port:        PORT STR
        {
                bool ok;
 
-               ok = target_set_physical_port($2);
+               ok = target_add_physical_port($2);
                free($2);
                if (!ok)
                        return (1);
diff --git a/usr.sbin/ctld/uclparse.cc b/usr.sbin/ctld/uclparse.cc
index 8a62636ffec6..0c6b2af8d741 100644
--- a/usr.sbin/ctld/uclparse.cc
+++ b/usr.sbin/ctld/uclparse.cc
@@ -1255,7 +1255,7 @@ uclparse_target(const char *name, const ucl::Ucl &top)
                                return false;
                        }
 
-                       if 
(!target_set_physical_port(obj.string_value().c_str()))
+                       if 
(!target_add_physical_port(obj.string_value().c_str()))
                                return false;
                }
 

Reply via email to