Bring some more order into iSCSI portal group tags support.

While ctld(8) still does not allow multiple portal groups per target
to be configured, kernel should now be able to handle it.

MFC after:	2 weeks
Sponsored by:	iXsystems, Inc.
This commit is contained in:
Alexander Motin 2015-02-03 16:17:54 +00:00
parent 5b3ddf0928
commit 6b31e1302f
6 changed files with 47 additions and 30 deletions

View File

@ -165,9 +165,10 @@ static void cfiscsi_pdu_handle_data_out(struct icl_pdu *request);
static void cfiscsi_pdu_handle_logout_request(struct icl_pdu *request);
static void cfiscsi_session_terminate(struct cfiscsi_session *cs);
static struct cfiscsi_target *cfiscsi_target_find(struct cfiscsi_softc
*softc, const char *name);
*softc, const char *name, uint16_t tag);
static struct cfiscsi_target *cfiscsi_target_find_or_create(
struct cfiscsi_softc *softc, const char *name, const char *alias);
struct cfiscsi_softc *softc, const char *name, const char *alias,
uint16_t tag);
static void cfiscsi_target_release(struct cfiscsi_target *ct);
static void cfiscsi_session_delete(struct cfiscsi_session *cs);
@ -1434,7 +1435,8 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
cihp->initiator_name, cihp->initiator_addr,
cihp->target_name);
ct = cfiscsi_target_find(softc, cihp->target_name);
ct = cfiscsi_target_find(softc, cihp->target_name,
cihp->portal_group_tag);
if (ct == NULL) {
ci->status = CTL_ISCSI_ERROR;
snprintf(ci->error_str, sizeof(ci->error_str),
@ -1484,7 +1486,6 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
* PDU from the Login Phase received from the initiator. Thus,
* the -1 below.
*/
cs->cs_portal_group_tag = cihp->portal_group_tag;
cs->cs_cmdsn = cihp->cmdsn;
cs->cs_statsn = cihp->statsn;
cs->cs_max_data_segment_length = cihp->max_recv_data_segment_length;
@ -1529,7 +1530,6 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
TAILQ_FOREACH(cs2, &softc->sessions, cs_next) {
if (cs2 != cs && cs2->cs_tasks_aborted == false &&
cs->cs_target == cs2->cs_target &&
cs->cs_portal_group_tag == cs2->cs_portal_group_tag &&
strcmp(cs->cs_initiator_id, cs2->cs_initiator_id) == 0) {
cfiscsi_session_terminate(cs2);
mtx_unlock(&softc->lock);
@ -1614,6 +1614,7 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci)
"<initiator_alias>%s</initiator_alias>"
"<target>%s</target>"
"<target_alias>%s</target_alias>"
"<target_portal_group_tag>%u</target_portal_group_tag>"
"<header_digest>%s</header_digest>"
"<data_digest>%s</data_digest>"
"<max_data_segment_length>%zd</max_data_segment_length>"
@ -1623,6 +1624,7 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci)
cs->cs_id,
cs->cs_initiator_name, cs->cs_initiator_addr, cs->cs_initiator_alias,
cs->cs_target->ct_name, cs->cs_target->ct_alias,
cs->cs_target->ct_tag,
cs->cs_conn->ic_header_crc32c ? "CRC32C" : "None",
cs->cs_conn->ic_data_crc32c ? "CRC32C" : "None",
cs->cs_max_data_segment_length,
@ -1980,23 +1982,25 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
{
struct cfiscsi_target *ct;
struct ctl_port *port;
const char *target, *alias, *tag;
const char *target, *alias, *tags;
struct scsi_vpd_id_descriptor *desc;
ctl_options_t opts;
int retval, len, idlen;
uint16_t tag;
ctl_init_opts(&opts, req->num_args, req->kern_args);
target = ctl_get_opt(&opts, "cfiscsi_target");
alias = ctl_get_opt(&opts, "cfiscsi_target_alias");
tag = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
if (target == NULL || tag == NULL) {
tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
if (target == NULL || tags == NULL) {
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"Missing required argument");
ctl_free_opts(&opts);
return;
}
ct = cfiscsi_target_find_or_create(&cfiscsi_softc, target, alias);
tag = strtol(tags, (char **)NULL, 10);
ct = cfiscsi_target_find_or_create(&cfiscsi_softc, target, alias, tag);
if (ct == NULL) {
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
@ -2022,7 +2026,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
/* XXX KDM what should the real number be here? */
port->num_requested_ctl_io = 4096;
port->port_name = "iscsi";
port->physical_port = strtoul(tag, NULL, 0);
port->physical_port = tag;
port->virtual_port = ct->ct_target_id;
port->port_online = cfiscsi_online;
port->port_offline = cfiscsi_offline;
@ -2054,8 +2058,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
SVPD_ID_TYPE_SCSI_NAME;
desc->length = idlen;
snprintf(desc->identifier, idlen, "%s,t,0x%4.4x",
target, port->physical_port);
snprintf(desc->identifier, idlen, "%s,t,0x%4.4x", target, tag);
/* Generate Target ID. */
idlen = strlen(target) + 1;
@ -2093,19 +2096,22 @@ static void
cfiscsi_ioctl_port_remove(struct ctl_req *req)
{
struct cfiscsi_target *ct;
const char *target;
const char *target, *tags;
ctl_options_t opts;
uint16_t tag;
ctl_init_opts(&opts, req->num_args, req->kern_args);
target = ctl_get_opt(&opts, "cfiscsi_target");
if (target == NULL) {
tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
if (target == NULL || tags == NULL) {
ctl_free_opts(&opts);
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"Missing required argument");
return;
}
ct = cfiscsi_target_find(&cfiscsi_softc, target);
tag = strtol(tags, (char **)NULL, 10);
ct = cfiscsi_target_find(&cfiscsi_softc, target, tag);
if (ct == NULL) {
ctl_free_opts(&opts);
req->status = CTL_LUN_ERROR;
@ -2126,6 +2132,7 @@ cfiscsi_ioctl_port_remove(struct ctl_req *req)
ctl_port_offline(&ct->ct_port);
cfiscsi_target_release(ct);
cfiscsi_target_release(ct);
req->status = CTL_LUN_OK;
}
static int
@ -2234,13 +2241,14 @@ cfiscsi_target_release(struct cfiscsi_target *ct)
}
static struct cfiscsi_target *
cfiscsi_target_find(struct cfiscsi_softc *softc, const char *name)
cfiscsi_target_find(struct cfiscsi_softc *softc, const char *name, uint16_t tag)
{
struct cfiscsi_target *ct;
mtx_lock(&softc->lock);
TAILQ_FOREACH(ct, &softc->targets, ct_next) {
if (strcmp(name, ct->ct_name) != 0 ||
if (ct->ct_tag != tag ||
strcmp(name, ct->ct_name) != 0 ||
ct->ct_state != CFISCSI_TARGET_STATE_ACTIVE)
continue;
cfiscsi_target_hold(ct);
@ -2254,7 +2262,7 @@ cfiscsi_target_find(struct cfiscsi_softc *softc, const char *name)
static struct cfiscsi_target *
cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
const char *alias)
const char *alias, uint16_t tag)
{
struct cfiscsi_target *ct, *newct;
@ -2265,7 +2273,8 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
mtx_lock(&softc->lock);
TAILQ_FOREACH(ct, &softc->targets, ct_next) {
if (strcmp(name, ct->ct_name) != 0 ||
if (ct->ct_tag != tag ||
strcmp(name, ct->ct_name) != 0 ||
ct->ct_state == CFISCSI_TARGET_STATE_INVALID)
continue;
cfiscsi_target_hold(ct);
@ -2277,6 +2286,7 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
strlcpy(newct->ct_name, name, sizeof(newct->ct_name));
if (alias != NULL)
strlcpy(newct->ct_alias, alias, sizeof(newct->ct_alias));
newct->ct_tag = tag;
refcount_init(&newct->ct_refcount, 1);
newct->ct_softc = softc;
if (TAILQ_EMPTY(&softc->targets))

View File

@ -42,6 +42,7 @@ struct cfiscsi_target {
volatile u_int ct_refcount;
char ct_name[CTL_ISCSI_NAME_LEN];
char ct_alias[CTL_ISCSI_ALIAS_LEN];
uint16_t ct_tag;
int ct_state;
int ct_online;
int ct_target_id;
@ -79,7 +80,6 @@ struct cfiscsi_session {
struct cfiscsi_target *cs_target;
struct callout cs_callout;
int cs_timeout;
int cs_portal_group_tag;
struct cv cs_maintenance_cv;
bool cs_terminating;
bool cs_tasks_aborted;

View File

@ -3542,6 +3542,7 @@ cctl_islist_end_element(void *user_data, const char *name)
} else if (strcmp(name, "target_alias") == 0) {
cur_conn->target_alias = str;
str = NULL;
} else if (strcmp(name, "target_portal_group_tag") == 0) {
} else if (strcmp(name, "header_digest") == 0) {
cur_conn->header_digest = str;
str = NULL;

View File

@ -59,6 +59,7 @@ static volatile bool sigterm_received = false;
static volatile bool sigalrm_received = false;
static int nchildren = 0;
static uint16_t last_portal_group_tag = 0;
static void
usage(void)
@ -609,8 +610,7 @@ portal_group_new(struct conf *conf, const char *name)
pg->pg_name = checked_strdup(name);
TAILQ_INIT(&pg->pg_portals);
pg->pg_conf = conf;
conf->conf_last_portal_group_tag++;
pg->pg_tag = conf->conf_last_portal_group_tag;
pg->pg_tag = 0; /* Assigned later in conf_apply(). */
TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
return (pg);
@ -1655,6 +1655,17 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
}
}
/*
* Go through the new portal groups, assigning tags or preserving old.
*/
TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) {
oldpg = portal_group_find(oldconf, newpg->pg_name);
if (oldpg != NULL)
newpg->pg_tag = oldpg->pg_tag;
else
newpg->pg_tag = ++last_portal_group_tag;
}
/* Deregister on removed iSNS servers. */
TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) {
TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) {
@ -2372,7 +2383,7 @@ main(int argc, char **argv)
log_debugx("exiting on signal; "
"reloading empty configuration");
log_debugx("disabling CTL iSCSI port "
log_debugx("removing CTL iSCSI ports "
"and terminating all connections");
oldconf = newconf;

View File

@ -180,7 +180,6 @@ struct conf {
int conf_timeout;
int conf_maxproc;
uint16_t conf_last_portal_group_tag;
#ifdef ICL_KERNEL_PROXY
int conf_portal_id;
#endif

View File

@ -913,12 +913,8 @@ 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);
if (targ->t_portal_group) {
snprintf(tagstr, sizeof(tagstr), "%d",
targ->t_portal_group->pg_tag);
str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
} else
req.num_args--;
snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
free(req.args);