summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ctl/ctl.c70
-rw-r--r--sys/cam/ctl/ctl_frontend.c4
-rw-r--r--sys/cam/ctl/ctl_frontend.h1
-rw-r--r--sys/cam/ctl/ctl_io.h2
4 files changed, 49 insertions, 28 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 81ae151..d0276b7 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -409,6 +409,9 @@ static int ctl_debug = CTL_DEBUG_NONE;
TUNABLE_INT("kern.cam.ctl.debug", &ctl_debug);
SYSCTL_INT(_kern_cam_ctl, OID_AUTO, debug, CTLFLAG_RWTUN,
&ctl_debug, 0, "Enabled debug flags");
+static int ctl_lun_map_size = 1024;
+SYSCTL_INT(_kern_cam_ctl, OID_AUTO, lun_map_size, CTLFLAG_RWTUN,
+ &ctl_lun_map_size, 0, "Size of per-port LUN map (max LUN + 1)");
/*
* Supported pages (0x00), Serial number (0x80), Device ID (0x83),
@@ -828,7 +831,7 @@ ctl_isc_announce_port(struct ctl_port *port)
return;
i = sizeof(msg->port) + strlen(port->port_name) + 1;
if (port->lun_map)
- i += sizeof(uint32_t) * CTL_MAX_LUNS;
+ i += port->lun_map_size * sizeof(uint32_t);
if (port->port_devid)
i += port->port_devid->len;
if (port->target_devid)
@@ -848,7 +851,7 @@ ctl_isc_announce_port(struct ctl_port *port)
"%d:%s", softc->ha_id, port->port_name) + 1;
i += msg->port.name_len;
if (port->lun_map) {
- msg->port.lun_map_len = sizeof(uint32_t) * CTL_MAX_LUNS;
+ msg->port.lun_map_len = port->lun_map_size * sizeof(uint32_t);
memcpy(&msg->port.data[i], port->lun_map,
msg->port.lun_map_len);
i += msg->port.lun_map_len;
@@ -1157,19 +1160,25 @@ ctl_isc_port_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
M_CTL);
i += msg->port.name_len;
if (msg->port.lun_map_len != 0) {
- if (port->lun_map == NULL)
- port->lun_map = malloc(sizeof(uint32_t) * CTL_MAX_LUNS,
+ if (port->lun_map == NULL ||
+ port->lun_map_size * sizeof(uint32_t) <
+ msg->port.lun_map_len) {
+ port->lun_map_size = 0;
+ free(port->lun_map, M_CTL);
+ port->lun_map = malloc(msg->port.lun_map_len,
M_CTL, M_WAITOK);
- memcpy(port->lun_map, &msg->port.data[i],
- sizeof(uint32_t) * CTL_MAX_LUNS);
+ }
+ memcpy(port->lun_map, &msg->port.data[i], msg->port.lun_map_len);
+ port->lun_map_size = msg->port.lun_map_len / sizeof(uint32_t);
i += msg->port.lun_map_len;
} else {
+ port->lun_map_size = 0;
free(port->lun_map, M_CTL);
port->lun_map = NULL;
}
if (msg->port.port_devid_len != 0) {
if (port->port_devid == NULL ||
- port->port_devid->len != msg->port.port_devid_len) {
+ port->port_devid->len < msg->port.port_devid_len) {
free(port->port_devid, M_CTL);
port->port_devid = malloc(sizeof(struct ctl_devid) +
msg->port.port_devid_len, M_CTL, M_WAITOK);
@@ -1184,7 +1193,7 @@ ctl_isc_port_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
}
if (msg->port.target_devid_len != 0) {
if (port->target_devid == NULL ||
- port->target_devid->len != msg->port.target_devid_len) {
+ port->target_devid->len < msg->port.target_devid_len) {
free(port->target_devid, M_CTL);
port->target_devid = malloc(sizeof(struct ctl_devid) +
msg->port.target_devid_len, M_CTL, M_WAITOK);
@@ -1199,7 +1208,7 @@ ctl_isc_port_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
}
if (msg->port.init_devid_len != 0) {
if (port->init_devid == NULL ||
- port->init_devid->len != msg->port.init_devid_len) {
+ port->init_devid->len < msg->port.init_devid_len) {
free(port->init_devid, M_CTL);
port->init_devid = malloc(sizeof(struct ctl_devid) +
msg->port.init_devid_len, M_CTL, M_WAITOK);
@@ -3286,7 +3295,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (port->lun_map != NULL) {
sbuf_printf(sb, "\t<lun_map>on</lun_map>\n");
- for (j = 0; j < CTL_MAX_LUNS; j++) {
+ for (j = 0; j < port->lun_map_size; j++) {
plun = ctl_lun_map_from_port(port, j);
if (plun == UINT32_MAX)
continue;
@@ -3366,7 +3375,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
}
}
mtx_unlock(&softc->ctl_lock); // XXX: port_enable sleeps
- if (lm->plun < CTL_MAX_LUNS) {
+ if (lm->plun != UINT32_MAX) {
if (lm->lun == UINT32_MAX)
retval = ctl_lun_map_unset(port, lm->plun);
else if (lm->lun < CTL_MAX_LUNS &&
@@ -3374,13 +3383,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
retval = ctl_lun_map_set(port, lm->plun, lm->lun);
else
return (ENXIO);
- } else if (lm->plun == UINT32_MAX) {
+ } else {
if (lm->lun == UINT32_MAX)
retval = ctl_lun_map_deinit(port);
else
retval = ctl_lun_map_init(port);
- } else
- return (ENXIO);
+ }
if (port->status & CTL_PORT_STATUS_ONLINE)
ctl_isc_announce_port(port);
break;
@@ -3433,15 +3441,20 @@ ctl_lun_map_init(struct ctl_port *port)
{
struct ctl_softc *softc = port->ctl_softc;
struct ctl_lun *lun;
+ int size = ctl_lun_map_size;
uint32_t i;
- if (port->lun_map == NULL)
- port->lun_map = malloc(sizeof(uint32_t) * CTL_MAX_LUNS,
+ if (port->lun_map == NULL || port->lun_map_size < size) {
+ port->lun_map_size = 0;
+ free(port->lun_map, M_CTL);
+ port->lun_map = malloc(size * sizeof(uint32_t),
M_CTL, M_NOWAIT);
+ }
if (port->lun_map == NULL)
return (ENOMEM);
- for (i = 0; i < CTL_MAX_LUNS; i++)
+ for (i = 0; i < size; i++)
port->lun_map[i] = UINT32_MAX;
+ port->lun_map_size = size;
if (port->status & CTL_PORT_STATUS_ONLINE) {
if (port->lun_disable != NULL) {
STAILQ_FOREACH(lun, &softc->lun_list, links)
@@ -3460,6 +3473,7 @@ ctl_lun_map_deinit(struct ctl_port *port)
if (port->lun_map == NULL)
return (0);
+ port->lun_map_size = 0;
free(port->lun_map, M_CTL);
port->lun_map = NULL;
if (port->status & CTL_PORT_STATUS_ONLINE) {
@@ -3483,6 +3497,8 @@ ctl_lun_map_set(struct ctl_port *port, uint32_t plun, uint32_t glun)
if (status != 0)
return (status);
}
+ if (plun >= port->lun_map_size)
+ return (EINVAL);
old = port->lun_map[plun];
port->lun_map[plun] = glun;
if ((port->status & CTL_PORT_STATUS_ONLINE) && old == UINT32_MAX) {
@@ -3498,7 +3514,7 @@ ctl_lun_map_unset(struct ctl_port *port, uint32_t plun)
{
uint32_t old;
- if (port->lun_map == NULL)
+ if (port->lun_map == NULL || plun >= port->lun_map_size)
return (0);
old = port->lun_map[plun];
port->lun_map[plun] = UINT32_MAX;
@@ -3516,8 +3532,10 @@ 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 == UINT32_MAX)
+ if (port->lun_map == NULL)
return (lun_id);
+ if (lun_id > port->lun_map_size)
+ return (UINT32_MAX);
return (port->lun_map[lun_id]);
}
@@ -3530,7 +3548,7 @@ ctl_lun_map_to_port(struct ctl_port *port, uint32_t lun_id)
return (UINT32_MAX);
if (port->lun_map == NULL)
return (lun_id);
- for (i = 0; i < CTL_MAX_LUNS; i++) {
+ for (i = 0; i < port->lun_map_size; i++) {
if (port->lun_map[i] == lun_id)
return (i);
}
@@ -9039,9 +9057,8 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
struct scsi_report_luns_data *lun_data;
struct ctl_lun *lun, *request_lun;
struct ctl_port *port;
- int num_luns, retval;
+ int num_filled, num_luns, num_port_luns, retval;
uint32_t alloc_len, lun_datalen;
- int num_filled;
uint32_t initidx, targ_lun_id, lun_id;
retval = CTL_RETVAL_COMPLETE;
@@ -9051,9 +9068,10 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_report_luns\n"));
- mtx_lock(&softc->ctl_lock);
num_luns = 0;
- for (targ_lun_id = 0; targ_lun_id < CTL_MAX_LUNS; targ_lun_id++) {
+ num_port_luns = port->lun_map ? port->lun_map_size : CTL_MAX_LUNS;
+ mtx_lock(&softc->ctl_lock);
+ for (targ_lun_id = 0; targ_lun_id < num_port_luns; targ_lun_id++) {
if (ctl_lun_map_from_port(port, targ_lun_id) != UINT32_MAX)
num_luns++;
}
@@ -9112,7 +9130,9 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
initidx = ctl_get_initindex(&ctsio->io_hdr.nexus);
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++) {
+ for (targ_lun_id = 0, num_filled = 0;
+ targ_lun_id < num_port_luns && num_filled < num_luns;
+ targ_lun_id++) {
lun_id = ctl_lun_map_from_port(port, targ_lun_id);
if (lun_id == UINT32_MAX)
continue;
diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c
index 5c6fa05..97f4e0b 100644
--- a/sys/cam/ctl/ctl_frontend.c
+++ b/sys/cam/ctl/ctl_frontend.c
@@ -315,7 +315,7 @@ ctl_port_online(struct ctl_port *port)
if (port->lun_enable != NULL) {
if (port->lun_map) {
- for (l = 0; l < CTL_MAX_LUNS; l++) {
+ for (l = 0; l < port->lun_map_size; l++) {
if (ctl_lun_map_from_port(port, l) ==
UINT32_MAX)
continue;
@@ -359,7 +359,7 @@ ctl_port_offline(struct ctl_port *port)
port->port_offline(port->onoff_arg);
if (port->lun_disable != NULL) {
if (port->lun_map) {
- for (l = 0; l < CTL_MAX_LUNS; l++) {
+ for (l = 0; l < port->lun_map_size; l++) {
if (ctl_lun_map_from_port(port, l) ==
UINT32_MAX)
continue;
diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h
index 1dd970a..3e42ac3 100644
--- a/sys/cam/ctl/ctl_frontend.h
+++ b/sys/cam/ctl/ctl_frontend.h
@@ -225,6 +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 */
+ int lun_map_size; /* 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 */
diff --git a/sys/cam/ctl/ctl_io.h b/sys/cam/ctl/ctl_io.h
index bad030f..77f4fc9 100644
--- a/sys/cam/ctl/ctl_io.h
+++ b/sys/cam/ctl/ctl_io.h
@@ -365,7 +365,7 @@ struct ctl_taskio {
/*
* HA link messages.
*/
-#define CTL_HA_VERSION 1
+#define CTL_HA_VERSION 2
/*
* Used for CTL_MSG_LOGIN.
OpenPOWER on IntegriCloud