CTL LUN mapping rewrite.
Replace iSCSI-specific LUN mapping mechanism with new one, working for any ports. By default all ports are created without LUN mapping, exposing all CTL LUNs as before. But, if needed, LUN mapping can be manually set on per-port basis via ctladm. For its iSCSI ports ctld does it via ioctl(2). The next step will be to teach ctld to work with FibreChannel ports also. Respecting additional flexibility of the new mechanism, ctl.conf now allows alternative syntax for LUN definition. LUNs can now be defined in global context, and then referenced from targets by unique name, as needed. It allows same LUN to be exposed several times via multiple targets. While there, increase limit for LUNs per target in ctld from 256 to 1024. Some initiators do not support LUNs above 255, but that is not our problem. Discussed with: trasz MFC after: 2 weeks Relnotes: yes Sponsored by: iXsystems, Inc.
This commit is contained in:
parent
b1877a0b39
commit
920c6cbadc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=278037
@ -398,12 +398,11 @@ static int ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num,
|
||||
struct ctl_ooa_entry *kern_entries);
|
||||
static int ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct thread *td);
|
||||
static uint32_t ctl_map_lun(struct ctl_softc *softc, int port_num, uint32_t lun);
|
||||
static uint32_t ctl_map_lun_back(struct ctl_softc *softc, int port_num, uint32_t lun);
|
||||
static int ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
|
||||
struct ctl_be_lun *be_lun, struct ctl_id target_id);
|
||||
static int ctl_free_lun(struct ctl_lun *lun);
|
||||
static void ctl_create_lun(struct ctl_be_lun *be_lun);
|
||||
static struct ctl_port * ctl_io_port(struct ctl_io_hdr *io_hdr);
|
||||
/**
|
||||
static void ctl_failover_change_pages(struct ctl_softc *softc,
|
||||
struct ctl_scsiio *ctsio, int master);
|
||||
@ -3411,6 +3410,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct ctl_lun_list *list;
|
||||
struct ctl_option *opt;
|
||||
int j;
|
||||
uint32_t plun;
|
||||
|
||||
list = (struct ctl_lun_list *)addr;
|
||||
|
||||
@ -3491,6 +3491,18 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
break;
|
||||
}
|
||||
|
||||
if (port->lun_map != NULL) {
|
||||
sbuf_printf(sb, "\t<lun_map>on</lun_map>\n");
|
||||
for (j = 0; j < CTL_MAX_LUNS; j++) {
|
||||
plun = ctl_lun_map_from_port(port, j);
|
||||
if (plun >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
sbuf_printf(sb,
|
||||
"\t<lun id=\"%u\">%u</lun>\n",
|
||||
j, plun);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < CTL_MAX_INIT_PER_PORT; j++) {
|
||||
if (port->wwpn_iid[j].in_use == 0 ||
|
||||
(port->wwpn_iid[j].wwpn == 0 &&
|
||||
@ -3538,6 +3550,38 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
sbuf_delete(sb);
|
||||
break;
|
||||
}
|
||||
case CTL_LUN_MAP: {
|
||||
struct ctl_lun_map *lm = (struct ctl_lun_map *)addr;
|
||||
struct ctl_port *port;
|
||||
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
if (lm->port >= CTL_MAX_PORTS ||
|
||||
(port = softc->ctl_ports[lm->port]) == NULL) {
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
return (ENXIO);
|
||||
}
|
||||
if (lm->plun < CTL_MAX_LUNS) {
|
||||
if (lm->lun == UINT32_MAX)
|
||||
retval = ctl_lun_map_unset(port, lm->plun);
|
||||
else if (lm->lun < CTL_MAX_LUNS &&
|
||||
softc->ctl_luns[lm->lun] != NULL)
|
||||
retval = ctl_lun_map_set(port, lm->plun, lm->lun);
|
||||
else {
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
return (ENXIO);
|
||||
}
|
||||
} else if (lm->plun == UINT32_MAX) {
|
||||
if (lm->lun == UINT32_MAX)
|
||||
retval = ctl_lun_map_deinit(port);
|
||||
else
|
||||
retval = ctl_lun_map_init(port);
|
||||
} else {
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
return (ENXIO);
|
||||
}
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* XXX KDM should we fix this? */
|
||||
#if 0
|
||||
@ -3602,35 +3646,106 @@ ctl_port_idx(int port_num)
|
||||
return(port_num - CTL_MAX_PORTS);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ctl_map_lun(struct ctl_softc *softc, int port_num, uint32_t lun_id)
|
||||
int
|
||||
ctl_lun_map_init(struct ctl_port *port)
|
||||
{
|
||||
struct ctl_port *port;
|
||||
uint32_t i;
|
||||
|
||||
if (port->lun_map == NULL)
|
||||
port->lun_map = malloc(sizeof(uint32_t) * CTL_MAX_LUNS,
|
||||
M_CTL, M_NOWAIT);
|
||||
if (port->lun_map == NULL)
|
||||
return (ENOMEM);
|
||||
for (i = 0; i < CTL_MAX_LUNS; i++)
|
||||
port->lun_map[i] = UINT32_MAX;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_lun_map_deinit(struct ctl_port *port)
|
||||
{
|
||||
|
||||
if (port->lun_map == NULL)
|
||||
return (0);
|
||||
free(port->lun_map, M_CTL);
|
||||
port->lun_map = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_lun_map_set(struct ctl_port *port, uint32_t plun, uint32_t glun)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (port->lun_map == NULL) {
|
||||
status = ctl_lun_map_init(port);
|
||||
if (status != 0)
|
||||
return (status);
|
||||
}
|
||||
port->lun_map[plun] = glun;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_lun_map_unset(struct ctl_port *port, uint32_t plun)
|
||||
{
|
||||
|
||||
if (port->lun_map == NULL)
|
||||
return (0);
|
||||
port->lun_map[plun] = UINT32_MAX;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_lun_map_unsetg(struct ctl_port *port, uint32_t glun)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (port->lun_map == NULL)
|
||||
return (0);
|
||||
for (i = 0; i < CTL_MAX_LUNS; i++) {
|
||||
if (port->lun_map[i] == glun)
|
||||
port->lun_map[i] = UINT32_MAX;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ctl_lun_map_from_port(struct ctl_port *port, uint32_t lun_id)
|
||||
{
|
||||
|
||||
if (port == NULL)
|
||||
return (UINT32_MAX);
|
||||
if (port->lun_map == NULL || lun_id >= CTL_MAX_LUNS)
|
||||
return (lun_id);
|
||||
return (port->lun_map[lun_id]);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ctl_lun_map_to_port(struct ctl_port *port, uint32_t lun_id)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
port = softc->ctl_ports[ctl_port_idx(port_num)];
|
||||
if (port == NULL)
|
||||
return (UINT32_MAX);
|
||||
if (port->lun_map == NULL)
|
||||
return (lun_id);
|
||||
return (port->lun_map(port->targ_lun_arg, lun_id));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ctl_map_lun_back(struct ctl_softc *softc, int port_num, uint32_t lun_id)
|
||||
{
|
||||
struct ctl_port *port;
|
||||
uint32_t i;
|
||||
|
||||
port = softc->ctl_ports[ctl_port_idx(port_num)];
|
||||
if (port->lun_map == NULL)
|
||||
return (lun_id);
|
||||
for (i = 0; i < CTL_MAX_LUNS; i++) {
|
||||
if (port->lun_map(port->targ_lun_arg, i) == lun_id)
|
||||
if (port->lun_map[i] == lun_id)
|
||||
return (i);
|
||||
}
|
||||
return (UINT32_MAX);
|
||||
}
|
||||
|
||||
static struct ctl_port *
|
||||
ctl_io_port(struct ctl_io_hdr *io_hdr)
|
||||
{
|
||||
int port_num;
|
||||
|
||||
port_num = io_hdr->nexus.targ_port;
|
||||
return (control_softc->ctl_ports[ctl_port_idx(port_num)]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: This only works for bitmask sizes that are at least 32 bits, and
|
||||
* that are a power of 2.
|
||||
@ -4676,9 +4791,7 @@ static int
|
||||
ctl_free_lun(struct ctl_lun *lun)
|
||||
{
|
||||
struct ctl_softc *softc;
|
||||
#if 0
|
||||
struct ctl_port *port;
|
||||
#endif
|
||||
struct ctl_lun *nlun;
|
||||
int i;
|
||||
|
||||
@ -4686,6 +4799,9 @@ ctl_free_lun(struct ctl_lun *lun)
|
||||
|
||||
mtx_assert(&softc->ctl_lock, MA_OWNED);
|
||||
|
||||
STAILQ_FOREACH(port, &softc->port_list, links)
|
||||
ctl_lun_map_unsetg(port, lun->lun);
|
||||
|
||||
STAILQ_REMOVE(&softc->lun_list, lun, ctl_lun, links);
|
||||
|
||||
ctl_clear_mask(softc->ctl_lun_mask, lun->lun);
|
||||
@ -7343,8 +7459,7 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
|
||||
STAILQ_FOREACH(port, &softc->port_list, links) {
|
||||
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
|
||||
continue;
|
||||
if (ctl_map_lun_back(softc, port->targ_port, lun->lun) >=
|
||||
CTL_MAX_LUNS)
|
||||
if (ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
num_target_ports++;
|
||||
}
|
||||
@ -7417,8 +7532,7 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
|
||||
STAILQ_FOREACH(port, &softc->port_list, links) {
|
||||
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
|
||||
continue;
|
||||
if (ctl_map_lun_back(softc, port->targ_port, lun->lun)
|
||||
>= CTL_MAX_LUNS)
|
||||
if (ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
p = port->targ_port % CTL_MAX_PORTS + g * CTL_MAX_PORTS;
|
||||
scsi_ulto2b(p, tpg_desc->descriptors[pc].
|
||||
@ -9260,6 +9374,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
struct scsi_report_luns *cdb;
|
||||
struct scsi_report_luns_data *lun_data;
|
||||
struct ctl_lun *lun, *request_lun;
|
||||
struct ctl_port *port;
|
||||
int num_luns, retval;
|
||||
uint32_t alloc_len, lun_datalen;
|
||||
int num_filled, well_known;
|
||||
@ -9316,6 +9431,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
|
||||
request_lun = (struct ctl_lun *)
|
||||
ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
|
||||
port = ctl_io_port(&ctsio->io_hdr);
|
||||
|
||||
lun_datalen = sizeof(*lun_data) +
|
||||
(num_luns * sizeof(struct scsi_report_luns_lundata));
|
||||
@ -9328,8 +9444,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
for (targ_lun_id = 0, num_filled = 0; targ_lun_id < CTL_MAX_LUNS && num_filled < num_luns; targ_lun_id++) {
|
||||
lun_id = ctl_map_lun(softc, ctsio->io_hdr.nexus.targ_port,
|
||||
targ_lun_id);
|
||||
lun_id = ctl_lun_map_from_port(port, targ_lun_id);
|
||||
if (lun_id >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
lun = softc->ctl_luns[lun_id];
|
||||
@ -10014,8 +10129,7 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
|
||||
continue;
|
||||
if (lun != NULL &&
|
||||
ctl_map_lun_back(softc, port->targ_port, lun->lun) >=
|
||||
CTL_MAX_LUNS)
|
||||
ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
num_target_ports++;
|
||||
if (port->init_devid)
|
||||
@ -10068,8 +10182,7 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
|
||||
continue;
|
||||
if (lun != NULL &&
|
||||
ctl_map_lun_back(softc, port->targ_port, lun->lun)
|
||||
>= CTL_MAX_LUNS)
|
||||
ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
p = port->targ_port % CTL_MAX_PORTS + g * CTL_MAX_PORTS;
|
||||
scsi_ulto2b(p, pd->relative_port_id);
|
||||
@ -13745,6 +13858,7 @@ int
|
||||
ctl_queue_sense(union ctl_io *io)
|
||||
{
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_port *port;
|
||||
struct ctl_softc *softc;
|
||||
uint32_t initidx, targ_lun;
|
||||
|
||||
@ -13765,8 +13879,8 @@ ctl_queue_sense(union ctl_io *io)
|
||||
* If we don't have a LUN for this, just toss the sense
|
||||
* information.
|
||||
*/
|
||||
targ_lun = io->io_hdr.nexus.targ_lun;
|
||||
targ_lun = ctl_map_lun(softc, io->io_hdr.nexus.targ_port, targ_lun);
|
||||
port = ctl_io_port(&ctsio->io_hdr);
|
||||
targ_lun = ctl_lun_map_from_port(port, io->io_hdr.nexus.targ_lun);
|
||||
if ((targ_lun < CTL_MAX_LUNS)
|
||||
&& (softc->ctl_luns[targ_lun] != NULL))
|
||||
lun = softc->ctl_luns[targ_lun];
|
||||
@ -13806,6 +13920,7 @@ ctl_queue_sense(union ctl_io *io)
|
||||
int
|
||||
ctl_queue(union ctl_io *io)
|
||||
{
|
||||
struct ctl_port *port;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_queue cdb[0]=%02X\n", io->scsiio.cdb[0]));
|
||||
|
||||
@ -13815,9 +13930,9 @@ ctl_queue(union ctl_io *io)
|
||||
#endif /* CTL_TIME_IO */
|
||||
|
||||
/* Map FE-specific LUN ID into global one. */
|
||||
port = ctl_io_port(&io->io_hdr);
|
||||
io->io_hdr.nexus.targ_mapped_lun =
|
||||
ctl_map_lun(control_softc, io->io_hdr.nexus.targ_port,
|
||||
io->io_hdr.nexus.targ_lun);
|
||||
ctl_lun_map_from_port(port, io->io_hdr.nexus.targ_lun);
|
||||
|
||||
switch (io->io_hdr.io_type) {
|
||||
case CTL_IO_SCSI:
|
||||
|
@ -234,6 +234,7 @@ ctl_port_deregister(struct ctl_port *port)
|
||||
ctl_pool_free(pool);
|
||||
ctl_free_opts(&port->options);
|
||||
|
||||
ctl_lun_map_deinit(port);
|
||||
free(port->port_devid, M_CTL);
|
||||
port->port_devid = NULL;
|
||||
free(port->target_devid, M_CTL);
|
||||
|
@ -51,7 +51,6 @@ typedef void (*fe_shutdown_t)(void);
|
||||
typedef void (*port_func_t)(void *onoff_arg);
|
||||
typedef int (*port_info_func_t)(void *onoff_arg, struct sbuf *sb);
|
||||
typedef int (*lun_func_t)(void *arg, struct ctl_id targ_id, int lun_id);
|
||||
typedef uint32_t (*lun_map_func_t)(void *arg, uint32_t lun_id);
|
||||
typedef int (*fe_ioctl_t)(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct thread *td);
|
||||
|
||||
@ -226,7 +225,7 @@ struct ctl_port {
|
||||
void *onoff_arg; /* passed to CTL */
|
||||
lun_func_t lun_enable; /* passed to CTL */
|
||||
lun_func_t lun_disable; /* passed to CTL */
|
||||
lun_map_func_t lun_map; /* passed to CTL */
|
||||
uint32_t *lun_map; /* passed to CTL */
|
||||
void *targ_lun_arg; /* passed to CTL */
|
||||
void (*fe_datamove)(union ctl_io *io); /* passed to CTL */
|
||||
void (*fe_done)(union ctl_io *io); /* passed to CTL */
|
||||
|
@ -151,7 +151,6 @@ static int cfiscsi_lun_enable(void *arg,
|
||||
struct ctl_id target_id, int lun_id);
|
||||
static int cfiscsi_lun_disable(void *arg,
|
||||
struct ctl_id target_id, int lun_id);
|
||||
static uint32_t cfiscsi_lun_map(void *arg, uint32_t lun);
|
||||
static int cfiscsi_ioctl(struct cdev *dev,
|
||||
u_long cmd, caddr_t addr, int flag, struct thread *td);
|
||||
static void cfiscsi_datamove(union ctl_io *io);
|
||||
@ -2031,7 +2030,6 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
|
||||
port->onoff_arg = ct;
|
||||
port->lun_enable = cfiscsi_lun_enable;
|
||||
port->lun_disable = cfiscsi_lun_disable;
|
||||
port->lun_map = cfiscsi_lun_map;
|
||||
port->targ_lun_arg = ct;
|
||||
port->fe_datamove = cfiscsi_datamove;
|
||||
port->fe_done = cfiscsi_done;
|
||||
@ -2081,7 +2079,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
|
||||
free(port->target_devid, M_CFISCSI);
|
||||
req->status = CTL_LUN_ERROR;
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"ctl_frontend_register() failed with error %d", retval);
|
||||
"ctl_port_register() failed with error %d", retval);
|
||||
return;
|
||||
}
|
||||
done:
|
||||
@ -2259,7 +2257,6 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
|
||||
const char *alias)
|
||||
{
|
||||
struct cfiscsi_target *ct, *newct;
|
||||
int i;
|
||||
|
||||
if (name[0] == '\0' || strlen(name) >= CTL_ISCSI_NAME_LEN)
|
||||
return (NULL);
|
||||
@ -2277,9 +2274,6 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
|
||||
return (ct);
|
||||
}
|
||||
|
||||
for (i = 0; i < CTL_MAX_LUNS; i++)
|
||||
newct->ct_luns[i] = UINT32_MAX;
|
||||
|
||||
strlcpy(newct->ct_name, name, sizeof(newct->ct_name));
|
||||
if (alias != NULL)
|
||||
strlcpy(newct->ct_alias, alias, sizeof(newct->ct_alias));
|
||||
@ -2294,108 +2288,17 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
|
||||
return (newct);
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes LUN from the target space and returns LUN from the CTL space.
|
||||
*/
|
||||
static uint32_t
|
||||
cfiscsi_lun_map(void *arg, uint32_t lun)
|
||||
{
|
||||
struct cfiscsi_target *ct = arg;
|
||||
|
||||
if (lun >= CTL_MAX_LUNS) {
|
||||
CFISCSI_DEBUG("requested lun number %d is higher "
|
||||
"than maximum %d", lun, CTL_MAX_LUNS - 1);
|
||||
return (UINT32_MAX);
|
||||
}
|
||||
return (ct->ct_luns[lun]);
|
||||
}
|
||||
|
||||
static int
|
||||
cfiscsi_target_set_lun(struct cfiscsi_target *ct,
|
||||
unsigned long lun_id, unsigned long ctl_lun_id)
|
||||
{
|
||||
|
||||
if (lun_id >= CTL_MAX_LUNS) {
|
||||
CFISCSI_WARN("requested lun number %ld is higher "
|
||||
"than maximum %d", lun_id, CTL_MAX_LUNS - 1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (ct->ct_luns[lun_id] < CTL_MAX_LUNS) {
|
||||
/*
|
||||
* CTL calls cfiscsi_lun_enable() twice for each LUN - once
|
||||
* when the LUN is created, and a second time just before
|
||||
* the port is brought online; don't emit warnings
|
||||
* for that case.
|
||||
*/
|
||||
if (ct->ct_luns[lun_id] == ctl_lun_id)
|
||||
return (0);
|
||||
CFISCSI_WARN("lun %ld already allocated", lun_id);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
CFISCSI_DEBUG("adding mapping for lun %ld, target %s "
|
||||
"to ctl lun %ld", lun_id, ct->ct_name, ctl_lun_id);
|
||||
#endif
|
||||
|
||||
ct->ct_luns[lun_id] = ctl_lun_id;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cfiscsi_lun_enable(void *arg, struct ctl_id target_id, int lun_id)
|
||||
{
|
||||
struct cfiscsi_softc *softc;
|
||||
struct cfiscsi_target *ct;
|
||||
const char *target = NULL;
|
||||
const char *lun = NULL;
|
||||
unsigned long tmp;
|
||||
|
||||
ct = (struct cfiscsi_target *)arg;
|
||||
softc = ct->ct_softc;
|
||||
|
||||
target = ctl_get_opt(&control_softc->ctl_luns[lun_id]->be_lun->options,
|
||||
"cfiscsi_target");
|
||||
lun = ctl_get_opt(&control_softc->ctl_luns[lun_id]->be_lun->options,
|
||||
"cfiscsi_lun");
|
||||
|
||||
if (target == NULL && lun == NULL)
|
||||
return (0);
|
||||
|
||||
if (target == NULL || lun == NULL) {
|
||||
CFISCSI_WARN("lun added with cfiscsi_target, but without "
|
||||
"cfiscsi_lun, or the other way around; ignoring");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (strcmp(target, ct->ct_name) != 0)
|
||||
return (0);
|
||||
|
||||
tmp = strtoul(lun, NULL, 10);
|
||||
cfiscsi_target_set_lun(ct, tmp, lun_id);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cfiscsi_lun_disable(void *arg, struct ctl_id target_id, int lun_id)
|
||||
{
|
||||
struct cfiscsi_softc *softc;
|
||||
struct cfiscsi_target *ct;
|
||||
int i;
|
||||
|
||||
ct = (struct cfiscsi_target *)arg;
|
||||
softc = ct->ct_softc;
|
||||
|
||||
mtx_lock(&softc->lock);
|
||||
for (i = 0; i < CTL_MAX_LUNS; i++) {
|
||||
if (ct->ct_luns[i] != lun_id)
|
||||
continue;
|
||||
ct->ct_luns[i] = UINT32_MAX;
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&softc->lock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,6 @@
|
||||
|
||||
struct cfiscsi_target {
|
||||
TAILQ_ENTRY(cfiscsi_target) ct_next;
|
||||
uint32_t ct_luns[CTL_MAX_LUNS];
|
||||
struct cfiscsi_softc *ct_softc;
|
||||
volatile u_int ct_refcount;
|
||||
char ct_name[CTL_ISCSI_NAME_LEN];
|
||||
|
@ -805,6 +805,12 @@ struct ctl_iscsi {
|
||||
/* passed to userland */
|
||||
};
|
||||
|
||||
struct ctl_lun_map {
|
||||
uint32_t port;
|
||||
uint32_t plun;
|
||||
uint32_t lun;
|
||||
};
|
||||
|
||||
#define CTL_IO _IOWR(CTL_MINOR, 0x00, union ctl_io)
|
||||
#define CTL_ENABLE_PORT _IOW(CTL_MINOR, 0x04, struct ctl_port_entry)
|
||||
#define CTL_DISABLE_PORT _IOW(CTL_MINOR, 0x05, struct ctl_port_entry)
|
||||
@ -832,6 +838,7 @@ struct ctl_iscsi {
|
||||
#define CTL_ISCSI _IOWR(CTL_MINOR, 0x25, struct ctl_iscsi)
|
||||
#define CTL_PORT_REQ _IOWR(CTL_MINOR, 0x26, struct ctl_req)
|
||||
#define CTL_PORT_LIST _IOWR(CTL_MINOR, 0x27, struct ctl_lun_list)
|
||||
#define CTL_LUN_MAP _IOW(CTL_MINOR, 0x28, struct ctl_lun_map)
|
||||
|
||||
#endif /* _CTL_IOCTL_H_ */
|
||||
|
||||
|
@ -492,6 +492,13 @@ extern const struct ctl_cmd_entry ctl_cmd_table[256];
|
||||
uint32_t ctl_get_initindex(struct ctl_nexus *nexus);
|
||||
uint32_t ctl_get_resindex(struct ctl_nexus *nexus);
|
||||
uint32_t ctl_port_idx(int port_num);
|
||||
int ctl_lun_map_init(struct ctl_port *port);
|
||||
int ctl_lun_map_deinit(struct ctl_port *port);
|
||||
int ctl_lun_map_set(struct ctl_port *port, uint32_t plun, uint32_t glun);
|
||||
int ctl_lun_map_unset(struct ctl_port *port, uint32_t plun);
|
||||
int ctl_lun_map_unsetg(struct ctl_port *port, uint32_t glun);
|
||||
uint32_t ctl_lun_map_from_port(struct ctl_port *port, uint32_t plun);
|
||||
uint32_t ctl_lun_map_to_port(struct ctl_port *port, uint32_t glun);
|
||||
int ctl_pool_create(struct ctl_softc *ctl_softc, const char *pool_name,
|
||||
uint32_t total_ctl_io, void **npool);
|
||||
void ctl_pool_free(struct ctl_io_pool *pool);
|
||||
|
@ -314,48 +314,30 @@ tpcl_resolve(struct ctl_softc *softc, int init_port,
|
||||
struct scsi_ec_cscd_id *cscdid;
|
||||
struct ctl_port *port;
|
||||
struct ctl_lun *lun;
|
||||
uint64_t lunid = UINT64_MAX, l;
|
||||
int i;
|
||||
uint64_t lunid = UINT64_MAX;
|
||||
|
||||
if (cscd->type_code != EC_CSCD_ID)
|
||||
return (lunid);
|
||||
|
||||
cscdid = (struct scsi_ec_cscd_id *)cscd;
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
if (init_port >= 0) {
|
||||
if (init_port >= 0)
|
||||
port = softc->ctl_ports[ctl_port_idx(init_port)];
|
||||
if (port == NULL || port->lun_map == NULL)
|
||||
init_port = -1;
|
||||
}
|
||||
if (init_port < 0) {
|
||||
STAILQ_FOREACH(lun, &softc->lun_list, links) {
|
||||
if (lun->lun_devid == NULL)
|
||||
continue;
|
||||
if (scsi_devid_match(lun->lun_devid->data,
|
||||
lun->lun_devid->len, &cscdid->codeset,
|
||||
cscdid->length + 4) == 0) {
|
||||
lunid = lun->lun;
|
||||
if (ss && lun->be_lun)
|
||||
*ss = lun->be_lun->blocksize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < CTL_MAX_LUNS; i++) {
|
||||
l = port->lun_map(port->targ_lun_arg, i);
|
||||
if (l >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
lun = softc->ctl_luns[l];
|
||||
if (lun == NULL || lun->lun_devid == NULL)
|
||||
continue;
|
||||
if (scsi_devid_match(lun->lun_devid->data,
|
||||
lun->lun_devid->len, &cscdid->codeset,
|
||||
cscdid->length + 4) == 0) {
|
||||
lunid = lun->lun;
|
||||
if (ss && lun->be_lun)
|
||||
*ss = lun->be_lun->blocksize;
|
||||
break;
|
||||
}
|
||||
else
|
||||
port = NULL;
|
||||
STAILQ_FOREACH(lun, &softc->lun_list, links) {
|
||||
if (port != NULL &&
|
||||
ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
if (lun->lun_devid == NULL)
|
||||
continue;
|
||||
if (scsi_devid_match(lun->lun_devid->data,
|
||||
lun->lun_devid->len, &cscdid->codeset,
|
||||
cscdid->length + 4) == 0) {
|
||||
lunid = lun->lun;
|
||||
if (ss && lun->be_lun)
|
||||
*ss = lun->be_lun->blocksize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
|
@ -34,7 +34,7 @@
|
||||
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 17, 2014
|
||||
.Dd February 1, 2015
|
||||
.Dt CTLADM 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -196,11 +196,17 @@
|
||||
.Ic portlist
|
||||
.Op Fl f Ar frontend
|
||||
.Op Fl i
|
||||
.Op Fl l
|
||||
.Op Fl p Ar targ_port
|
||||
.Op Fl q
|
||||
.Op Fl v
|
||||
.Op Fl x
|
||||
.Nm
|
||||
.Ic lunmap
|
||||
.Aq Fl p Ar targ_port
|
||||
.Op Fl l Ar pLUN
|
||||
.Op Fl L Ar cLUN
|
||||
.Nm
|
||||
.Ic dumpooa
|
||||
.Nm
|
||||
.Ic dumpstructs
|
||||
@ -782,7 +788,9 @@ List CTL frontend ports.
|
||||
.It Fl f Ar frontend
|
||||
Specify the frontend type.
|
||||
.It Fl i
|
||||
Report target and connected initiators addresses
|
||||
Report target and connected initiators addresses.
|
||||
.It Fl l
|
||||
Report LUN mapping.
|
||||
.It Fl p Ar targ_port
|
||||
Specify the frontend port number.
|
||||
.It Fl q
|
||||
@ -792,6 +800,31 @@ Enable verbose output (report all port options).
|
||||
.It Fl x
|
||||
Output the port list in XML format.
|
||||
.El
|
||||
.It Ic lunmap
|
||||
Change LUN mapping for specified port.
|
||||
If both
|
||||
.Ar pLUN
|
||||
and
|
||||
.Ar cLUN
|
||||
are specified -- LUN will be mapped.
|
||||
If
|
||||
.Ar pLUN
|
||||
is specified, but
|
||||
.Ar cLUN
|
||||
is not -- LUN will be unmapped.
|
||||
If neither
|
||||
.Ar pLUN
|
||||
nor
|
||||
.Ar cLUN
|
||||
are specified -- LUN mapping will be disabled, exposing all CTL LUNs.
|
||||
.Bl -tag -width 12n
|
||||
.It Fl p Ar targ_port
|
||||
Specify the frontend port number.
|
||||
.It Fl l Ar pLUN
|
||||
LUN number visible by specified port.
|
||||
.It Fl L Ar cLUN
|
||||
CTL LUN number.
|
||||
.El
|
||||
.It Ic dumpooa
|
||||
Dump the OOA (Order Of Arrival) queue for each LUN registered with CTL.
|
||||
.It Ic dumpstructs
|
||||
|
@ -121,7 +121,8 @@ typedef enum {
|
||||
CTLADM_CMD_MODIFY,
|
||||
CTLADM_CMD_ISLIST,
|
||||
CTLADM_CMD_ISLOGOUT,
|
||||
CTLADM_CMD_ISTERMINATE
|
||||
CTLADM_CMD_ISTERMINATE,
|
||||
CTLADM_CMD_LUNMAP
|
||||
} ctladm_cmdfunction;
|
||||
|
||||
typedef enum {
|
||||
@ -188,10 +189,11 @@ static struct ctladm_opts option_table[] = {
|
||||
{"islogout", CTLADM_CMD_ISLOGOUT, CTLADM_ARG_NONE, "ac:i:p:"},
|
||||
{"isterminate", CTLADM_CMD_ISTERMINATE, CTLADM_ARG_NONE, "ac:i:p:"},
|
||||
{"lunlist", CTLADM_CMD_LUNLIST, CTLADM_ARG_NONE, NULL},
|
||||
{"lunmap", CTLADM_CMD_LUNMAP, CTLADM_ARG_NONE, "p:l:L:"},
|
||||
{"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"},
|
||||
{"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:s:"},
|
||||
{"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:p:qt:w:W:x"},
|
||||
{"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ip:qvx"},
|
||||
{"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ilp:qvx"},
|
||||
{"prin", CTLADM_CMD_PRES_IN, CTLADM_ARG_NEED_TL, "a:"},
|
||||
{"prout", CTLADM_CMD_PRES_OUT, CTLADM_ARG_NEED_TL, "a:k:r:s:"},
|
||||
{"read", CTLADM_CMD_READ, CTLADM_ARG_NEED_TL, rw_opts},
|
||||
@ -4106,8 +4108,9 @@ struct cctl_port {
|
||||
char *frontend_type;
|
||||
char *name;
|
||||
int pp, vp;
|
||||
char *target, *port;
|
||||
char *target, *port, *lun_map;
|
||||
STAILQ_HEAD(,cctl_lun_nv) init_list;
|
||||
STAILQ_HEAD(,cctl_lun_nv) lun_list;
|
||||
STAILQ_HEAD(,cctl_lun_nv) attr_list;
|
||||
STAILQ_ENTRY(cctl_port) links;
|
||||
};
|
||||
@ -4161,6 +4164,7 @@ cctl_start_pelement(void *user_data, const char *name, const char **attr)
|
||||
portlist->cur_port = cur_port;
|
||||
|
||||
STAILQ_INIT(&cur_port->init_list);
|
||||
STAILQ_INIT(&cur_port->lun_list);
|
||||
STAILQ_INIT(&cur_port->attr_list);
|
||||
cur_port->port_id = portlist->cur_id;
|
||||
STAILQ_INSERT_TAIL(&portlist->port_list, cur_port, links);
|
||||
@ -4220,6 +4224,9 @@ cctl_end_pelement(void *user_data, const char *name)
|
||||
} else if (strcmp(name, "port") == 0) {
|
||||
cur_port->port = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "lun_map") == 0) {
|
||||
cur_port->lun_map = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "targ_port") == 0) {
|
||||
portlist->cur_port = NULL;
|
||||
} else if (strcmp(name, "ctlportlist") == 0) {
|
||||
@ -4232,7 +4239,8 @@ cctl_end_pelement(void *user_data, const char *name)
|
||||
err(1, "%s: can't allocate %zd bytes for nv pair",
|
||||
__func__, sizeof(*nv));
|
||||
|
||||
if (strcmp(name, "initiator") == 0)
|
||||
if (strcmp(name, "initiator") == 0 ||
|
||||
strcmp(name, "lun") == 0)
|
||||
asprintf(&nv->name, "%ju", portlist->cur_id);
|
||||
else
|
||||
nv->name = strdup(name);
|
||||
@ -4244,6 +4252,8 @@ cctl_end_pelement(void *user_data, const char *name)
|
||||
str = NULL;
|
||||
if (strcmp(name, "initiator") == 0)
|
||||
STAILQ_INSERT_TAIL(&cur_port->init_list, nv, links);
|
||||
else if (strcmp(name, "lun") == 0)
|
||||
STAILQ_INSERT_TAIL(&cur_port->lun_list, nv, links);
|
||||
else
|
||||
STAILQ_INSERT_TAIL(&cur_port->attr_list, nv, links);
|
||||
}
|
||||
@ -4274,7 +4284,7 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt)
|
||||
int retval, c;
|
||||
char *frontend = NULL;
|
||||
uint64_t portarg = UINT64_MAX;
|
||||
int verbose = 0, init = 0, quiet = 0;
|
||||
int verbose = 0, init = 0, lun = 0, quiet = 0;
|
||||
|
||||
retval = 0;
|
||||
port_len = 4096;
|
||||
@ -4290,6 +4300,9 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt)
|
||||
case 'i':
|
||||
init++;
|
||||
break;
|
||||
case 'l':
|
||||
lun++;
|
||||
break;
|
||||
case 'p':
|
||||
portarg = strtoll(optarg, NULL, 0);
|
||||
break;
|
||||
@ -4381,6 +4394,17 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt)
|
||||
}
|
||||
}
|
||||
|
||||
if (lun || verbose) {
|
||||
if (port->lun_map) {
|
||||
STAILQ_FOREACH(nv, &port->lun_list, links)
|
||||
printf(" LUN %s: %s\n",
|
||||
nv->name, nv->value);
|
||||
if (STAILQ_EMPTY(&port->lun_list))
|
||||
printf(" No LUNs mapped\n");
|
||||
} else
|
||||
printf(" All LUNs mapped\n");
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
STAILQ_FOREACH(nv, &port->attr_list, links) {
|
||||
printf(" %s=%s\n", nv->name, nv->value);
|
||||
@ -4393,6 +4417,41 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
cctl_lunmap(int fd, int argc, char **argv, char *combinedopt)
|
||||
{
|
||||
struct ctl_lun_map lm;
|
||||
int retval = 0, c;
|
||||
|
||||
retval = 0;
|
||||
lm.port = UINT32_MAX;
|
||||
lm.plun = UINT32_MAX;
|
||||
lm.lun = UINT32_MAX;
|
||||
|
||||
while ((c = getopt(argc, argv, combinedopt)) != -1) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
lm.port = strtoll(optarg, NULL, 0);
|
||||
break;
|
||||
case 'l':
|
||||
lm.plun = strtoll(optarg, NULL, 0);
|
||||
break;
|
||||
case 'L':
|
||||
lm.lun = strtoll(optarg, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(fd, CTL_LUN_MAP, &lm) == -1) {
|
||||
warn("%s: error issuing CTL_LUN_MAP ioctl", __func__);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void
|
||||
usage(int error)
|
||||
{
|
||||
@ -4430,6 +4489,7 @@ usage(int error)
|
||||
" ctladm hardstop\n"
|
||||
" ctladm hardstart\n"
|
||||
" ctladm lunlist\n"
|
||||
" ctladm lunmap -p targ_port [-l pLUN] [-L cLUN]\n"
|
||||
" ctladm bbrread [dev_id] <-l lba> <-d datalen>\n"
|
||||
" ctladm delay [dev_id] <-l datamove|done> [-T oneshot|cont]\n"
|
||||
" [-t secs]\n"
|
||||
@ -4529,10 +4589,15 @@ usage(int error)
|
||||
"portlist options:\n"
|
||||
"-f fronetnd : specify frontend type\n"
|
||||
"-i : report target and initiators addresses\n"
|
||||
"-l : report LUN mapping\n"
|
||||
"-p targ_port : specify target port number\n"
|
||||
"-q : omit header in list output\n"
|
||||
"-v : verbose output (report all port options)\n"
|
||||
"-x : output port list in XML format\n"
|
||||
"lunmap options:\n"
|
||||
"-p targ_port : specify target port number\n"
|
||||
"-L pLUN : specify port-visible LUN\n"
|
||||
"-L cLUN : specify CTL LUN\n"
|
||||
"bbrread options:\n"
|
||||
"-l lba : starting LBA\n"
|
||||
"-d datalen : length, in bytes, to read\n",
|
||||
@ -4760,6 +4825,9 @@ main(int argc, char **argv)
|
||||
case CTLADM_CMD_PORTLIST:
|
||||
retval = cctl_portlist(fd, argc, argv, combinedopt);
|
||||
break;
|
||||
case CTLADM_CMD_LUNMAP:
|
||||
retval = cctl_lunmap(fd, argc, argv, combinedopt);
|
||||
break;
|
||||
case CTLADM_CMD_READCAPACITY:
|
||||
retval = cctl_read_capacity(fd, target, lun, initid, retries,
|
||||
argc, argv, combinedopt);
|
||||
|
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 24, 2014
|
||||
.Dd February 1, 2015
|
||||
.Dt CTL.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -60,9 +60,14 @@ file is:
|
||||
.Dl ...
|
||||
}
|
||||
|
||||
.No lun Ar name No {
|
||||
.Dl path Ar path
|
||||
}
|
||||
|
||||
.No target Ar name {
|
||||
.Dl auth-group Ar name
|
||||
.Dl portal-group Ar name
|
||||
.Dl lun Ar number Ar name
|
||||
.Dl lun Ar number No {
|
||||
.Dl path Ar path
|
||||
.Dl }
|
||||
@ -95,6 +100,10 @@ Create a
|
||||
configuration context,
|
||||
defining a new portal-group,
|
||||
which can then be assigned to any number of targets.
|
||||
.It Ic lun Ar name
|
||||
Create a
|
||||
.Sy lun
|
||||
configuration context, defining a LUN to be exported by some target(s).
|
||||
.It Ic target Ar name
|
||||
Create a
|
||||
.Sy target
|
||||
@ -312,6 +321,10 @@ IPv4 or IPv6 address to redirect initiators to.
|
||||
When configured, all initiators attempting to connect to this target
|
||||
will get redirected using "Target moved temporarily" login response.
|
||||
Redirection happens after successful authentication.
|
||||
.It Ic lun Ar number Ar name
|
||||
Export previously defined
|
||||
.Sy lun
|
||||
by the parent target.
|
||||
.It Ic lun Ar number
|
||||
Create a
|
||||
.Sy lun
|
||||
@ -387,21 +400,21 @@ target iqn.2012-06.com.example:target0 {
|
||||
}
|
||||
}
|
||||
|
||||
lun example_1 {
|
||||
path /dev/zvol/tank/example_1
|
||||
}
|
||||
|
||||
target iqn.2012-06.com.example:target1 {
|
||||
chap chapuser chapsecret
|
||||
lun 0 {
|
||||
path /dev/zvol/tank/example_1
|
||||
}
|
||||
lun 0 example_1
|
||||
}
|
||||
|
||||
target iqn.2012-06.com.example:target2 {
|
||||
auth-group ag0
|
||||
portal-group pg0
|
||||
lun 0 {
|
||||
path /dev/zvol/tank/example2_0
|
||||
}
|
||||
lun 0 example_1
|
||||
lun 1 {
|
||||
path /dev/zvol/tank/example2_1
|
||||
path /dev/zvol/tank/example_2
|
||||
option foo bar
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ conf_new(void)
|
||||
conf = calloc(1, sizeof(*conf));
|
||||
if (conf == NULL)
|
||||
log_err(1, "calloc");
|
||||
TAILQ_INIT(&conf->conf_luns);
|
||||
TAILQ_INIT(&conf->conf_targets);
|
||||
TAILQ_INIT(&conf->conf_auth_groups);
|
||||
TAILQ_INIT(&conf->conf_portal_groups);
|
||||
@ -104,6 +105,7 @@ conf_new(void)
|
||||
void
|
||||
conf_delete(struct conf *conf)
|
||||
{
|
||||
struct lun *lun, *ltmp;
|
||||
struct target *targ, *tmp;
|
||||
struct auth_group *ag, *cagtmp;
|
||||
struct portal_group *pg, *cpgtmp;
|
||||
@ -111,6 +113,8 @@ conf_delete(struct conf *conf)
|
||||
|
||||
assert(conf->conf_pidfh == NULL);
|
||||
|
||||
TAILQ_FOREACH_SAFE(lun, &conf->conf_luns, l_next, ltmp)
|
||||
lun_delete(lun);
|
||||
TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
|
||||
target_delete(targ);
|
||||
TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp)
|
||||
@ -1146,7 +1150,6 @@ target_new(struct conf *conf, const char *name)
|
||||
for (i = 0; i < len; i++)
|
||||
targ->t_name[i] = tolower(targ->t_name[i]);
|
||||
|
||||
TAILQ_INIT(&targ->t_luns);
|
||||
targ->t_conf = conf;
|
||||
TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
|
||||
|
||||
@ -1156,12 +1159,9 @@ target_new(struct conf *conf, const char *name)
|
||||
void
|
||||
target_delete(struct target *targ)
|
||||
{
|
||||
struct lun *lun, *tmp;
|
||||
|
||||
TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
|
||||
|
||||
TAILQ_FOREACH_SAFE(lun, &targ->t_luns, l_next, tmp)
|
||||
lun_delete(lun);
|
||||
free(targ->t_name);
|
||||
free(targ->t_redirection);
|
||||
free(targ);
|
||||
@ -1196,25 +1196,31 @@ 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 target *targ, int lun_id)
|
||||
lun_new(struct conf *conf, const char *name)
|
||||
{
|
||||
struct lun *lun;
|
||||
|
||||
lun = lun_find(targ, lun_id);
|
||||
lun = lun_find(conf, name);
|
||||
if (lun != NULL) {
|
||||
log_warnx("duplicated lun %d for target \"%s\"",
|
||||
lun_id, targ->t_name);
|
||||
log_warnx("duplicated lun \"%s\"", name);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
lun = calloc(1, sizeof(*lun));
|
||||
if (lun == NULL)
|
||||
log_err(1, "calloc");
|
||||
lun->l_lun = lun_id;
|
||||
lun->l_conf = conf;
|
||||
lun->l_name = checked_strdup(name);
|
||||
TAILQ_INIT(&lun->l_options);
|
||||
lun->l_target = targ;
|
||||
TAILQ_INSERT_TAIL(&targ->t_luns, lun, l_next);
|
||||
TAILQ_INSERT_TAIL(&conf->conf_luns, lun, l_next);
|
||||
|
||||
return (lun);
|
||||
}
|
||||
@ -1222,26 +1228,36 @@ lun_new(struct target *targ, int lun_id)
|
||||
void
|
||||
lun_delete(struct lun *lun)
|
||||
{
|
||||
struct target *targ;
|
||||
struct lun_option *lo, *tmp;
|
||||
int i;
|
||||
|
||||
TAILQ_REMOVE(&lun->l_target->t_luns, lun, l_next);
|
||||
TAILQ_FOREACH(targ, &lun->l_conf->conf_targets, t_next) {
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
if (targ->t_luns[i] == lun)
|
||||
targ->t_luns[i] = NULL;
|
||||
}
|
||||
}
|
||||
TAILQ_REMOVE(&lun->l_conf->conf_luns, lun, l_next);
|
||||
|
||||
TAILQ_FOREACH_SAFE(lo, &lun->l_options, lo_next, tmp)
|
||||
lun_option_delete(lo);
|
||||
free(lun->l_name);
|
||||
free(lun->l_backend);
|
||||
free(lun->l_device_id);
|
||||
free(lun->l_path);
|
||||
free(lun->l_scsiname);
|
||||
free(lun->l_serial);
|
||||
free(lun);
|
||||
}
|
||||
|
||||
struct lun *
|
||||
lun_find(const struct target *targ, int lun_id)
|
||||
lun_find(const struct conf *conf, const char *name)
|
||||
{
|
||||
struct lun *lun;
|
||||
|
||||
TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
|
||||
if (lun->l_lun == lun_id)
|
||||
TAILQ_FOREACH(lun, &conf->conf_luns, l_next) {
|
||||
if (strcmp(lun->l_name, name) == 0)
|
||||
return (lun);
|
||||
}
|
||||
|
||||
@ -1276,6 +1292,13 @@ lun_set_path(struct lun *lun, const char *value)
|
||||
lun->l_path = checked_strdup(value);
|
||||
}
|
||||
|
||||
void
|
||||
lun_set_scsiname(struct lun *lun, const char *value)
|
||||
{
|
||||
free(lun->l_scsiname);
|
||||
lun->l_scsiname = checked_strdup(value);
|
||||
}
|
||||
|
||||
void
|
||||
lun_set_serial(struct lun *lun, const char *value)
|
||||
{
|
||||
@ -1304,8 +1327,8 @@ lun_option_new(struct lun *lun, const char *name, const char *value)
|
||||
|
||||
lo = lun_option_find(lun, name);
|
||||
if (lo != NULL) {
|
||||
log_warnx("duplicated lun option %s for lun %d, target \"%s\"",
|
||||
name, lun->l_lun, lun->l_target->t_name);
|
||||
log_warnx("duplicated lun option \"%s\" for lun \"%s\"",
|
||||
name, lun->l_name);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -1410,18 +1433,18 @@ conf_print(struct conf *conf)
|
||||
fprintf(stderr, "\t listen %s\n", portal->p_listen);
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
TAILQ_FOREACH(lun, &conf->conf_luns, l_next) {
|
||||
fprintf(stderr, "\tlun %s {\n", lun->l_name);
|
||||
fprintf(stderr, "\t\tpath %s\n", lun->l_path);
|
||||
TAILQ_FOREACH(lo, &lun->l_options, lo_next)
|
||||
fprintf(stderr, "\t\toption %s %s\n",
|
||||
lo->lo_name, lo->lo_value);
|
||||
fprintf(stderr, "\t}\n");
|
||||
}
|
||||
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
|
||||
fprintf(stderr, "target %s {\n", targ->t_name);
|
||||
if (targ->t_alias != NULL)
|
||||
fprintf(stderr, "\t alias %s\n", targ->t_alias);
|
||||
TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
|
||||
fprintf(stderr, "\tlun %d {\n", lun->l_lun);
|
||||
fprintf(stderr, "\t\tpath %s\n", lun->l_path);
|
||||
TAILQ_FOREACH(lo, &lun->l_options, lo_next)
|
||||
fprintf(stderr, "\t\toption %s %s\n",
|
||||
lo->lo_name, lo->lo_value);
|
||||
fprintf(stderr, "\t}\n");
|
||||
}
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
}
|
||||
@ -1431,60 +1454,49 @@ static int
|
||||
conf_verify_lun(struct lun *lun)
|
||||
{
|
||||
const struct lun *lun2;
|
||||
const struct target *targ2;
|
||||
|
||||
if (lun->l_backend == NULL)
|
||||
lun_set_backend(lun, "block");
|
||||
if (strcmp(lun->l_backend, "block") == 0) {
|
||||
if (lun->l_path == NULL) {
|
||||
log_warnx("missing path for lun %d, target \"%s\"",
|
||||
lun->l_lun, lun->l_target->t_name);
|
||||
log_warnx("missing path for lun \"%s\"",
|
||||
lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
} else if (strcmp(lun->l_backend, "ramdisk") == 0) {
|
||||
if (lun->l_size == 0) {
|
||||
log_warnx("missing size for ramdisk-backed lun %d, "
|
||||
"target \"%s\"", lun->l_lun, lun->l_target->t_name);
|
||||
log_warnx("missing size for ramdisk-backed lun \"%s\"",
|
||||
lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
if (lun->l_path != NULL) {
|
||||
log_warnx("path must not be specified "
|
||||
"for ramdisk-backed lun %d, target \"%s\"",
|
||||
lun->l_lun, lun->l_target->t_name);
|
||||
"for ramdisk-backed lun \"%s\"",
|
||||
lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
if (lun->l_lun < 0 || lun->l_lun > 255) {
|
||||
log_warnx("invalid lun number for lun %d, target \"%s\"; "
|
||||
"must be between 0 and 255", lun->l_lun,
|
||||
lun->l_target->t_name);
|
||||
return (1);
|
||||
}
|
||||
if (lun->l_blocksize == 0) {
|
||||
lun_set_blocksize(lun, DEFAULT_BLOCKSIZE);
|
||||
} else if (lun->l_blocksize < 0) {
|
||||
log_warnx("invalid blocksize for lun %d, target \"%s\"; "
|
||||
"must be larger than 0", lun->l_lun, lun->l_target->t_name);
|
||||
log_warnx("invalid blocksize for lun \"%s\"; "
|
||||
"must be larger than 0", lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
if (lun->l_size != 0 && lun->l_size % lun->l_blocksize != 0) {
|
||||
log_warnx("invalid size for lun %d, target \"%s\"; "
|
||||
"must be multiple of blocksize", lun->l_lun,
|
||||
lun->l_target->t_name);
|
||||
log_warnx("invalid size for lun \"%s\"; "
|
||||
"must be multiple of blocksize", lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
TAILQ_FOREACH(targ2, &lun->l_target->t_conf->conf_targets, t_next) {
|
||||
TAILQ_FOREACH(lun2, &targ2->t_luns, l_next) {
|
||||
if (lun == lun2)
|
||||
continue;
|
||||
if (lun->l_path != NULL && lun2->l_path != NULL &&
|
||||
strcmp(lun->l_path, lun2->l_path) == 0) {
|
||||
log_debugx("WARNING: path \"%s\" duplicated "
|
||||
"between lun %d, target \"%s\", and "
|
||||
"lun %d, target \"%s\"", lun->l_path,
|
||||
lun->l_lun, lun->l_target->t_name,
|
||||
lun2->l_lun, lun2->l_target->t_name);
|
||||
}
|
||||
TAILQ_FOREACH(lun2, &lun->l_conf->conf_luns, l_next) {
|
||||
if (lun == lun2)
|
||||
continue;
|
||||
if (lun->l_path != NULL && lun2->l_path != NULL &&
|
||||
strcmp(lun->l_path, lun2->l_path) == 0) {
|
||||
log_debugx("WARNING: path \"%s\" duplicated "
|
||||
"between lun \"%s\", and "
|
||||
"lun \"%s\"", lun->l_path,
|
||||
lun->l_name, lun2->l_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1499,11 +1511,16 @@ conf_verify(struct conf *conf)
|
||||
struct target *targ;
|
||||
struct lun *lun;
|
||||
bool found;
|
||||
int error;
|
||||
int error, i;
|
||||
|
||||
if (conf->conf_pidfile_path == NULL)
|
||||
conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE);
|
||||
|
||||
TAILQ_FOREACH(lun, &conf->conf_luns, l_next) {
|
||||
error = conf_verify_lun(lun);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
|
||||
if (targ->t_auth_group == NULL) {
|
||||
targ->t_auth_group = auth_group_find(conf,
|
||||
@ -1516,11 +1533,9 @@ conf_verify(struct conf *conf)
|
||||
assert(targ->t_portal_group != NULL);
|
||||
}
|
||||
found = false;
|
||||
TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
|
||||
error = conf_verify_lun(lun);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
found = true;
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
if (targ->t_luns[i] != NULL)
|
||||
found = true;
|
||||
}
|
||||
if (!found && targ->t_redirection == NULL) {
|
||||
log_warnx("no LUNs defined for target \"%s\"",
|
||||
@ -1657,126 +1672,128 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
|
||||
* be somewhat hairy, though, and lun deletion failures don't
|
||||
* really happen, so leave it as it is for now.
|
||||
*/
|
||||
/*
|
||||
* First, remove any targets present in the old configuration
|
||||
* and missing in the new one.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
|
||||
/*
|
||||
* First, remove any targets present in the old configuration
|
||||
* and missing in the new one.
|
||||
*/
|
||||
newtarg = target_find(newconf, oldtarg->t_name);
|
||||
if (newtarg == NULL) {
|
||||
error = kernel_port_remove(oldtarg);
|
||||
if (newtarg != NULL)
|
||||
continue;
|
||||
error = kernel_port_remove(oldtarg);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove target %s",
|
||||
oldtarg->t_name);
|
||||
/*
|
||||
* XXX: Uncomment after fixing the root cause.
|
||||
*
|
||||
* cumulated_error++;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Second, remove any LUNs present in the old configuration
|
||||
* and missing in the new one.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(oldlun, &oldconf->conf_luns, l_next, tmplun) {
|
||||
newlun = lun_find(newconf, oldlun->l_name);
|
||||
if (newlun == NULL) {
|
||||
log_debugx("lun \"%s\", CTL lun %d "
|
||||
"not found in new configuration; "
|
||||
"removing", oldlun->l_name, oldlun->l_ctl_lun);
|
||||
error = kernel_lun_remove(oldlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove target %s",
|
||||
oldtarg->t_name);
|
||||
/*
|
||||
* XXX: Uncomment after fixing the root cause.
|
||||
*
|
||||
* cumulated_error++;
|
||||
*/
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next,
|
||||
tmplun) {
|
||||
log_debugx("target %s not found in new "
|
||||
"configuration; removing its lun %d, "
|
||||
"backed by CTL lun %d",
|
||||
oldtarg->t_name, oldlun->l_lun,
|
||||
oldlun->l_ctl_lun);
|
||||
error = kernel_lun_remove(oldlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove lun %d, "
|
||||
"target %s, CTL lun %d",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
cumulated_error++;
|
||||
}
|
||||
log_warnx("failed to remove lun \"%s\", "
|
||||
"CTL lun %d",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
cumulated_error++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second, remove any LUNs present in the old target
|
||||
* and missing in the new one.
|
||||
* Also remove the LUNs changed by more than size.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next, tmplun) {
|
||||
newlun = lun_find(newtarg, oldlun->l_lun);
|
||||
if (newlun == NULL) {
|
||||
log_debugx("lun %d, target %s, CTL lun %d "
|
||||
"not found in new configuration; "
|
||||
"removing", oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
error = kernel_lun_remove(oldlun);
|
||||
changed = 0;
|
||||
assert(oldlun->l_backend != NULL);
|
||||
assert(newlun->l_backend != NULL);
|
||||
if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) {
|
||||
log_debugx("backend for lun \"%s\", "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (oldlun->l_blocksize != newlun->l_blocksize) {
|
||||
log_debugx("blocksize for lun \"%s\", "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (newlun->l_device_id != NULL &&
|
||||
(oldlun->l_device_id == NULL ||
|
||||
strcmp(oldlun->l_device_id, newlun->l_device_id) !=
|
||||
0)) {
|
||||
log_debugx("device-id for lun \"%s\", "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (newlun->l_path != NULL &&
|
||||
(oldlun->l_path == NULL ||
|
||||
strcmp(oldlun->l_path, newlun->l_path) != 0)) {
|
||||
log_debugx("path for lun \"%s\", "
|
||||
"CTL lun %d, changed; removing",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (newlun->l_serial != NULL &&
|
||||
(oldlun->l_serial == NULL ||
|
||||
strcmp(oldlun->l_serial, newlun->l_serial) != 0)) {
|
||||
log_debugx("serial for lun \"%s\", "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (changed) {
|
||||
error = kernel_lun_remove(oldlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove lun \"%s\", "
|
||||
"CTL lun %d",
|
||||
oldlun->l_name, oldlun->l_ctl_lun);
|
||||
cumulated_error++;
|
||||
}
|
||||
lun_delete(oldlun);
|
||||
continue;
|
||||
}
|
||||
|
||||
lun_set_ctl_lun(newlun, oldlun->l_ctl_lun);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(newlun, &newconf->conf_luns, l_next, tmplun) {
|
||||
oldlun = lun_find(oldconf, newlun->l_name);
|
||||
if (oldlun != NULL) {
|
||||
if (newlun->l_size != oldlun->l_size ||
|
||||
newlun->l_size == 0) {
|
||||
log_debugx("resizing lun \"%s\", CTL lun %d",
|
||||
newlun->l_name, newlun->l_ctl_lun);
|
||||
error = kernel_lun_resize(newlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove lun %d, "
|
||||
"target %s, CTL lun %d",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
log_warnx("failed to "
|
||||
"resize lun \"%s\", CTL lun %d",
|
||||
newlun->l_name,
|
||||
newlun->l_ctl_lun);
|
||||
cumulated_error++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Also remove the LUNs changed by more than size.
|
||||
*/
|
||||
changed = 0;
|
||||
assert(oldlun->l_backend != NULL);
|
||||
assert(newlun->l_backend != NULL);
|
||||
if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) {
|
||||
log_debugx("backend for lun %d, target %s, "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (oldlun->l_blocksize != newlun->l_blocksize) {
|
||||
log_debugx("blocksize for lun %d, target %s, "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (newlun->l_device_id != NULL &&
|
||||
(oldlun->l_device_id == NULL ||
|
||||
strcmp(oldlun->l_device_id, newlun->l_device_id) !=
|
||||
0)) {
|
||||
log_debugx("device-id for lun %d, target %s, "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (newlun->l_path != NULL &&
|
||||
(oldlun->l_path == NULL ||
|
||||
strcmp(oldlun->l_path, newlun->l_path) != 0)) {
|
||||
log_debugx("path for lun %d, target %s, "
|
||||
"CTL lun %d, changed; removing",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (newlun->l_serial != NULL &&
|
||||
(oldlun->l_serial == NULL ||
|
||||
strcmp(oldlun->l_serial, newlun->l_serial) != 0)) {
|
||||
log_debugx("serial for lun %d, target %s, "
|
||||
"CTL lun %d changed; removing",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
changed = 1;
|
||||
}
|
||||
if (changed) {
|
||||
error = kernel_lun_remove(oldlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to remove lun %d, "
|
||||
"target %s, CTL lun %d",
|
||||
oldlun->l_lun, oldtarg->t_name,
|
||||
oldlun->l_ctl_lun);
|
||||
cumulated_error++;
|
||||
}
|
||||
lun_delete(oldlun);
|
||||
continue;
|
||||
}
|
||||
|
||||
lun_set_ctl_lun(newlun, oldlun->l_ctl_lun);
|
||||
continue;
|
||||
}
|
||||
log_debugx("adding lun \"%s\"", newlun->l_name);
|
||||
error = kernel_lun_add(newlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to add lun \"%s\"", newlun->l_name);
|
||||
lun_delete(newlun);
|
||||
cumulated_error++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1786,54 +1803,21 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
|
||||
TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
|
||||
oldtarg = target_find(oldconf, newtarg->t_name);
|
||||
|
||||
TAILQ_FOREACH_SAFE(newlun, &newtarg->t_luns, l_next, tmplun) {
|
||||
if (oldtarg != NULL) {
|
||||
oldlun = lun_find(oldtarg, newlun->l_lun);
|
||||
if (oldlun != NULL) {
|
||||
if (newlun->l_size != oldlun->l_size ||
|
||||
newlun->l_size == 0) {
|
||||
log_debugx("resizing lun %d, "
|
||||
"target %s, CTL lun %d",
|
||||
newlun->l_lun,
|
||||
newtarg->t_name,
|
||||
newlun->l_ctl_lun);
|
||||
error =
|
||||
kernel_lun_resize(newlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to "
|
||||
"resize lun %d, "
|
||||
"target %s, "
|
||||
"CTL lun %d",
|
||||
newlun->l_lun,
|
||||
newtarg->t_name,
|
||||
newlun->l_lun);
|
||||
cumulated_error++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
log_debugx("adding lun %d, target %s",
|
||||
newlun->l_lun, newtarg->t_name);
|
||||
error = kernel_lun_add(newlun);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to add lun %d, target %s",
|
||||
newlun->l_lun, newtarg->t_name);
|
||||
lun_delete(newlun);
|
||||
cumulated_error++;
|
||||
}
|
||||
}
|
||||
if (oldtarg == NULL) {
|
||||
if (oldtarg == NULL)
|
||||
error = kernel_port_add(newtarg);
|
||||
if (error != 0) {
|
||||
log_warnx("failed to add target %s",
|
||||
newtarg->t_name);
|
||||
/*
|
||||
* XXX: Uncomment after fixing the root cause.
|
||||
*
|
||||
* cumulated_error++;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
target_set_ctl_port(newtarg, oldtarg->t_ctl_port);
|
||||
error = kernel_port_update(newtarg);
|
||||
}
|
||||
if (error != 0) {
|
||||
log_warnx("failed to %s target %s",
|
||||
(oldtarg == NULL) ? "add" : "update",
|
||||
newtarg->t_name);
|
||||
/*
|
||||
* XXX: Uncomment after fixing the root cause.
|
||||
*
|
||||
* cumulated_error++;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define DEFAULT_PIDFILE "/var/run/ctld.pid"
|
||||
#define DEFAULT_BLOCKSIZE 512
|
||||
|
||||
#define MAX_LUNS 1024
|
||||
#define MAX_NAME_LEN 223
|
||||
#define MAX_DATA_SEGMENT_LENGTH (128 * 1024)
|
||||
#define MAX_BURST_LENGTH 16776192
|
||||
@ -132,13 +133,14 @@ struct lun_option {
|
||||
|
||||
struct lun {
|
||||
TAILQ_ENTRY(lun) l_next;
|
||||
struct conf *l_conf;
|
||||
TAILQ_HEAD(, lun_option) l_options;
|
||||
struct target *l_target;
|
||||
int l_lun;
|
||||
char *l_name;
|
||||
char *l_backend;
|
||||
int l_blocksize;
|
||||
char *l_device_id;
|
||||
char *l_path;
|
||||
char *l_scsiname;
|
||||
char *l_serial;
|
||||
int64_t l_size;
|
||||
|
||||
@ -147,13 +149,15 @@ struct lun {
|
||||
|
||||
struct target {
|
||||
TAILQ_ENTRY(target) t_next;
|
||||
TAILQ_HEAD(, lun) t_luns;
|
||||
struct conf *t_conf;
|
||||
struct lun *t_luns[MAX_LUNS];
|
||||
struct auth_group *t_auth_group;
|
||||
struct portal_group *t_portal_group;
|
||||
char *t_name;
|
||||
char *t_alias;
|
||||
char *t_redirection;
|
||||
|
||||
uint32_t t_ctl_port;
|
||||
};
|
||||
|
||||
struct isns {
|
||||
@ -165,6 +169,7 @@ struct isns {
|
||||
|
||||
struct conf {
|
||||
char *conf_pidfile_path;
|
||||
TAILQ_HEAD(, lun) conf_luns;
|
||||
TAILQ_HEAD(, target) conf_targets;
|
||||
TAILQ_HEAD(, auth_group) conf_auth_groups;
|
||||
TAILQ_HEAD(, portal_group) conf_portal_groups;
|
||||
@ -319,14 +324,17 @@ 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 target *target, int lun_id);
|
||||
struct lun *lun_new(struct conf *conf, const char *name);
|
||||
void lun_delete(struct lun *lun);
|
||||
struct lun *lun_find(const struct target *target, int lun_id);
|
||||
struct lun *lun_find(const struct conf *conf, const char *name);
|
||||
void lun_set_backend(struct lun *lun, const char *value);
|
||||
void lun_set_blocksize(struct lun *lun, size_t value);
|
||||
void lun_set_device_id(struct lun *lun, const char *value);
|
||||
void lun_set_path(struct lun *lun, const char *value);
|
||||
void lun_set_scsiname(struct lun *lun, const char *value);
|
||||
void lun_set_serial(struct lun *lun, const char *value);
|
||||
void lun_set_size(struct lun *lun, size_t value);
|
||||
void lun_set_ctl_lun(struct lun *lun, uint32_t value);
|
||||
@ -345,6 +353,7 @@ 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);
|
||||
void kernel_capsicate(void);
|
||||
|
||||
|
@ -114,8 +114,7 @@ struct cctl_lun {
|
||||
uint32_t blocksize;
|
||||
char *serial_number;
|
||||
char *device_id;
|
||||
char *cfiscsi_target;
|
||||
int cfiscsi_lun;
|
||||
char *ctld_name;
|
||||
STAILQ_HEAD(,cctl_lun_nv) attr_list;
|
||||
STAILQ_ENTRY(cctl_lun) links;
|
||||
};
|
||||
@ -229,11 +228,9 @@ cctl_end_element(void *user_data, const char *name)
|
||||
} else if (strcmp(name, "device_id") == 0) {
|
||||
cur_lun->device_id = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "cfiscsi_target") == 0) {
|
||||
cur_lun->cfiscsi_target = str;
|
||||
} else if (strcmp(name, "ctld_name") == 0) {
|
||||
cur_lun->ctld_name = str;
|
||||
str = NULL;
|
||||
} else if (strcmp(name, "cfiscsi_lun") == 0) {
|
||||
cur_lun->cfiscsi_lun = strtoul(str, NULL, 0);
|
||||
} else if (strcmp(name, "lun") == 0) {
|
||||
devlist->cur_lun = NULL;
|
||||
} else if (strcmp(name, "ctllunlist") == 0) {
|
||||
@ -522,38 +519,25 @@ conf_new_from_kernel(void)
|
||||
STAILQ_FOREACH(lun, &devlist.lun_list, links) {
|
||||
struct cctl_lun_nv *nv;
|
||||
|
||||
if (lun->cfiscsi_target == NULL) {
|
||||
if (lun->ctld_name == NULL) {
|
||||
log_debugx("CTL lun %ju wasn't managed by ctld; "
|
||||
"ignoring", (uintmax_t)lun->lun_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
targ = target_find(conf, lun->cfiscsi_target);
|
||||
if (targ == NULL) {
|
||||
#if 0
|
||||
log_debugx("found new kernel target %s for CTL lun %ld",
|
||||
lun->cfiscsi_target, lun->lun_id);
|
||||
#endif
|
||||
targ = target_new(conf, lun->cfiscsi_target);
|
||||
if (targ == NULL) {
|
||||
log_warnx("target_new failed");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
cl = lun_find(targ, lun->cfiscsi_lun);
|
||||
cl = lun_find(conf, lun->ctld_name);
|
||||
if (cl != NULL) {
|
||||
log_warnx("found CTL lun %ju, backing lun %d, target "
|
||||
"%s, also backed by CTL lun %d; ignoring",
|
||||
(uintmax_t) lun->lun_id, cl->l_lun,
|
||||
cl->l_target->t_name, cl->l_ctl_lun);
|
||||
log_warnx("found CTL lun %ju \"%s\", "
|
||||
"also backed by CTL lun %d; ignoring",
|
||||
(uintmax_t)lun->lun_id, lun->ctld_name,
|
||||
cl->l_ctl_lun);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debugx("found CTL lun %ju, backing lun %d, target %s",
|
||||
(uintmax_t)lun->lun_id, lun->cfiscsi_lun, lun->cfiscsi_target);
|
||||
log_debugx("found CTL lun %ju \"%s\"",
|
||||
(uintmax_t)lun->lun_id, lun->ctld_name);
|
||||
|
||||
cl = lun_new(targ, lun->cfiscsi_lun);
|
||||
cl = lun_new(conf, lun->ctld_name);
|
||||
if (cl == NULL) {
|
||||
log_warnx("lun_new failed");
|
||||
continue;
|
||||
@ -574,9 +558,9 @@ conf_new_from_kernel(void)
|
||||
lo = lun_option_new(cl, nv->name, nv->value);
|
||||
if (lo == NULL)
|
||||
log_warnx("unable to add CTL lun option %s "
|
||||
"for CTL lun %ju for lun %d, target %s",
|
||||
"for CTL lun %ju \"%s\"",
|
||||
nv->name, (uintmax_t) lun->lun_id,
|
||||
cl->l_lun, cl->l_target->t_name);
|
||||
cl->l_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,7 +583,6 @@ kernel_lun_add(struct lun *lun)
|
||||
{
|
||||
struct lun_option *lo;
|
||||
struct ctl_lun_req req;
|
||||
char *tmp;
|
||||
int error, i, num_options;
|
||||
|
||||
bzero(&req, sizeof(req));
|
||||
@ -637,38 +620,17 @@ kernel_lun_add(struct lun *lun)
|
||||
}
|
||||
}
|
||||
|
||||
lo = lun_option_find(lun, "cfiscsi_target");
|
||||
lo = lun_option_find(lun, "ctld_name");
|
||||
if (lo != NULL) {
|
||||
lun_option_set(lo, lun->l_target->t_name);
|
||||
lun_option_set(lo, lun->l_name);
|
||||
} else {
|
||||
lo = lun_option_new(lun, "cfiscsi_target",
|
||||
lun->l_target->t_name);
|
||||
lo = lun_option_new(lun, "ctld_name", lun->l_name);
|
||||
assert(lo != NULL);
|
||||
}
|
||||
|
||||
asprintf(&tmp, "%d", lun->l_lun);
|
||||
if (tmp == NULL)
|
||||
log_errx(1, "asprintf");
|
||||
lo = lun_option_find(lun, "cfiscsi_lun");
|
||||
if (lo != NULL) {
|
||||
lun_option_set(lo, tmp);
|
||||
free(tmp);
|
||||
} else {
|
||||
lo = lun_option_new(lun, "cfiscsi_lun", tmp);
|
||||
free(tmp);
|
||||
assert(lo != NULL);
|
||||
}
|
||||
|
||||
asprintf(&tmp, "%s,lun,%d", lun->l_target->t_name, lun->l_lun);
|
||||
if (tmp == NULL)
|
||||
log_errx(1, "asprintf");
|
||||
lo = lun_option_find(lun, "scsiname");
|
||||
if (lo != NULL) {
|
||||
lun_option_set(lo, tmp);
|
||||
free(tmp);
|
||||
} else {
|
||||
lo = lun_option_new(lun, "scsiname", tmp);
|
||||
free(tmp);
|
||||
if (lo == NULL && lun->l_scsiname != NULL) {
|
||||
lo = lun_option_new(lun, "scsiname", lun->l_scsiname);
|
||||
assert(lo != NULL);
|
||||
}
|
||||
|
||||
@ -846,10 +808,11 @@ kernel_port_add(struct target *targ)
|
||||
{
|
||||
struct ctl_port_entry entry;
|
||||
struct ctl_req req;
|
||||
struct ctl_lun_map lm;
|
||||
char tagstr[16];
|
||||
int error;
|
||||
uint32_t port_id = -1;
|
||||
int error, i;
|
||||
|
||||
/* Create iSCSI port. */
|
||||
bzero(&req, sizeof(req));
|
||||
strlcpy(req.driver, "iscsi", sizeof(req.driver));
|
||||
req.reqtype = CTL_REQ_CREATE;
|
||||
@ -857,8 +820,8 @@ kernel_port_add(struct target *targ)
|
||||
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(port_id);
|
||||
req.args[0].value = &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);
|
||||
@ -867,29 +830,46 @@ kernel_port_add(struct target *targ)
|
||||
str_arg(&req.args[3], "cfiscsi_target_alias", targ->t_alias);
|
||||
else
|
||||
req.num_args--;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bzero(&entry, sizeof(entry));
|
||||
entry.targ_port = port_id;
|
||||
/* Explicitly enable mapping to block any access except allowed. */
|
||||
lm.port = targ->t_ctl_port;
|
||||
lm.plun = UINT32_MAX;
|
||||
lm.lun = 0;
|
||||
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
|
||||
if (error != 0)
|
||||
log_warn("CTL_LUN_MAP ioctl failed");
|
||||
|
||||
/* Map configured LUNs */
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
if (targ->t_luns[i] == NULL)
|
||||
continue;
|
||||
lm.port = targ->t_ctl_port;
|
||||
lm.plun = i;
|
||||
lm.lun = targ->t_luns[i]->l_ctl_lun;
|
||||
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
|
||||
if (error != 0)
|
||||
log_warn("CTL_LUN_MAP ioctl failed");
|
||||
}
|
||||
|
||||
/* Enable port */
|
||||
bzero(&entry, sizeof(entry));
|
||||
entry.targ_port = targ->t_ctl_port;
|
||||
error = ioctl(ctl_fd, CTL_ENABLE_PORT, &entry);
|
||||
if (error != 0) {
|
||||
log_warn("CTL_ENABLE_PORT ioctl failed");
|
||||
@ -899,6 +879,27 @@ kernel_port_add(struct target *targ)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_port_update(struct target *targ)
|
||||
{
|
||||
struct ctl_lun_map lm;
|
||||
int error, i;
|
||||
|
||||
/* Map configured LUNs and unmap others */
|
||||
for (i = 0; i < MAX_LUNS; i++) {
|
||||
lm.port = targ->t_ctl_port;
|
||||
lm.plun = i;
|
||||
if (targ->t_luns[i] == NULL)
|
||||
lm.lun = UINT32_MAX;
|
||||
else
|
||||
lm.lun = targ->t_luns[i]->l_ctl_lun;
|
||||
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
|
||||
if (error != 0)
|
||||
log_warn("CTL_LUN_MAP ioctl failed");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_port_remove(struct target *targ)
|
||||
{
|
||||
|
@ -99,6 +99,8 @@ statement:
|
||||
|
|
||||
portal_group
|
||||
|
|
||||
lun
|
||||
|
|
||||
target
|
||||
;
|
||||
|
||||
@ -407,6 +409,22 @@ portal_group_redirect: REDIRECT STR
|
||||
}
|
||||
;
|
||||
|
||||
lun: LUN lun_name
|
||||
OPENING_BRACKET lun_entries CLOSING_BRACKET
|
||||
{
|
||||
lun = NULL;
|
||||
}
|
||||
;
|
||||
|
||||
lun_name: STR
|
||||
{
|
||||
lun = lun_new(conf, $1);
|
||||
free($1);
|
||||
if (lun == NULL)
|
||||
return (1);
|
||||
}
|
||||
;
|
||||
|
||||
target: TARGET target_name
|
||||
OPENING_BRACKET target_entries CLOSING_BRACKET
|
||||
{
|
||||
@ -450,6 +468,8 @@ target_entry:
|
||||
target_redirect
|
||||
|
|
||||
target_lun
|
||||
|
|
||||
target_lun_ref
|
||||
;
|
||||
|
||||
target_alias: ALIAS STR
|
||||
@ -672,6 +692,7 @@ target_lun: LUN lun_number
|
||||
lun_number: STR
|
||||
{
|
||||
uint64_t tmp;
|
||||
char *name;
|
||||
|
||||
if (expand_number($1, &tmp) != 0) {
|
||||
yyerror("invalid numeric value");
|
||||
@ -679,9 +700,34 @@ lun_number: STR
|
||||
return (1);
|
||||
}
|
||||
|
||||
lun = lun_new(target, tmp);
|
||||
asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
|
||||
lun = lun_new(conf, name);
|
||||
if (lun == NULL)
|
||||
return (1);
|
||||
|
||||
lun_set_scsiname(lun, name);
|
||||
target->t_luns[tmp] = lun;
|
||||
}
|
||||
;
|
||||
|
||||
target_lun_ref: LUN STR STR
|
||||
{
|
||||
uint64_t tmp;
|
||||
|
||||
if (expand_number($2, &tmp) != 0) {
|
||||
yyerror("invalid numeric value");
|
||||
free($2);
|
||||
free($3);
|
||||
return (1);
|
||||
}
|
||||
free($2);
|
||||
|
||||
lun = lun_find(conf, $3);
|
||||
free($3);
|
||||
if (lun == NULL)
|
||||
return (1);
|
||||
|
||||
target->t_luns[tmp] = lun;
|
||||
}
|
||||
;
|
||||
|
||||
@ -711,9 +757,9 @@ lun_entry:
|
||||
lun_backend: BACKEND STR
|
||||
{
|
||||
if (lun->l_backend != NULL) {
|
||||
log_warnx("backend for lun %d, target \"%s\" "
|
||||
log_warnx("backend for lun \"%s\" "
|
||||
"specified more than once",
|
||||
lun->l_lun, target->t_name);
|
||||
lun->l_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
@ -733,9 +779,9 @@ lun_blocksize: BLOCKSIZE STR
|
||||
}
|
||||
|
||||
if (lun->l_blocksize != 0) {
|
||||
log_warnx("blocksize for lun %d, target \"%s\" "
|
||||
log_warnx("blocksize for lun \"%s\" "
|
||||
"specified more than once",
|
||||
lun->l_lun, target->t_name);
|
||||
lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
lun_set_blocksize(lun, tmp);
|
||||
@ -745,9 +791,9 @@ lun_blocksize: BLOCKSIZE STR
|
||||
lun_device_id: DEVICE_ID STR
|
||||
{
|
||||
if (lun->l_device_id != NULL) {
|
||||
log_warnx("device_id for lun %d, target \"%s\" "
|
||||
log_warnx("device_id for lun \"%s\" "
|
||||
"specified more than once",
|
||||
lun->l_lun, target->t_name);
|
||||
lun->l_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
@ -771,9 +817,9 @@ lun_option: OPTION STR STR
|
||||
lun_path: PATH STR
|
||||
{
|
||||
if (lun->l_path != NULL) {
|
||||
log_warnx("path for lun %d, target \"%s\" "
|
||||
log_warnx("path for lun \"%s\" "
|
||||
"specified more than once",
|
||||
lun->l_lun, target->t_name);
|
||||
lun->l_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
@ -785,9 +831,9 @@ lun_path: PATH STR
|
||||
lun_serial: SERIAL STR
|
||||
{
|
||||
if (lun->l_serial != NULL) {
|
||||
log_warnx("serial for lun %d, target \"%s\" "
|
||||
log_warnx("serial for lun \"%s\" "
|
||||
"specified more than once",
|
||||
lun->l_lun, target->t_name);
|
||||
lun->l_name);
|
||||
free($2);
|
||||
return (1);
|
||||
}
|
||||
@ -807,9 +853,9 @@ lun_size: SIZE STR
|
||||
}
|
||||
|
||||
if (lun->l_size != 0) {
|
||||
log_warnx("size for lun %d, target \"%s\" "
|
||||
log_warnx("size for lun \"%s\" "
|
||||
"specified more than once",
|
||||
lun->l_lun, target->t_name);
|
||||
lun->l_name);
|
||||
return (1);
|
||||
}
|
||||
lun_set_size(lun, tmp);
|
||||
|
Loading…
Reference in New Issue
Block a user