Author: mav
Date: Thu Feb 19 14:52:01 2015
New Revision: 279006
URL: https://svnweb.freebsd.org/changeset/base/279006

Log:
  MFC r278322: Add support for multiple portal groups per target.
  
  This change allows multiple "portal-group" options to be specified per
  target.  Each of them may include new optional auth-group name parameter
  to override per-target auth parameters for specific portal group.
  
  Kernel side support was added earlier at r278161.
  
  Sponsored by: iXsystems, Inc.

Modified:
  stable/10/usr.sbin/ctld/ctl.conf.5
  stable/10/usr.sbin/ctld/ctld.c
  stable/10/usr.sbin/ctld/ctld.h
  stable/10/usr.sbin/ctld/discovery.c
  stable/10/usr.sbin/ctld/kernel.c
  stable/10/usr.sbin/ctld/login.c
  stable/10/usr.sbin/ctld/parse.y
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.sbin/ctld/ctl.conf.5
==============================================================================
--- stable/10/usr.sbin/ctld/ctl.conf.5  Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/ctl.conf.5  Thu Feb 19 14:52:01 2015        
(r279006)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 1, 2015
+.Dd February 6, 2015
 .Dt CTL.CONF 5
 .Os
 .Sh NAME
@@ -66,7 +66,7 @@ file is:
 
 .No target Ar name {
 .Dl auth-group Ar name
-.Dl portal-group Ar name
+.Dl portal-group Ar name Op Ar agname
 .Dl lun Ar number Ar name
 .Dl lun Ar number No {
 .Dl    path Ar path
@@ -310,12 +310,15 @@ This clause is mutually exclusive with
 .Sy auth-group ;
 one cannot use
 both in a single target.
-.It Ic portal-group Ar name
+.It Ic portal-group Ar name Op Ar agname
 Assign a previously defined portal group to the target.
 The default portal group is
 .Qq Ar default ,
 which makes the target available
 on TCP port 3260 on all configured IPv4 and IPv6 addresses.
+Optional second argument specifies auth group name for connections
+to this specific portal group.
+If second argument is not specified, target auth group is used.
 .It Ic redirect Aq Ar address
 IPv4 or IPv6 address to redirect initiators to.
 When configured, all initiators attempting to connect to this target

Modified: stable/10/usr.sbin/ctld/ctld.c
==============================================================================
--- stable/10/usr.sbin/ctld/ctld.c      Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/ctld.c      Thu Feb 19 14:52:01 2015        
(r279006)
@@ -91,6 +91,7 @@ conf_new(void)
        TAILQ_INIT(&conf->conf_luns);
        TAILQ_INIT(&conf->conf_targets);
        TAILQ_INIT(&conf->conf_auth_groups);
+       TAILQ_INIT(&conf->conf_ports);
        TAILQ_INIT(&conf->conf_portal_groups);
        TAILQ_INIT(&conf->conf_isns);
 
@@ -124,6 +125,7 @@ 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);
        free(conf);
 }
@@ -609,6 +611,7 @@ portal_group_new(struct conf *conf, cons
                log_err(1, "calloc");
        pg->pg_name = checked_strdup(name);
        TAILQ_INIT(&pg->pg_portals);
+       TAILQ_INIT(&pg->pg_ports);
        pg->pg_conf = conf;
        pg->pg_tag = 0;         /* Assigned later in conf_apply(). */
        TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
@@ -620,7 +623,10 @@ void
 portal_group_delete(struct portal_group *pg)
 {
        struct portal *portal, *tmp;
+       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);
 
        TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp)
@@ -784,6 +790,7 @@ isns_do_register(struct isns *isns, int 
        struct target *target;
        struct portal *portal;
        struct portal_group *pg;
+       struct port *port;
        struct isns_req *req;
        int res = 0;
        uint32_t error;
@@ -807,11 +814,14 @@ isns_do_register(struct isns *isns, int 
                isns_req_add_32(req, 33, 1); /* 1 -- Target*/
                if (target->t_alias != NULL)
                        isns_req_add_str(req, 34, target->t_alias);
-               pg = target->t_portal_group;
-               isns_req_add_32(req, 51, pg->pg_tag);
-               TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
-                       isns_req_add_addr(req, 49, portal->p_ai);
-                       isns_req_add_port(req, 50, portal->p_ai);
+               TAILQ_FOREACH(port, &target->t_ports, p_ts) {
+                       if ((pg = port->p_portal_group) == NULL)
+                               continue;
+                       isns_req_add_32(req, 51, pg->pg_tag);
+                       TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
+                               isns_req_add_addr(req, 49, portal->p_ai);
+                               isns_req_add_port(req, 50, portal->p_ai);
+                       }
                }
        }
        res = isns_req_send(s, req);
@@ -1123,6 +1133,68 @@ valid_iscsi_name(const char *name)
        return (true);
 }
 
+struct port *
+port_new(struct conf *conf, struct target *target, struct portal_group *pg)
+{
+       struct port *port;
+
+       port = calloc(1, sizeof(*port));
+       if (port == NULL)
+               log_err(1, "calloc");
+       asprintf(&port->p_name, "%s-%s", pg->pg_name, target->t_name);
+       if (port_find(conf, port->p_name) != NULL) {
+               log_warnx("duplicate port \"%s\"", port->p_name);
+               free(port);
+               return (NULL);
+       }
+       port->p_conf = conf;
+       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);
+}
+
+struct port *
+port_find(const struct conf *conf, const char *name)
+{
+       struct port *port;
+
+       TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
+               if (strcasecmp(port->p_name, name) == 0)
+                       return (port);
+       }
+
+       return (NULL);
+}
+
+struct port *
+port_find_in_pg(const struct portal_group *pg, const char *target)
+{
+       struct port *port;
+
+       TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
+               if (strcasecmp(port->p_target->t_name, target) == 0)
+                       return (port);
+       }
+
+       return (NULL);
+}
+
+void
+port_delete(struct port *port)
+{
+
+       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);
+}
+
 struct target *
 target_new(struct conf *conf, const char *name)
 {
@@ -1151,6 +1223,7 @@ target_new(struct conf *conf, const char
                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);
@@ -1159,7 +1232,10 @@ target_new(struct conf *conf, const char
 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_name);
@@ -1196,13 +1272,6 @@ target_set_redirection(struct target *ta
        return (0);
 }
 
-void
-target_set_ctl_port(struct target *target, uint32_t value)
-{
-
-       target->t_ctl_port = value;
-}
-
 struct lun *
 lun_new(struct conf *conf, const char *name)
 {
@@ -1508,6 +1577,7 @@ conf_verify(struct conf *conf)
 {
        struct auth_group *ag;
        struct portal_group *pg;
+       struct port *port;
        struct target *targ;
        struct lun *lun;
        bool found;
@@ -1527,10 +1597,10 @@ conf_verify(struct conf *conf)
                            "default");
                        assert(targ->t_auth_group != NULL);
                }
-               if (targ->t_portal_group == NULL) {
-                       targ->t_portal_group = portal_group_find(conf,
-                           "default");
-                       assert(targ->t_portal_group != NULL);
+               if (TAILQ_EMPTY(&targ->t_ports)) {
+                       pg = portal_group_find(conf, "default");
+                       assert(pg != NULL);
+                       port_new(conf, targ, pg);
                }
                found = false;
                for (i = 0; i < MAX_LUNS; i++) {
@@ -1558,20 +1628,14 @@ conf_verify(struct conf *conf)
                if (pg->pg_discovery_filter == PG_FILTER_UNKNOWN)
                        pg->pg_discovery_filter = PG_FILTER_NONE;
 
-               TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
-                       if (targ->t_portal_group == pg)
-                               break;
-               }
-               if (pg->pg_redirection != NULL) {
-                       if (targ != NULL) {
+               if (!TAILQ_EMPTY(&pg->pg_ports)) {
+                       if (pg->pg_redirection != NULL) {
                                log_debugx("portal-group \"%s\" assigned "
-                                   "to target \"%s\", but configured "
+                                   "to target, but configured "
                                    "for redirection",
-                                   pg->pg_name, targ->t_name);
+                                   pg->pg_name);
                        }
                        pg->pg_unassigned = false;
-               } else if (targ != NULL) {
-                       pg->pg_unassigned = false;
                } else {
                        if (strcmp(pg->pg_name, "default") != 0)
                                log_warnx("portal-group \"%s\" not assigned "
@@ -1592,6 +1656,12 @@ conf_verify(struct conf *conf)
                                break;
                        }
                }
+               TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
+                       if (port->p_auth_group == ag) {
+                               found = true;
+                               break;
+                       }
+               }
                TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
                        if (pg->pg_discovery_auth_group == ag) {
                                found = true;
@@ -1613,10 +1683,10 @@ conf_verify(struct conf *conf)
 static int
 conf_apply(struct conf *oldconf, struct conf *newconf)
 {
-       struct target *oldtarg, *newtarg, *tmptarg;
        struct lun *oldlun, *newlun, *tmplun;
        struct portal_group *oldpg, *newpg;
        struct portal *oldp, *newp;
+       struct port *oldport, *newport, *tmpport;
        struct isns *oldns, *newns;
        pid_t otherpid;
        int changed, cumulated_error = 0, error, sockbuf;
@@ -1684,17 +1754,17 @@ conf_apply(struct conf *oldconf, struct 
         *      really happen, so leave it as it is for now.
         */
        /*
-        * First, remove any targets present in the old configuration
+        * First, remove any ports present in the old configuration
         * and missing in the new one.
         */
-       TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
-               newtarg = target_find(newconf, oldtarg->t_name);
-               if (newtarg != NULL)
+       TAILQ_FOREACH_SAFE(oldport, &oldconf->conf_ports, p_next, tmpport) {
+               newport = port_find(newconf, oldport->p_name);
+               if (newport != NULL)
                        continue;
-               error = kernel_port_remove(oldtarg);
+               error = kernel_port_remove(oldport);
                if (error != 0) {
-                       log_warnx("failed to remove target %s",
-                           oldtarg->t_name);
+                       log_warnx("failed to remove port %s",
+                           oldport->p_name);
                        /*
                         * XXX: Uncomment after fixing the root cause.
                         *
@@ -1809,21 +1879,21 @@ conf_apply(struct conf *oldconf, struct 
        }
 
        /*
-        * Now add new targets or modify existing ones.
+        * Now add new ports or modify existing ones.
         */
-       TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
-               oldtarg = target_find(oldconf, newtarg->t_name);
+       TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) {
+               oldport = port_find(oldconf, newport->p_name);
 
-               if (oldtarg == NULL)
-                       error = kernel_port_add(newtarg);
-               else {
-                       target_set_ctl_port(newtarg, oldtarg->t_ctl_port);
-                       error = kernel_port_update(newtarg);
+               if (oldport == NULL) {
+                       error = kernel_port_add(newport);
+               } else {
+                       newport->p_ctl_port = oldport->p_ctl_port;
+                       error = kernel_port_update(newport);
                }
                if (error != 0) {
-                       log_warnx("failed to %s target %s",
-                           (oldtarg == NULL) ? "add" : "update",
-                           newtarg->t_name);
+                       log_warnx("failed to %s port %s",
+                           (oldport == NULL) ? "add" : "update",
+                           newport->p_name);
                        /*
                         * XXX: Uncomment after fixing the root cause.
                         *

Modified: stable/10/usr.sbin/ctld/ctld.h
==============================================================================
--- stable/10/usr.sbin/ctld/ctld.h      Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/ctld.h      Thu Feb 19 14:52:01 2015        
(r279006)
@@ -119,11 +119,25 @@ struct portal_group {
        int                             pg_discovery_filter;
        bool                            pg_unassigned;
        TAILQ_HEAD(, portal)            pg_portals;
+       TAILQ_HEAD(, port)              pg_ports;
        char                            *pg_redirection;
 
        uint16_t                        pg_tag;
 };
 
+struct port {
+       TAILQ_ENTRY(port)               p_next;
+       TAILQ_ENTRY(port)               p_pgs;
+       TAILQ_ENTRY(port)               p_ts;
+       struct conf                     *p_conf;
+       char                            *p_name;
+       struct auth_group               *p_auth_group;
+       struct portal_group             *p_portal_group;
+       struct target                   *p_target;
+
+       uint32_t                        p_ctl_port;
+};
+
 struct lun_option {
        TAILQ_ENTRY(lun_option)         lo_next;
        struct lun                      *lo_lun;
@@ -152,12 +166,10 @@ struct target {
        struct conf                     *t_conf;
        struct lun                      *t_luns[MAX_LUNS];
        struct auth_group               *t_auth_group;
-       struct portal_group             *t_portal_group;
+       TAILQ_HEAD(, port)              t_ports;
        char                            *t_name;
        char                            *t_alias;
        char                            *t_redirection;
-
-       uint32_t                        t_ctl_port;
 };
 
 struct isns {
@@ -172,6 +184,7 @@ struct conf {
        TAILQ_HEAD(, lun)               conf_luns;
        TAILQ_HEAD(, target)            conf_targets;
        TAILQ_HEAD(, auth_group)        conf_auth_groups;
+       TAILQ_HEAD(, port)              conf_ports;
        TAILQ_HEAD(, portal_group)      conf_portal_groups;
        TAILQ_HEAD(, isns)              conf_isns;
        int                             conf_isns_period;
@@ -199,6 +212,7 @@ struct conf {
 
 struct connection {
        struct portal           *conn_portal;
+       struct port             *conn_port;
        struct target           *conn_target;
        int                     conn_socket;
        int                     conn_session_type;
@@ -317,14 +331,19 @@ void                      isns_register(struct isns 
*isns, 
 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_find(const struct conf *conf, const char *name);
+struct port            *port_find_in_pg(const struct portal_group *pg,
+                           const char *target);
+void                   port_delete(struct port *port);
+
 struct target          *target_new(struct conf *conf, const char *name);
 void                   target_delete(struct target *target);
 struct target          *target_find(struct conf *conf,
                            const char *name);
 int                    target_set_redirection(struct target *target,
                            const char *addr);
-void                   target_set_ctl_port(struct target *target,
-                           uint32_t value);
 
 struct lun             *lun_new(struct conf *conf, const char *name);
 void                   lun_delete(struct lun *lun);
@@ -351,9 +370,9 @@ int                 kernel_lun_add(struct lun *lun);
 int                    kernel_lun_resize(struct lun *lun);
 int                    kernel_lun_remove(struct lun *lun);
 void                   kernel_handoff(struct connection *conn);
-int                    kernel_port_add(struct target *targ);
-int                    kernel_port_update(struct target *targ);
-int                    kernel_port_remove(struct target *targ);
+int                    kernel_port_add(struct port *port);
+int                    kernel_port_update(struct port *port);
+int                    kernel_port_remove(struct port *port);
 void                   kernel_capsicate(void);
 
 #ifdef ICL_KERNEL_PROXY

Modified: stable/10/usr.sbin/ctld/discovery.c
==============================================================================
--- stable/10/usr.sbin/ctld/discovery.c Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/discovery.c Thu Feb 19 14:52:01 2015        
(r279006)
@@ -162,6 +162,7 @@ logout_new_response(struct pdu *request)
 static void
 discovery_add_target(struct keys *response_keys, const struct target *targ)
 {
+       struct port *port;
        struct portal *portal;
        char *buf;
        char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
@@ -169,7 +170,10 @@ discovery_add_target(struct keys *respon
        int ret;
 
        keys_add(response_keys, "TargetName", targ->t_name);
-       TAILQ_FOREACH(portal, &targ->t_portal_group->pg_portals, p_next) {
+       TAILQ_FOREACH(port, &targ->t_ports, p_ts) {
+           if (port->p_portal_group == NULL)
+               continue;
+           TAILQ_FOREACH(portal, &port->p_portal_group->pg_portals, p_next) {
                ai = portal->p_ai;
                ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
                    hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
@@ -183,13 +187,13 @@ discovery_add_target(struct keys *respon
                        if (strcmp(hbuf, "0.0.0.0") == 0)
                                continue;
                        ret = asprintf(&buf, "%s:%s,%d", hbuf, sbuf,
-                           targ->t_portal_group->pg_tag);
+                           port->p_portal_group->pg_tag);
                        break;
                case AF_INET6:
                        if (strcmp(hbuf, "::") == 0)
                                continue;
                        ret = asprintf(&buf, "[%s]:%s,%d", hbuf, sbuf,
-                           targ->t_portal_group->pg_tag);
+                           port->p_portal_group->pg_tag);
                        break;
                default:
                        continue;
@@ -198,19 +202,24 @@ discovery_add_target(struct keys *respon
                    log_err(1, "asprintf");
                keys_add(response_keys, "TargetAddress", buf);
                free(buf);
+           }
        }
 }
 
 static bool
 discovery_target_filtered_out(const struct connection *conn,
-    const struct target *targ)
+    const struct port *port)
 {
        const struct auth_group *ag;
        const struct portal_group *pg;
+       const struct target *targ;
        const struct auth *auth;
        int error;
 
-       ag = targ->t_auth_group;
+       targ = port->p_target;
+       ag = port->p_auth_group;
+       if (ag == NULL)
+               ag = targ->t_auth_group;
        pg = conn->conn_portal->p_portal_group;
 
        assert(pg->pg_discovery_auth_group != PG_FILTER_UNKNOWN);
@@ -265,8 +274,8 @@ discovery(struct connection *conn)
 {
        struct pdu *request, *response;
        struct keys *request_keys, *response_keys;
+       const struct port *port;
        const struct portal_group *pg;
-       const struct target *targ;
        const char *send_targets;
 
        pg = conn->conn_portal->p_portal_group;
@@ -284,29 +293,23 @@ discovery(struct connection *conn)
        response_keys = keys_new();
 
        if (strcmp(send_targets, "All") == 0) {
-               TAILQ_FOREACH(targ, &pg->pg_conf->conf_targets, t_next) {
-                       if (targ->t_portal_group != pg) {
-                               log_debugx("not returning target \"%s\"; "
-                                   "belongs to a different portal group",
-                                   targ->t_name);
-                               continue;
-                       }
-                       if (discovery_target_filtered_out(conn, targ)) {
+               TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
+                       if (discovery_target_filtered_out(conn, port)) {
                                /* Ignore this target. */
                                continue;
                        }
-                       discovery_add_target(response_keys, targ);
+                       discovery_add_target(response_keys, port->p_target);
                }
        } else {
-               targ = target_find(pg->pg_conf, send_targets);
-               if (targ == NULL) {
+               port = port_find_in_pg(pg, send_targets);
+               if (port == NULL) {
                        log_debugx("initiator requested information on unknown "
                            "target \"%s\"; returning nothing", send_targets);
                } else {
-                       if (discovery_target_filtered_out(conn, targ)) {
+                       if (discovery_target_filtered_out(conn, port)) {
                                /* Ignore this target. */
                        } else {
-                               discovery_add_target(response_keys, targ);
+                               discovery_add_target(response_keys, 
port->p_target);
                        }
                }
        }

Modified: stable/10/usr.sbin/ctld/kernel.c
==============================================================================
--- stable/10/usr.sbin/ctld/kernel.c    Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/kernel.c    Thu Feb 19 14:52:01 2015        
(r279006)
@@ -121,9 +121,10 @@ struct cctl_lun {
 
 struct cctl_port {
        uint32_t port_id;
-       int cfiscsi_status;
+       int cfiscsi_state;
        char *cfiscsi_target;
        uint16_t cfiscsi_portal_group_tag;
+       char *ctld_portal_group_name;
        STAILQ_HEAD(,cctl_lun_nv) attr_list;
        STAILQ_ENTRY(cctl_port) links;
 };
@@ -332,10 +333,13 @@ cctl_end_pelement(void *user_data, const
        if (strcmp(name, "cfiscsi_target") == 0) {
                cur_port->cfiscsi_target = str;
                str = NULL;
-       } else if (strcmp(name, "cfiscsi_status") == 0) {
-               cur_port->cfiscsi_status = strtoul(str, NULL, 0);
+       } else if (strcmp(name, "cfiscsi_state") == 0) {
+               cur_port->cfiscsi_state = strtoul(str, NULL, 0);
        } else if (strcmp(name, "cfiscsi_portal_group_tag") == 0) {
                cur_port->cfiscsi_portal_group_tag = strtoul(str, NULL, 0);
+       } else if (strcmp(name, "ctld_portal_group_name") == 0) {
+               cur_port->ctld_portal_group_name = str;
+               str = NULL;
        } else if (strcmp(name, "targ_port") == 0) {
                devlist->cur_port = NULL;
        } else if (strcmp(name, "ctlportlist") == 0) {
@@ -373,6 +377,8 @@ conf_new_from_kernel(void)
 {
        struct conf *conf = NULL;
        struct target *targ;
+       struct portal_group *pg;
+       struct port *cp;
        struct lun *cl;
        struct lun_option *lo;
        struct ctl_lun_list list;
@@ -496,9 +502,9 @@ retry_port:
                            "ignoring", (uintmax_t)port->port_id);
                        continue;
                }
-               if (port->cfiscsi_status != 1) {
+               if (port->cfiscsi_state != 1) {
                        log_debugx("CTL port %ju is not active (%d); ignoring",
-                           (uintmax_t)port->port_id, port->cfiscsi_status);
+                           (uintmax_t)port->port_id, port->cfiscsi_state);
                        continue;
                }
 
@@ -514,6 +520,28 @@ retry_port:
                                continue;
                        }
                }
+
+               if (port->ctld_portal_group_name == NULL)
+                       continue;
+               pg = portal_group_find(conf, port->ctld_portal_group_name);
+               if (pg == NULL) {
+#if 0
+                       log_debugx("found new kernel portal group %s for CTL 
port %ld",
+                           port->ctld_portal_group_name, port->port_id);
+#endif
+                       pg = portal_group_new(conf, 
port->ctld_portal_group_name);
+                       if (pg == NULL) {
+                               log_warnx("portal_group_new failed");
+                               continue;
+                       }
+               }
+               pg->pg_tag = port->cfiscsi_portal_group_tag;
+               cp = port_new(conf, targ, pg);
+               if (cp == NULL) {
+                       log_warnx("port_new failed");
+                       continue;
+               }
+               cp->p_ctl_port = port->port_id;
        }
 
        STAILQ_FOREACH(lun, &devlist.lun_list, links) {
@@ -804,32 +832,34 @@ kernel_handoff(struct connection *conn)
 }
 
 int
-kernel_port_add(struct target *targ)
+kernel_port_add(struct port *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 tagstr[16];
-       int error, i;
+       int error, i, n;
 
        /* Create iSCSI port. */
        bzero(&req, sizeof(req));
        strlcpy(req.driver, "iscsi", sizeof(req.driver));
        req.reqtype = CTL_REQ_CREATE;
-       req.num_args = 4;
        req.args = malloc(req.num_args * sizeof(*req.args));
-       req.args[0].namelen = sizeof("port_id");
-       req.args[0].name = __DECONST(char *, "port_id");
-       req.args[0].vallen = sizeof(targ->t_ctl_port);
-       req.args[0].value = &targ->t_ctl_port;
-       req.args[0].flags = CTL_BEARG_WR;
-       str_arg(&req.args[1], "cfiscsi_target", targ->t_name);
-       snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
-       str_arg(&req.args[2], "cfiscsi_portal_group_tag", tagstr);
+       n = 0;
+       req.args[n].namelen = sizeof("port_id");
+       req.args[n].name = __DECONST(char *, "port_id");
+       req.args[n].vallen = sizeof(port->p_ctl_port);
+       req.args[n].value = &port->p_ctl_port;
+       req.args[n++].flags = CTL_BEARG_WR;
+       str_arg(&req.args[n++], "cfiscsi_target", targ->t_name);
+       snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
+       str_arg(&req.args[n++], "cfiscsi_portal_group_tag", tagstr);
        if (targ->t_alias)
-               str_arg(&req.args[3], "cfiscsi_target_alias", targ->t_alias);
-       else
-               req.num_args--;
+               str_arg(&req.args[n++], "cfiscsi_target_alias", targ->t_alias);
+       str_arg(&req.args[n++], "ctld_portal_group_name", pg->pg_name);
+       req.num_args = n;
        error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
        free(req.args);
        if (error != 0) {
@@ -848,7 +878,7 @@ kernel_port_add(struct target *targ)
        }
 
        /* Explicitly enable mapping to block any access except allowed. */
-       lm.port = targ->t_ctl_port;
+       lm.port = port->p_ctl_port;
        lm.plun = UINT32_MAX;
        lm.lun = 0;
        error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
@@ -859,7 +889,7 @@ kernel_port_add(struct target *targ)
        for (i = 0; i < MAX_LUNS; i++) {
                if (targ->t_luns[i] == NULL)
                        continue;
-               lm.port = targ->t_ctl_port;
+               lm.port = port->p_ctl_port;
                lm.plun = i;
                lm.lun = targ->t_luns[i]->l_ctl_lun;
                error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
@@ -869,7 +899,7 @@ kernel_port_add(struct target *targ)
 
        /* Enable port */
        bzero(&entry, sizeof(entry));
-       entry.targ_port = targ->t_ctl_port;
+       entry.targ_port = port->p_ctl_port;
        error = ioctl(ctl_fd, CTL_ENABLE_PORT, &entry);
        if (error != 0) {
                log_warn("CTL_ENABLE_PORT ioctl failed");
@@ -880,14 +910,15 @@ kernel_port_add(struct target *targ)
 }
 
 int
-kernel_port_update(struct target *targ)
+kernel_port_update(struct port *port)
 {
        struct ctl_lun_map lm;
+       struct target *targ = port->p_target;
        int error, i;
 
        /* Map configured LUNs and unmap others */
        for (i = 0; i < MAX_LUNS; i++) {
-               lm.port = targ->t_ctl_port;
+               lm.port = port->p_ctl_port;
                lm.plun = i;
                if (targ->t_luns[i] == NULL)
                        lm.lun = UINT32_MAX;
@@ -901,10 +932,12 @@ kernel_port_update(struct target *targ)
 }
 
 int
-kernel_port_remove(struct target *targ)
+kernel_port_remove(struct port *port)
 {
        struct ctl_req req;
        char tagstr[16];
+       struct target *targ = port->p_target;
+       struct portal_group *pg = port->p_portal_group;
        int error;
 
        bzero(&req, sizeof(req));
@@ -913,7 +946,7 @@ kernel_port_remove(struct target *targ)
        req.num_args = 2;
        req.args = malloc(req.num_args * sizeof(*req.args));
        str_arg(&req.args[0], "cfiscsi_target", targ->t_name);
-       snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
+       snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
        str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
 
        error = ioctl(ctl_fd, CTL_PORT_REQ, &req);

Modified: stable/10/usr.sbin/ctld/login.c
==============================================================================
--- stable/10/usr.sbin/ctld/login.c     Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/login.c     Thu Feb 19 14:52:01 2015        
(r279006)
@@ -827,19 +827,22 @@ login(struct connection *conn)
                        log_errx(1, "received Login PDU without TargetName");
                }
 
-               conn->conn_target = target_find(pg->pg_conf, target_name);
-               if (conn->conn_target == NULL) {
+               conn->conn_port = port_find_in_pg(pg, target_name);
+               if (conn->conn_port == NULL) {
                        login_send_error(request, 0x02, 0x03);
                        log_errx(1, "requested target \"%s\" not found",
                            target_name);
                }
+               conn->conn_target = conn->conn_port->p_target;
        }
 
        /*
         * At this point we know what kind of authentication we need.
         */
        if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
-               ag = conn->conn_target->t_auth_group;
+               ag = conn->conn_port->p_auth_group;
+               if (ag == NULL)
+                       ag = conn->conn_target->t_auth_group;
                if (ag->ag_name != NULL) {
                        log_debugx("initiator requests to connect "
                            "to target \"%s\"; auth-group \"%s\"",

Modified: stable/10/usr.sbin/ctld/parse.y
==============================================================================
--- stable/10/usr.sbin/ctld/parse.y     Thu Feb 19 14:40:50 2015        
(r279005)
+++ stable/10/usr.sbin/ctld/parse.y     Thu Feb 19 14:52:01 2015        
(r279006)
@@ -652,21 +652,58 @@ target_initiator_portal:  INITIATOR_PORTA
        }
        ;
 
-target_portal_group:   PORTAL_GROUP STR
+target_portal_group:   PORTAL_GROUP STR STR
        {
-               if (target->t_portal_group != NULL) {
-                       log_warnx("portal-group for target \"%s\" "
-                           "specified more than once", target->t_name);
+               struct portal_group *tpg;
+               struct auth_group *tag;
+               struct port *tp;
+
+               tpg = portal_group_find(conf, $2);
+               if (tpg == NULL) {
+                       log_warnx("unknown portal-group \"%s\" for target "
+                           "\"%s\"", $2, target->t_name);
                        free($2);
+                       free($3);
                        return (1);
                }
-               target->t_portal_group = portal_group_find(conf, $2);
-               if (target->t_portal_group == NULL) {
+               tag = auth_group_find(conf, $3);
+               if (tag == NULL) {
+                       log_warnx("unknown auth-group \"%s\" for target "
+                           "\"%s\"", $3, target->t_name);
+                       free($2);
+                       free($3);
+                       return (1);
+               }
+               tp = port_new(conf, target, tpg);
+               if (tp == NULL) {
+                       log_warnx("can't link portal-group \"%s\" to target "
+                           "\"%s\"", $2, target->t_name);
+                       free($2);
+                       return (1);
+               }
+               tp->p_auth_group = tag;
+               free($2);
+               free($3);
+       }
+       |               PORTAL_GROUP STR
+       {
+               struct portal_group *tpg;
+               struct port *tp;
+
+               tpg = portal_group_find(conf, $2);
+               if (tpg == NULL) {
                        log_warnx("unknown portal-group \"%s\" for target "
                            "\"%s\"", $2, target->t_name);
                        free($2);
                        return (1);
                }
+               tp = port_new(conf, target, tpg);
+               if (tp == NULL) {
+                       log_warnx("can't link portal-group \"%s\" to target "
+                           "\"%s\"", $2, target->t_name);
+                       free($2);
+                       return (1);
+               }
                free($2);
        }
        ;
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to