summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ctld/ctld.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-02-06 17:43:13 +0000
committermav <mav@FreeBSD.org>2015-02-06 17:43:13 +0000
commit7bd92dacb8d7f8dabe4266e8eaa7c14c339b09e4 (patch)
tree27ef1245ae93716ad309d2c64416f2208fbeb573 /usr.sbin/ctld/ctld.c
parented270a5b10cfad67e8efe67ad3974fe3b00025ce (diff)
downloadFreeBSD-src-7bd92dacb8d7f8dabe4266e8eaa7c14c339b09e4.zip
FreeBSD-src-7bd92dacb8d7f8dabe4266e8eaa7c14c339b09e4.tar.gz
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. MFC after: 2 weeks Sponsored by: iXsystems, Inc.
Diffstat (limited to 'usr.sbin/ctld/ctld.c')
-rw-r--r--usr.sbin/ctld/ctld.c162
1 files changed, 116 insertions, 46 deletions
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index c19b55a..513e073 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -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, const char *name)
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 s, const char *hostname)
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 s, const char *hostname)
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 *name)
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 *name)
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 *target, const char *addr)
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 conf *newconf)
* 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 conf *newconf)
}
/*
- * 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);
-
- if (oldtarg == NULL)
- error = kernel_port_add(newtarg);
- else {
- target_set_ctl_port(newtarg, oldtarg->t_ctl_port);
- error = kernel_port_update(newtarg);
+ TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) {
+ oldport = port_find(oldconf, newport->p_name);
+
+ 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.
*
OpenPOWER on IntegriCloud