Mercurial > illumos > illumos-gate
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; /*