6753387 No ereports sent to root domains after rebooting control and panicking both root domains
6753970 libds corrupts memory in fmd etm module
6756916 vlds driver doesn't throttle misbehaving clients
6756919 libds entry missing from usr/src/Makefile.lint
--- a/usr/src/Makefile.lint Sat Oct 11 18:43:57 2008 -0700
+++ b/usr/src/Makefile.lint Sun Oct 12 13:47:48 2008 -0700
@@ -461,6 +461,7 @@
cmd/prtfru \
cmd/sckmd \
cmd/vntsd \
+ lib/libds \
lib/libdscp \
lib/libpri \
lib/libpcp \
--- a/usr/src/lib/libds/Makefile.com Sat Oct 11 18:43:57 2008 -0700
+++ b/usr/src/lib/libds/Makefile.com Sun Oct 12 13:47:48 2008 -0700
@@ -44,11 +44,11 @@
LDLIBS += -lsysevent -lnvpair -lc
LINTFLAGS = -msux
-LINTFLAGS64 = -msux -Xarch=$(MACH64:sparcv9=v9)
+LINTFLAGS64 = -msux -m64
$(LINTLIB) := SRCS = $(LINTSRC:%=$(SRCDIR)/%)
$(LINTLIB) := LINTFLAGS = -nsvx -I$(ROOT)/usr/platform/sun4v/include
-$(LINTLIB) := LINTFLAGS64 = -nsvx -Xarch=$(MACH64:sparcv9=v9) \
+$(LINTLIB) := LINTFLAGS64 = -nsvx -m64 \
-I$(ROOT)/usr/platform/sun4v/include
.KEEP_STATE:
--- a/usr/src/lib/libds/common/libds.c Sat Oct 11 18:43:57 2008 -0700
+++ b/usr/src/lib/libds/common/libds.c Sun Oct 12 13:47:48 2008 -0700
@@ -43,10 +43,14 @@
typedef struct dslibentry {
ds_hdl_t dsl_hdl;
uint32_t dsl_flags;
+ uint32_t dsl_tflags;
char *dsl_service;
ds_ops_t dsl_ops;
} dslibentry_t;
+/* dsl_tflags */
+#define DSL_ENTRY_INUSE 0x0001 /* handle is currently active */
+
#define MIN_DSLIB_ENTRIES 64
static dslibentry_t *dslibtab;
static int ndslib;
@@ -69,6 +73,8 @@
* Static functions internal to dslib.
*/
static dslibentry_t *ds_hdl_to_dslibentry(ds_hdl_t hdl);
+static dslibentry_t *ds_new_dslibentry(void);
+static uint_t ds_service_count(char *service, boolean_t is_client);
static dslibentry_t *ds_lookup_dslibentry(char *service, boolean_t is_client);
static dslibentry_t *ds_register_dslibentry(ds_hdl_t hdl, char *service,
boolean_t is_client);
@@ -110,6 +116,24 @@
return (dsp);
}
+static uint_t
+ds_service_count(char *service, boolean_t is_client)
+{
+ int i;
+ dslibentry_t *dsp;
+ uint_t is_client_flag = is_client ? VLDS_REG_CLIENT : 0;
+ uint_t count = 0;
+
+ for (i = 0, dsp = dslibtab; i < ndslib; i++, dsp++) {
+ if (dsp->dsl_hdl != NULL &&
+ strcmp(dsp->dsl_service, service) == 0 &&
+ (dsp->dsl_flags & VLDS_REG_CLIENT) == is_client_flag) {
+ count++;
+ }
+ }
+ return (count);
+}
+
static dslibentry_t *
ds_lookup_dslibentry(char *service, boolean_t is_client)
{
@@ -131,36 +155,29 @@
ds_register_dslibentry(ds_hdl_t hdl, char *service, boolean_t is_client)
{
dslibentry_t *dsp, *orig_dsp;
- uint_t nhdls;
- if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL)
+ if ((dsp = ds_hdl_to_dslibentry(hdl)) != NULL) {
+ dsp->dsl_tflags |= DSL_ENTRY_INUSE;
return (dsp);
+ }
if ((orig_dsp = ds_lookup_dslibentry(service, is_client)) == NULL) {
return (NULL);
}
- /*
- * Find out if we have 1 or 2 or more handles. Having one implies
- * that we can reuse the current one handle for this service.
- * Having two or more implies we need to allocate a new handle.
- */
- if (ds_hdl_lookup(service, is_client, NULL, 2, &nhdls) != 0)
+ if ((orig_dsp->dsl_tflags & DSL_ENTRY_INUSE) == 0) {
+ /* use the original structure entry */
+ orig_dsp->dsl_tflags |= DSL_ENTRY_INUSE;
+ orig_dsp->dsl_hdl = hdl;
+ return (orig_dsp);
+ }
+
+ /* allocate a new structure entry */
+ if ((dsp = ds_new_dslibentry()) == NULL)
return (NULL);
- if (nhdls == 1) {
- /* reuse the original structure entry */
- dsp = orig_dsp;
- } else if (nhdls == 2) {
- /* allocate a new structure entry */
- if ((dsp = ds_new_dslibentry()) == NULL)
- return (NULL);
- *dsp = *orig_dsp;
- dsp->dsl_service = strdup(orig_dsp->dsl_service);
- } else {
- /* can't happen... */
- return (NULL);
- }
+ *dsp = *orig_dsp;
+ dsp->dsl_service = strdup(orig_dsp->dsl_service);
dsp->dsl_hdl = hdl;
return (dsp);
}
@@ -175,22 +192,22 @@
uint_t nhdls;
/*
- * Find out if we have 1 or 2 or more handles. Having one implies
- * that we want to leave the entry alone unless this is a ds_unreg_hdl
+ * Find out if we have 1 or 2 or more handles for the given
+ * service. Having one implies that we want to leave the entry
+ * intact but marked as not in use unless this is a ds_unreg_hdl
* (force_unreg is true).
*/
- if (ds_hdl_lookup(dsp->dsl_service,
- (dsp->dsl_flags & VLDS_REG_CLIENT) != 0, NULL, 2, &nhdls) != 0) {
- /* should never happen */
- return;
- }
+ nhdls = ds_service_count(dsp->dsl_service,
+ (dsp->dsl_flags & VLDS_REG_CLIENT) != 0);
- if ((nhdls == 1 && force_unreg) || nhdls == 2) {
+ if ((nhdls == 1 && force_unreg) || nhdls >= 2) {
dsp->dsl_hdl = NULL;
if (dsp->dsl_service) {
free(dsp->dsl_service);
}
(void) memset(dsp, 0, sizeof (dslibentry_t));
+ } else if (nhdls == 1) {
+ dsp->dsl_tflags &= ~DSL_ENTRY_INUSE;
}
}
@@ -316,7 +333,8 @@
return (errno);
if (dslibtab == NULL) {
- if ((dslibtab = malloc(sizeof (dslibentry_t) * ndslib)) == NULL)
+ dslibtab = malloc(sizeof (dslibentry_t) * MIN_DSLIB_ENTRIES);
+ if (dslibtab == NULL)
return (errno = ENOMEM);
ndslib = MIN_DSLIB_ENTRIES;
(void) memset(dslibtab, 0, sizeof (dslibentry_t) * ndslib);
@@ -415,6 +433,7 @@
*/
dsp->dsl_hdl = hdl;
dsp->dsl_flags = flags;
+ dsp->dsl_tflags = 0;
dsp->dsl_service = strdup(cap->svc_id);
dsp->dsl_ops = *ops;
(void) mutex_unlock(&dslib_lock);
--- a/usr/src/uts/sun4v/io/vlds.c Sat Oct 11 18:43:57 2008 -0700
+++ b/usr/src/uts/sun4v/io/vlds.c Sun Oct 12 13:47:48 2008 -0700
@@ -77,6 +77,7 @@
vlds_recv_hdr_t *recv_headp; /* ptr to head of recv queue */
vlds_recv_hdr_t *recv_tailp; /* ptr to tail of recv queue */
size_t recv_size; /* no. of bytes in recv queue */
+ uint_t recv_cnt; /* no of messages in recv queue */
kmutex_t recv_lock; /* lock for recv queue */
kcondvar_t recv_cv; /* condition variable for recv queue */
int recv_nreaders; /* no of currently waiting readers */
@@ -84,6 +85,7 @@
#define VLDS_RECV_OK 1
#define VLDS_RECV_UNREG_PENDING 2
+#define VLDS_RECV_OVERFLOW 3
static int vlds_ports_inited = 0;
@@ -179,6 +181,9 @@
NULL /* ds_ucap_init will fill in */
};
+static size_t vlds_recvq_maxsize = DS_STREAM_MTU * 8;
+static uint_t vlds_recvq_maxmsg = 16;
+
#define VLDS_MINOR_MAX SHRT_MAX
/* Definitions for binding handle array */
@@ -1393,6 +1398,7 @@
dpsp->recv_headp = NULL;
dpsp->recv_tailp = NULL;
dpsp->recv_size = 0;
+ dpsp->recv_cnt = 0;
}
static void
@@ -1400,6 +1406,7 @@
{
ASSERT(dpsp->state == VLDS_RECV_UNREG_PENDING);
ASSERT(dpsp->recv_size == 0);
+ ASSERT(dpsp->recv_cnt == 0);
ASSERT(dpsp->recv_headp == NULL);
ASSERT(dpsp->recv_tailp == NULL);
@@ -1418,8 +1425,17 @@
mutex_enter(&dpsp->recv_lock);
while (dpsp->recv_size == 0) {
+ ASSERT(dpsp->recv_cnt == 0);
if (dpsp->state == VLDS_RECV_UNREG_PENDING)
break;
+
+ if (dpsp->state == VLDS_RECV_OVERFLOW) {
+ DS_DBG_RCVQ(CE_NOTE, "%s: user data queue overflow",
+ __func__);
+ dpsp->state = VLDS_RECV_OK;
+ mutex_exit(&dpsp->recv_lock);
+ return (ENOBUFS);
+ }
/*
* Passing in a buflen of 0 allows user to poll for msgs.
*/
@@ -1462,7 +1478,9 @@
dpsp->recv_headp = rhp->next;
ASSERT(dpsp->recv_headp != NULL);
}
+ ASSERT(dpsp->recv_cnt > 0);
dpsp->recv_size -= rhp->datasz;
+ dpsp->recv_cnt -= 1;
mutex_exit(&dpsp->recv_lock);
msglen = rhp->datasz;
@@ -1503,6 +1521,7 @@
dpsp->recv_headp = NULL;
dpsp->recv_tailp = NULL;
dpsp->recv_size = 0;
+ dpsp->recv_cnt = 0;
/*
* Make sure other readers have exited.
@@ -1524,6 +1543,26 @@
mutex_enter(&dpsp->recv_lock);
if (dpsp->state != VLDS_RECV_UNREG_PENDING) {
+ /*
+ * If we've already encountered an overflow, or there
+ * are pending messages and either queue size and
+ * message limits will be exceeded with this message,
+ * we mark the recvq as overflowed and return an ENOBUFS
+ * error. This allows the enqueuing of one big message
+ * or several little messages.
+ */
+ if ((dpsp->state == VLDS_RECV_OVERFLOW) ||
+ ((dpsp->recv_cnt != 0) &&
+ ((dpsp->recv_size + buflen) > vlds_recvq_maxsize) ||
+ ((dpsp->recv_cnt + 1) > vlds_recvq_maxmsg))) {
+ DS_DBG_RCVQ(CE_NOTE, "%s: user data queue overflow",
+ __func__);
+ dpsp->state = VLDS_RECV_OVERFLOW;
+ cv_broadcast(&dpsp->recv_cv);
+ mutex_exit(&dpsp->recv_lock);
+ return (ENOBUFS);
+ }
+
DS_DBG_RCVQ(CE_NOTE, "%s: user data enqueued msglen: %ld",
__func__, buflen);
DS_DUMP_MSG(DS_DBG_FLAG_RCVQ, buf, buflen);
@@ -1540,6 +1579,7 @@
dpsp->recv_tailp = rhp;
}
dpsp->recv_size += rhp->datasz;
+ dpsp->recv_cnt += 1;
cv_broadcast(&dpsp->recv_cv);
}
mutex_exit(&dpsp->recv_lock);