changeset 3759:f817e8463cb0

6526280 Guest with 64 vdisk devices hangs during boot 6526814 Booting multiple LDoms in a loop can cause hard hangs 6528758 'ds_cap_send: invalid handle' message during LDom boot 6529035 platsvc module could use some lint cleanup
author rsmaeda
date Sun, 04 Mar 2007 16:03:47 -0800
parents 88646977ee6c
children 928a7412f6c1
files usr/src/uts/sun4v/io/ds.c usr/src/uts/sun4v/io/mdeg.c usr/src/uts/sun4v/io/platsvc.c usr/src/uts/sun4v/platsvc/Makefile usr/src/uts/sun4v/sys/mdeg.h
diffstat 5 files changed, 100 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sun4v/io/ds.c	Sun Mar 04 13:55:29 2007 -0800
+++ b/usr/src/uts/sun4v/io/ds.c	Sun Mar 04 16:03:47 2007 -0800
@@ -32,7 +32,7 @@
  * The Domain Services (DS) module is responsible for communication
  * with external service entities. It provides an API for clients to
  * publish capabilities and handles the low level communication and
- * version negotiation required to export those capabilites to any
+ * version negotiation required to export those capabilities to any
  * interested service entity. Once a capability has been successfully
  * registered with a service entity, the DS module facilitates all
  * data transfers between the service entity and the client providing
@@ -67,7 +67,7 @@
 /*
  * Table of registered services
  *
- * Locking: Accesses to the table of services are sychronized using
+ * Locking: Accesses to the table of services are synchronized using
  *   a RW lock. The reader lock must be held when looking up service
  *   information in the table. The writer lock must be held when any
  *   service information is being modified.
@@ -236,7 +236,7 @@
 /* event processing functions */
 static uint_t ds_ldc_cb(uint64_t event, caddr_t arg);
 static void ds_dispatch_event(void *arg);
-static int ds_recv_msg(ldc_handle_t ldc_hdl, caddr_t msgp, size_t msglen);
+static int ds_recv_msg(ldc_handle_t ldc_hdl, caddr_t msgp, size_t *sizep);
 static void ds_handle_recv(void *arg);
 
 /* message sending functions */
@@ -301,7 +301,7 @@
 	ds_init();
 
 	if ((rv = ds_ports_init()) != 0) {
-		cmn_err(CE_WARN, "Domin Services initialization failed");
+		cmn_err(CE_WARN, "Domain Services initialization failed");
 		ds_fini();
 		return (rv);
 	}
@@ -599,7 +599,7 @@
 
 	/* register the LDC callback */
 	if ((rv = ldc_reg_callback(port->ldc.hdl, ds_ldc_cb, cb_arg)) != 0) {
-		cmn_err(CE_WARN, "ds@%lx: dc_init: ldc_reg_callback error "
+		cmn_err(CE_WARN, "ds@%lx: ldc_init: ldc_reg_callback error "
 		    "(%d)", port->id, rv);
 		goto done;
 	}
@@ -757,13 +757,22 @@
 	return (LDC_SUCCESS);
 }
 
+/*
+ * Attempt to read a specified number of bytes from a particular LDC.
+ * Returns zero for success or the return code from the LDC read on
+ * failure. The actual number of bytes read from the LDC is returned
+ * in the size parameter.
+ */
 static int
-ds_recv_msg(ldc_handle_t ldc_hdl, caddr_t msgp, size_t msglen)
+ds_recv_msg(ldc_handle_t ldc_hdl, caddr_t msgp, size_t *sizep)
 {
 	int	rv = 0;
+	size_t	msglen = *sizep;
 	size_t	amt_left = msglen;
 	int	loopcnt = 0;
 
+	*sizep = 0;
+
 	while (msglen > 0) {
 		if ((rv = ldc_read(ldc_hdl, msgp, &amt_left)) != 0) {
 			if ((rv == EAGAIN) && (loopcnt++ < 1000)) {
@@ -778,11 +787,20 @@
 				return (rv);
 			}
 		} else {
+			/*
+			 * Check for a zero length read. This
+			 * indicates that there is no more data
+			 * to read from the channel.
+			 */
+			if (amt_left == 0)
+				break;
+
+			*sizep += amt_left;
 			msgp += amt_left;
 			msglen -= amt_left;
 			amt_left = msglen;
 		}
-	} /* while (msglen > 0) */
+	}
 
 	return (rv);
 }
@@ -792,7 +810,7 @@
 {
 	ds_port_t	*port = (ds_port_t *)arg;
 	char		*hbuf;
-	size_t		len;
+	size_t		msglen;
 	size_t		read_size;
 	boolean_t	hasdata;
 	ds_hdr_t	hdr;
@@ -807,9 +825,15 @@
 	ldc_hdl = port->ldc.hdl;
 
 	mutex_enter(&port->lock);
+
+	/*
+	 * Read messages from the channel until there are none
+	 * pending. Valid messages are dispatched to be handled
+	 * by a separate thread while any malformed messages are
+	 * dropped.
+	 */
 	while ((ldc_chkq(ldc_hdl, &hasdata) == 0) && hasdata) {
 
-
 		DS_DBG("ds@%lx: reading next message\n", port->id);
 
 		/*
@@ -821,42 +845,52 @@
 		currp = hbuf;
 
 		/* read in the message header */
-
-		if ((rv = ds_recv_msg(ldc_hdl, currp, read_size)) != 0) {
-			/*
-			 * Failed to read message. Drop it and see if
-			 * there are any more messages.
-			 */
-			cmn_err(CE_NOTE, "ldc_read returned %d", rv);
+		if ((rv = ds_recv_msg(ldc_hdl, currp, &read_size)) != 0) {
+			cmn_err(CE_NOTE, "ds@%lx: ldc_read returned %d",
+			    port->id, rv);
 			continue;
 		}
 
-		len = read_size;
-
-		/* get payload size and alloc a buffer */
-
+		if (read_size < DS_HDR_SZ) {
+			/*
+			 * A zero length read is a valid signal that
+			 * there is no data left on the channel.
+			 */
+			if (read_size != 0) {
+				cmn_err(CE_NOTE, "ds@%lx: invalid message "
+				    "length, received %ld bytes, expected %ld",
+				    port->id, read_size, DS_HDR_SZ);
+			}
+			continue;
+		}
+
+		/* get payload size and allocate a buffer */
 		read_size = ((ds_hdr_t *)hbuf)->payload_len;
-		msg = kmem_zalloc((DS_HDR_SZ + read_size), KM_SLEEP);
+		msglen = DS_HDR_SZ + read_size;
+		msg = kmem_zalloc(msglen, KM_SLEEP);
 
 		/* move message header into buffer */
-
 		bcopy(hbuf, msg, DS_HDR_SZ);
 		currp = (char *)(msg) + DS_HDR_SZ;
 
 		/* read in the message body */
-
-		if ((rv = ds_recv_msg(ldc_hdl, currp, read_size)) != 0) {
-			/*
-			 * Failed to read message. Drop it and see if
-			 * there are any more messages.
-			 */
-			kmem_free(msg, (DS_HDR_SZ + read_size));
-			cmn_err(CE_NOTE, "ldc_read returned %d", rv);
+		if ((rv = ds_recv_msg(ldc_hdl, currp, &read_size)) != 0) {
+			cmn_err(CE_NOTE, "ds@%lx: ldc_read returned %d",
+			    port->id, rv);
+			kmem_free(msg, msglen);
 			continue;
 		}
 
-		len += read_size;
-		DS_DUMP_LDC_MSG(msg, len);
+		/* validate the size of the message */
+		if ((DS_HDR_SZ + read_size) != msglen) {
+			cmn_err(CE_NOTE, "ds@%lx: invalid message length, "
+			    "received %ld bytes, expected %ld", port->id,
+			    (DS_HDR_SZ + read_size), msglen);
+			kmem_free(msg, msglen);
+			continue;
+		}
+
+		DS_DUMP_LDC_MSG(msg, msglen);
 
 		/*
 		 * Send the message for processing, and store it
@@ -867,14 +901,15 @@
 		devent = kmem_zalloc(sizeof (ds_event_t), KM_SLEEP);
 		devent->port = port;
 		devent->buf = (char *)msg;
-		devent->buflen = len;
+		devent->buflen = msglen;
 
 		/* log the message */
-		(void) ds_log_add_msg(DS_LOG_IN(port->id), msg, len);
+		(void) ds_log_add_msg(DS_LOG_IN(port->id), msg, msglen);
 
 		/* send the message off to get processed in a new thread */
 		if (DS_DISPATCH(ds_dispatch_event, devent) == NULL) {
 			cmn_err(CE_WARN, "error initiating event handler");
+			kmem_free(devent, sizeof (ds_event_t));
 			continue;
 		}
 
@@ -897,7 +932,7 @@
 	if (!DS_MSG_TYPE_VALID(hdr->msg_type)) {
 		cmn_err(CE_NOTE, "ds@%lx: dispatch_event: invalid msg "
 		    "type (%d)", port->id, hdr->msg_type);
-		return;
+		goto done;
 	}
 
 	DS_DBG("ds@%lx: dispatch_event: msg_type=%d\n", port->id,
@@ -905,6 +940,7 @@
 
 	(*ds_msg_handlers[hdr->msg_type])(port, event->buf, event->buflen);
 
+done:
 	kmem_free(event, sizeof (ds_event_t));
 }
 
@@ -1001,7 +1037,7 @@
 	} else {
 		/*
 		 * Use the lower minor version returned in
-		 * the ack. By defninition, all lower minor
+		 * the ack. By definition, all lower minor
 		 * versions must be supported.
 		 */
 		port->ver.minor = ack->minor_vers;
@@ -1192,7 +1228,7 @@
 	} else {
 		/*
 		 * Use the lower minor version returned in
-		 * the ack. By defninition, all lower minor
+		 * the ack. By definition, all lower minor
 		 * versions must be supported.
 		 */
 		svc->ver.minor = ack->minor_vers;
--- a/usr/src/uts/sun4v/io/mdeg.c	Sun Mar 04 13:55:29 2007 -0800
+++ b/usr/src/uts/sun4v/io/mdeg.c	Sun Mar 04 16:03:47 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -58,12 +58,12 @@
  *
  * Locking Strategy:
  *
- *   mdeg.lock - lock used to sychronize system wide MD updates. An
+ *   mdeg.lock - lock used to synchronize system-wide MD updates. An
  *	MD update must be treated as an atomic event. The lock is
  *	taken when notification that a new MD is available and held
  *	until all clients have been notified.
  *
- *   mdeg.rwlock - lock used to sychronize access to the table of
+ *   mdeg.rwlock - lock used to synchronize access to the table of
  *	registered clients. The reader lock must be held when looking
  *	up client information in the table. The writer lock must be
  *	held when modifying any client information.
@@ -253,9 +253,10 @@
 
 	/*
 	 * Since the old table was full, the first free entry
-	 * will be just past the end of the old table.
+	 * will be just past the end of the old table data in
+	 * the new table.
 	 */
-	clnt = &mdeg.tbl[mdeg.maxclnts];
+	clnt = &newtbl[mdeg.maxclnts];
 
 	/* clean up the old table */
 	kmem_free(mdeg.tbl, oldtblsz);
@@ -517,7 +518,7 @@
  * Simple algorithm for now, grab the global lock and let all
  * the clients update themselves in parallel. There is a lot of
  * room for improvement here. We could eliminate some scans of
- * the DAG by imcrementally scanning at lower levels of the DAG
+ * the DAG by incrementally scanning at lower levels of the DAG
  * rather than having each client start its own scan from the root.
  */
 void
--- a/usr/src/uts/sun4v/io/platsvc.c	Sun Mar 04 13:55:29 2007 -0800
+++ b/usr/src/uts/sun4v/io/platsvc.c	Sun Mar 04 16:03:47 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -115,7 +115,7 @@
 static void ps_fini(void);
 
 /*
- * Powerdown timeout value of 5 minutes.
+ * Power down timeout value of 5 minutes.
  */
 #define	PLATSVC_POWERDOWN_DELAY		1200
 
@@ -221,7 +221,7 @@
 	extern void mdeg_notify_clients(void);
 	extern void recalc_xc_timeouts(void);
 
-	ds_svc_hdl_t		 ds_handle;
+	ds_svc_hdl_t		 ds_handle = ds_md_handle;
 	platsvc_md_update_req_t	 *msg = buf;
 	platsvc_md_update_resp_t resp_msg;
 	uint_t			 rv;
@@ -229,7 +229,10 @@
 	if (arg == NULL)
 		return;
 
-	ds_handle = ds_md_handle;
+	if (ds_handle == DS_INVALID_HDL) {
+		DBG("ps_md_data_handler: DS handle no longer valid\n");
+		return;
+	}
 
 	if (msg == NULL || buflen != sizeof (platsvc_md_update_req_t)) {
 		resp_msg.req_num = 0;
@@ -265,7 +268,7 @@
 static void
 ps_shutdown_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
 {
-	ds_svc_hdl_t		ds_handle;
+	ds_svc_hdl_t		ds_handle = ds_shutdown_handle;
 	platsvc_shutdown_req_t	*msg = buf;
 	platsvc_shutdown_resp_t	resp_msg;
 	uint_t			rv;
@@ -274,7 +277,10 @@
 	if (arg == NULL)
 		return;
 
-	ds_handle = ds_shutdown_handle;
+	if (ds_handle == DS_INVALID_HDL) {
+		DBG("ps_shutdown_data_handler: DS handle no longer valid\n");
+		return;
+	}
 
 	if (msg == NULL || buflen != sizeof (platsvc_shutdown_req_t)) {
 		resp_msg.req_num = 0;
@@ -313,7 +319,7 @@
 static void
 ps_panic_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
 {
-	ds_svc_hdl_t		ds_handle;
+	ds_svc_hdl_t		ds_handle = ds_panic_handle;
 	platsvc_panic_req_t	*msg = buf;
 	platsvc_panic_resp_t	resp_msg;
 	uint_t			rv;
@@ -321,7 +327,10 @@
 	if (arg == NULL)
 		return;
 
-	ds_handle = ds_panic_handle;
+	if (ds_handle == DS_INVALID_HDL) {
+		DBG("ps_panic_data_handler: DS handle no longer valid\n");
+		return;
+	}
 
 	if (msg == NULL || buflen != sizeof (platsvc_panic_req_t)) {
 		resp_msg.req_num = 0;
--- a/usr/src/uts/sun4v/platsvc/Makefile	Sun Mar 04 13:55:29 2007 -0800
+++ b/usr/src/uts/sun4v/platsvc/Makefile	Sun Mar 04 16:03:47 2007 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -71,13 +71,6 @@
 LDFLAGS		+= -dy -Nmisc/ds
 
 #
-# For now, disable these lint checks; maintainers should endeavor
-# to investigate and remove these for maximum lint coverage.
-# Please do not carry these forward to new Makefiles.
-#
-LINTTAGS	+= -erroff=E_SUSPICIOUS_COMPARISON
-
-#
 # Default build targets.
 #
 .KEEP_STATE:
--- a/usr/src/uts/sun4v/sys/mdeg.h	Sun Mar 04 13:55:29 2007 -0800
+++ b/usr/src/uts/sun4v/sys/mdeg.h	Sun Mar 04 16:03:47 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -83,7 +83,7 @@
 typedef struct {
 	md_t		*mdp;
 	mde_cookie_t	*mdep;
-	uint_t		nelem;
+	int		nelem;
 } mdeg_diff_t;
 
 /*