summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-01-21 08:33:44 +0000
committermav <mav@FreeBSD.org>2017-01-21 08:33:44 +0000
commita6c9673af925d5ad82214f2da3e412dd10217337 (patch)
treeae90eefbc4f2eb59c0b9c4516407e9ea7a659735
parent2cd2565e1e5d585ee5b4d1a26368fa934e8e4f91 (diff)
downloadFreeBSD-src-a6c9673af925d5ad82214f2da3e412dd10217337.zip
FreeBSD-src-a6c9673af925d5ad82214f2da3e412dd10217337.tar.gz
MFC r310635: Decouple limits on number of LUNs per port and LUs per CTL.
Those two values are not directly related, so make them independent. This does not change any limits immediately, but makes number of LUNs per port controllable via tunable/sysctl kern.cam.ctl.lun_map_size. After this change increasing CTL_MAX_LUNS should be pretty cheap, and even making it tunable should be easy.
-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 502aca2..3f5b752 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -407,6 +407,9 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, worker_threads, CTLFLAG_RDTUN,
static int ctl_debug = CTL_DEBUG_NONE;
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),
@@ -826,7 +829,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)
@@ -846,7 +849,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;
@@ -1155,19 +1158,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);
@@ -1182,7 +1191,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);
@@ -1197,7 +1206,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);
@@ -3295,7 +3304,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;
@@ -3375,7 +3384,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 &&
@@ -3383,13 +3392,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;
@@ -3442,15 +3450,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)
@@ -3469,6 +3482,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) {
@@ -3492,6 +3506,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) {
@@ -3507,7 +3523,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;
@@ -3525,8 +3541,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]);
}
@@ -3539,7 +3557,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);
}
@@ -9048,9 +9066,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;
@@ -9060,9 +9077,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++;
}
@@ -9121,7 +9139,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