diff options
-rw-r--r-- | sys/cam/ctl/ctl.c | 70 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend.c | 4 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend.h | 1 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_io.h | 2 |
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. |