Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Dec 2016 18:23:17 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r310635 - head/sys/cam/ctl
Message-ID:  <201612271823.uBRINHwn028630@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612271823.uBRINHwn028630>