Date: Fri, 20 Feb 2015 17:09:50 +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: r279055 - stable/10/usr.sbin/ctld Message-ID: <201502201709.t1KH9o5o070617@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Fri Feb 20 17:09:49 2015 New Revision: 279055 URL: https://svnweb.freebsd.org/changeset/base/279055 Log: MFC r278354: Teach ctld(8) to control non-iSCSI CTL ports. This change introduces new target option "port", that assigns current target to specified CTL port. On config application ctld(8) will apply LUN mapping according to target configuration to specified port and bring the port up. On shutdown cltd(8) will remove the mapping and put the port down. This change allows to configure both iSCSI and FibreChannel targets in the same configuration file in alike way. Kernel side support was added earlier at r278037. Relnotes: yes 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/kernel.c stable/10/usr.sbin/ctld/parse.y stable/10/usr.sbin/ctld/token.l Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/ctld/ctl.conf.5 ============================================================================== --- stable/10/usr.sbin/ctld/ctl.conf.5 Fri Feb 20 13:50:50 2015 (r279054) +++ stable/10/usr.sbin/ctld/ctl.conf.5 Fri Feb 20 17:09:49 2015 (r279055) @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 6, 2015 +.Dd February 7, 2015 .Dt CTL.CONF 5 .Os .Sh NAME @@ -67,6 +67,7 @@ file is: .No target Ar name { .Dl auth-group Ar name .Dl portal-group Ar name Op Ar agname +.Dl port Ar name .Dl lun Ar number Ar name .Dl lun Ar number No { .Dl path Ar path @@ -319,6 +320,10 @@ on TCP port 3260 on all configured IPv4 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 port Ar name +Assign specified CTL port (such as "isp0") to the target. +On startup ctld configures LUN mapping and enables all assigned ports. +Each port can be assigned to only one target. .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 Fri Feb 20 13:50:50 2015 (r279054) +++ stable/10/usr.sbin/ctld/ctld.c Fri Feb 20 17:09:49 2015 (r279055) @@ -93,6 +93,7 @@ conf_new(void) TAILQ_INIT(&conf->conf_auth_groups); TAILQ_INIT(&conf->conf_ports); TAILQ_INIT(&conf->conf_portal_groups); + TAILQ_INIT(&conf->conf_pports); TAILQ_INIT(&conf->conf_isns); conf->conf_isns_period = 900; @@ -111,6 +112,7 @@ conf_delete(struct conf *conf) struct target *targ, *tmp; struct auth_group *ag, *cagtmp; struct portal_group *pg, *cpgtmp; + struct pport *pp, *pptmp; struct isns *is, *istmp; assert(conf->conf_pidfh == NULL); @@ -123,6 +125,8 @@ conf_delete(struct conf *conf) auth_group_delete(ag); TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp) portal_group_delete(pg); + TAILQ_FOREACH_SAFE(pp, &conf->conf_pports, pp_next, pptmp) + pport_delete(pp); TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp) isns_delete(is); assert(TAILQ_EMPTY(&conf->conf_ports)); @@ -1133,21 +1137,72 @@ valid_iscsi_name(const char *name) return (true); } +struct pport * +pport_new(struct conf *conf, const char *name, uint32_t ctl_port) +{ + struct pport *pp; + + pp = calloc(1, sizeof(*pp)); + if (pp == NULL) + log_err(1, "calloc"); + pp->pp_conf = conf; + pp->pp_name = checked_strdup(name); + pp->pp_ctl_port = ctl_port; + TAILQ_INIT(&pp->pp_ports); + TAILQ_INSERT_TAIL(&conf->conf_pports, pp, pp_next); + return (pp); +} + +struct pport * +pport_find(const struct conf *conf, const char *name) +{ + struct pport *pp; + + TAILQ_FOREACH(pp, &conf->conf_pports, pp_next) { + if (strcasecmp(pp->pp_name, name) == 0) + return (pp); + } + return (NULL); +} + +struct pport * +pport_copy(struct pport *pp, struct conf *conf) +{ + struct pport *ppnew; + + ppnew = pport_new(conf, pp->pp_name, pp->pp_ctl_port); + return (ppnew); +} + +void +pport_delete(struct pport *pp) +{ + struct port *port, *tport; + + TAILQ_FOREACH_SAFE(port, &pp->pp_ports, p_ts, tport) + port_delete(port); + TAILQ_REMOVE(&pp->pp_conf->conf_pports, pp, pp_next); + free(pp->pp_name); + free(pp); +} + struct port * port_new(struct conf *conf, struct target *target, struct portal_group *pg) { struct port *port; + char *name; + asprintf(&name, "%s-%s", pg->pg_name, target->t_name); + if (port_find(conf, name) != NULL) { + log_warnx("duplicate port \"%s\"", name); + free(name); + return (NULL); + } 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; + port->p_name = name; TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next); TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts); port->p_target = target; @@ -1157,6 +1212,31 @@ port_new(struct conf *conf, struct targe } struct port * +port_new_pp(struct conf *conf, struct target *target, struct pport *pp) +{ + struct port *port; + char *name; + + asprintf(&name, "%s-%s", pp->pp_name, target->t_name); + if (port_find(conf, name) != NULL) { + log_warnx("duplicate port \"%s\"", name); + free(name); + return (NULL); + } + port = calloc(1, sizeof(*port)); + if (port == NULL) + log_err(1, "calloc"); + port->p_conf = conf; + port->p_name = name; + 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(&pp->pp_ports, port, p_pps); + port->p_pport = pp; + return (port); +} + +struct port * port_find(const struct conf *conf, const char *name) { struct port *port; @@ -1188,6 +1268,8 @@ port_delete(struct port *port) if (port->p_portal_group) TAILQ_REMOVE(&port->p_portal_group->pg_ports, port, p_pgs); + if (port->p_pport) + TAILQ_REMOVE(&port->p_pport->pp_ports, port, p_pps); if (port->p_target) TAILQ_REMOVE(&port->p_target->t_ports, port, p_ts); TAILQ_REMOVE(&port->p_conf->conf_ports, port, p_next); @@ -1761,6 +1843,7 @@ conf_apply(struct conf *oldconf, struct newport = port_find(newconf, oldport->p_name); if (newport != NULL) continue; + log_debugx("removing port \"%s\"", oldport->p_name); error = kernel_port_remove(oldport); if (error != 0) { log_warnx("failed to remove port %s", @@ -1885,8 +1968,10 @@ conf_apply(struct conf *oldconf, struct oldport = port_find(oldconf, newport->p_name); if (oldport == NULL) { + log_debugx("adding port \"%s\"", newport->p_name); error = kernel_port_add(newport); } else { + log_debugx("updating port \"%s\"", newport->p_name); newport->p_ctl_port = oldport->p_ctl_port; error = kernel_port_update(newport); } @@ -2398,7 +2483,7 @@ main(int argc, char **argv) kernel_init(); oldconf = conf_new_from_kernel(); - newconf = conf_new_from_file(config_path); + newconf = conf_new_from_file(config_path, oldconf); if (newconf == NULL) log_errx(1, "configuration error; exiting"); if (debug > 0) { @@ -2433,7 +2518,7 @@ main(int argc, char **argv) if (sighup_received) { sighup_received = false; log_debugx("received SIGHUP, reloading configuration"); - tmpconf = conf_new_from_file(config_path); + tmpconf = conf_new_from_file(config_path, newconf); if (tmpconf == NULL) { log_warnx("configuration error, " "continuing with old configuration"); Modified: stable/10/usr.sbin/ctld/ctld.h ============================================================================== --- stable/10/usr.sbin/ctld/ctld.h Fri Feb 20 13:50:50 2015 (r279054) +++ stable/10/usr.sbin/ctld/ctld.h Fri Feb 20 17:09:49 2015 (r279055) @@ -125,14 +125,25 @@ struct portal_group { uint16_t pg_tag; }; +struct pport { + TAILQ_ENTRY(pport) pp_next; + TAILQ_HEAD(, port) pp_ports; + struct conf *pp_conf; + char *pp_name; + + uint32_t pp_ctl_port; +}; + struct port { TAILQ_ENTRY(port) p_next; TAILQ_ENTRY(port) p_pgs; + TAILQ_ENTRY(port) p_pps; 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 pport *p_pport; struct target *p_target; uint32_t p_ctl_port; @@ -186,6 +197,7 @@ struct conf { TAILQ_HEAD(, auth_group) conf_auth_groups; TAILQ_HEAD(, port) conf_ports; TAILQ_HEAD(, portal_group) conf_portal_groups; + TAILQ_HEAD(, pport) conf_pports; TAILQ_HEAD(, isns) conf_isns; int conf_isns_period; int conf_isns_timeout; @@ -278,7 +290,7 @@ char *rchap_get_response(struct rchap void rchap_delete(struct rchap *rchap); struct conf *conf_new(void); -struct conf *conf_new_from_file(const char *path); +struct conf *conf_new_from_file(const char *path, struct conf *old); struct conf *conf_new_from_kernel(void); void conf_delete(struct conf *conf); int conf_verify(struct conf *conf); @@ -331,8 +343,16 @@ void isns_register(struct isns *isns, void isns_check(struct isns *isns); void isns_deregister(struct isns *isns); +struct pport *pport_new(struct conf *conf, const char *name, + uint32_t ctl_port); +struct pport *pport_find(const struct conf *conf, const char *name); +struct pport *pport_copy(struct pport *pport, struct conf *conf); +void pport_delete(struct pport *pport); + struct port *port_new(struct conf *conf, struct target *target, struct portal_group *pg); +struct port *port_new_pp(struct conf *conf, struct target *target, + struct pport *pp); 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); Modified: stable/10/usr.sbin/ctld/kernel.c ============================================================================== --- stable/10/usr.sbin/ctld/kernel.c Fri Feb 20 13:50:50 2015 (r279054) +++ stable/10/usr.sbin/ctld/kernel.c Fri Feb 20 17:09:49 2015 (r279055) @@ -121,6 +121,7 @@ struct cctl_lun { struct cctl_port { uint32_t port_id; + char *port_name; int cfiscsi_state; char *cfiscsi_target; uint16_t cfiscsi_portal_group_tag; @@ -330,7 +331,10 @@ cctl_end_pelement(void *user_data, const devlist->cur_sb[devlist->level] = NULL; devlist->level--; - if (strcmp(name, "cfiscsi_target") == 0) { + if (strcmp(name, "port_name") == 0) { + cur_port->port_name = str; + str = NULL; + } else if (strcmp(name, "cfiscsi_target") == 0) { cur_port->cfiscsi_target = str; str = NULL; } else if (strcmp(name, "cfiscsi_state") == 0) { @@ -378,6 +382,7 @@ conf_new_from_kernel(void) struct conf *conf = NULL; struct target *targ; struct portal_group *pg; + struct pport *pp; struct port *cp; struct lun *cl; struct lun_option *lo; @@ -498,8 +503,20 @@ retry_port: STAILQ_FOREACH(port, &devlist.port_list, links) { if (port->cfiscsi_target == NULL) { - log_debugx("CTL port %ju wasn't managed by ctld; " - "ignoring", (uintmax_t)port->port_id); + log_debugx("CTL port %u \"%s\" wasn't managed by ctld; ", + port->port_id, port->port_name); + pp = pport_find(conf, port->port_name); + if (pp == NULL) { +#if 0 + log_debugx("found new kernel port %u \"%s\"", + port->port_id, port->port_name); +#endif + pp = pport_new(conf, port->port_name, port->port_id); + if (pp == NULL) { + log_warnx("pport_new failed"); + continue; + } + } continue; } if (port->cfiscsi_state != 1) { @@ -843,39 +860,42 @@ kernel_port_add(struct port *port) int error, i, n; /* Create iSCSI port. */ - bzero(&req, sizeof(req)); - strlcpy(req.driver, "iscsi", sizeof(req.driver)); - req.reqtype = CTL_REQ_CREATE; - req.args = malloc(req.num_args * sizeof(*req.args)); - 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[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) { - log_warn("error issuing CTL_PORT_REQ ioctl"); - return (1); - } - if (req.status == CTL_LUN_ERROR) { - log_warnx("error returned from port creation request: %s", - req.error_str); - return (1); - } - if (req.status != CTL_LUN_OK) { - log_warnx("unknown port creation request status %d", - req.status); - return (1); - } + if (port->p_portal_group) { + bzero(&req, sizeof(req)); + strlcpy(req.driver, "iscsi", sizeof(req.driver)); + req.reqtype = CTL_REQ_CREATE; + req.args = malloc(req.num_args * sizeof(*req.args)); + 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[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) { + log_warn("error issuing CTL_PORT_REQ ioctl"); + return (1); + } + if (req.status == CTL_LUN_ERROR) { + log_warnx("error returned from port creation request: %s", + req.error_str); + return (1); + } + if (req.status != CTL_LUN_OK) { + log_warnx("unknown port creation request status %d", + req.status); + return (1); + } + } else if (port->p_pport) + port->p_ctl_port = port->p_pport->pp_ctl_port; /* Explicitly enable mapping to block any access except allowed. */ lm.port = port->p_ctl_port; @@ -934,40 +954,58 @@ kernel_port_update(struct port *port) int kernel_port_remove(struct port *port) { + struct ctl_port_entry entry; + struct ctl_lun_map lm; 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)); - strlcpy(req.driver, "iscsi", sizeof(req.driver)); - req.reqtype = CTL_REQ_REMOVE; - 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", pg->pg_tag); - str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr); - - error = ioctl(ctl_fd, CTL_PORT_REQ, &req); - free(req.args); + /* Disable port */ + bzero(&entry, sizeof(entry)); + entry.targ_port = port->p_ctl_port; + error = ioctl(ctl_fd, CTL_DISABLE_PORT, &entry); if (error != 0) { - log_warn("error issuing CTL_PORT_REQ ioctl"); - return (1); - } - - if (req.status == CTL_LUN_ERROR) { - log_warnx("error returned from port removal request: %s", - req.error_str); - return (1); + log_warn("CTL_DISABLE_PORT ioctl failed"); + return (-1); } - if (req.status != CTL_LUN_OK) { - log_warnx("unknown port removal request status %d", - req.status); - return (1); + /* Remove iSCSI port. */ + if (port->p_portal_group) { + bzero(&req, sizeof(req)); + strlcpy(req.driver, "iscsi", sizeof(req.driver)); + req.reqtype = CTL_REQ_REMOVE; + 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", pg->pg_tag); + str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr); + error = ioctl(ctl_fd, CTL_PORT_REQ, &req); + free(req.args); + if (error != 0) { + log_warn("error issuing CTL_PORT_REQ ioctl"); + return (1); + } + if (req.status == CTL_LUN_ERROR) { + log_warnx("error returned from port removal request: %s", + req.error_str); + return (1); + } + if (req.status != CTL_LUN_OK) { + log_warnx("unknown port removal request status %d", + req.status); + return (1); + } + } else { + /* Disable LUN mapping. */ + lm.port = port->p_ctl_port; + lm.plun = UINT32_MAX; + lm.lun = UINT32_MAX; + error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); + if (error != 0) + log_warn("CTL_LUN_MAP ioctl failed"); } - return (0); } Modified: stable/10/usr.sbin/ctld/parse.y ============================================================================== --- stable/10/usr.sbin/ctld/parse.y Fri Feb 20 13:50:50 2015 (r279054) +++ stable/10/usr.sbin/ctld/parse.y Fri Feb 20 17:09:49 2015 (r279055) @@ -61,7 +61,7 @@ extern void yyrestart(FILE *); %token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT %token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION -%token PATH PIDFILE PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR +%token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR %token TARGET TIMEOUT %union @@ -465,6 +465,8 @@ target_entry: | target_portal_group | + target_port + | target_redirect | target_lun @@ -708,6 +710,36 @@ target_portal_group: PORTAL_GROUP STR ST } ; +target_port: PORT STR + { + struct pport *pp; + struct port *tp; + + pp = pport_find(conf, $2); + if (pp == NULL) { + log_warnx("unknown port \"%s\" for target \"%s\"", + $2, target->t_name); + free($2); + return (1); + } + if (!TAILQ_EMPTY(&pp->pp_ports)) { + log_warnx("can't link port \"%s\" to target \"%s\", " + "port already linked to some target", + $2, target->t_name); + free($2); + return (1); + } + tp = port_new_pp(conf, target, pp); + if (tp == NULL) { + log_warnx("can't link port \"%s\" to target \"%s\"", + $2, target->t_name); + free($2); + return (1); + } + free($2); + } + ; + target_redirect: REDIRECT STR { int error; @@ -937,16 +969,20 @@ check_perms(const char *path) } struct conf * -conf_new_from_file(const char *path) +conf_new_from_file(const char *path, struct conf *oldconf) { struct auth_group *ag; struct portal_group *pg; + struct pport *pp; int error; log_debugx("obtaining configuration from %s", path); conf = conf_new(); + TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) + pport_copy(pp, conf); + ag = auth_group_new(conf, "default"); assert(ag != NULL); Modified: stable/10/usr.sbin/ctld/token.l ============================================================================== --- stable/10/usr.sbin/ctld/token.l Fri Feb 20 13:50:50 2015 (r279054) +++ stable/10/usr.sbin/ctld/token.l Fri Feb 20 17:09:49 2015 (r279055) @@ -71,6 +71,7 @@ pidfile { return PIDFILE; } isns-server { return ISNS_SERVER; } isns-period { return ISNS_PERIOD; } isns-timeout { return ISNS_TIMEOUT; } +port { return PORT; } portal-group { return PORTAL_GROUP; } redirect { return REDIRECT; } serial { return SERIAL; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502201709.t1KH9o5o070617>