Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Feb 2015 14:52:01 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r279006 - stable/10/usr.sbin/ctld
Message-ID:  <201502191452.t1JEq1w7013965@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 	}
 	;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502191452.t1JEq1w7013965>