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.
This commit is contained in:
parent
c869aa71f0
commit
92847ee1f3
@ -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
|
||||
|
@ -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);
|
||||
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.
|
||||
*
|
||||
|
@ -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, struct isns *oldisns);
|
||||
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
|
||||
|
@ -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 *response_keys, const struct target *targ)
|
||||
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 *response_keys, const struct target *targ)
|
||||
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 *response_keys, const struct target *targ)
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 char *name)
|
||||
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);
|
||||
|
@ -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\"",
|
||||
|
@ -652,21 +652,58 @@ target_initiator_portal: INITIATOR_PORTAL STR
|
||||
}
|
||||
;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
target->t_portal_group = portal_group_find(conf, $2);
|
||||
if (target->t_portal_group == NULL) {
|
||||
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);
|
||||
}
|
||||
;
|
||||
|
Loading…
x
Reference in New Issue
Block a user