Author: mav
Date: Tue Dec 27 18:23:16 2016
New Revision: 310635
URL: https://svnweb.freebsd.org/changeset/base/310635

Log:
  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.
  
  MFC after:    2 weeks

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl_frontend.c
  head/sys/cam/ctl/ctl_frontend.h
  head/sys/cam/ctl/ctl_io.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c      Tue Dec 27 17:31:07 2016        (r310634)
+++ head/sys/cam/ctl/ctl.c      Tue Dec 27 18:23:16 2016        (r310635)
@@ -407,6 +407,9 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, work
 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 *p
                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 *p
            "%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 *soft
            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 *soft
        }
        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 *soft
        }
        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, 
 
                        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, 
                        }
                }
                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, 
                                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, u
                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 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 *p
 
        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 *por
                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;

Modified: head/sys/cam/ctl/ctl_frontend.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend.c     Tue Dec 27 17:31:07 2016        
(r310634)
+++ head/sys/cam/ctl/ctl_frontend.c     Tue Dec 27 18:23:16 2016        
(r310635)
@@ -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;

Modified: head/sys/cam/ctl/ctl_frontend.h
==============================================================================
--- head/sys/cam/ctl/ctl_frontend.h     Tue Dec 27 17:31:07 2016        
(r310634)
+++ head/sys/cam/ctl/ctl_frontend.h     Tue Dec 27 18:23:16 2016        
(r310635)
@@ -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 */

Modified: head/sys/cam/ctl/ctl_io.h
==============================================================================
--- head/sys/cam/ctl/ctl_io.h   Tue Dec 27 17:31:07 2016        (r310634)
+++ head/sys/cam/ctl/ctl_io.h   Tue Dec 27 18:23:16 2016        (r310635)
@@ -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.
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to