changeset 4138:c1afdb77f1fa

6534136 nsc_ctx_t's waiters list is poorly protected 6537512 nscd hangs desktop at password prompt with gdm 6550191 nscd should update the queries-queued (wait_count) counter
author michen
date Mon, 30 Apr 2007 14:34:54 -0700
parents 8bbbcf1ea205
children 5f9029783cc0
files usr/src/cmd/nscd/cache.c usr/src/cmd/nscd/cache.h usr/src/cmd/nscd/nscd_wait.c
diffstat 3 files changed, 40 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/nscd/cache.c	Mon Apr 30 13:20:49 2007 -0700
+++ b/usr/src/cmd/nscd/cache.c	Mon Apr 30 14:34:54 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1514,8 +1514,7 @@
 				"%s: no clearance to wait\n");
 			}
 			/* yes can wait */
-			(void) nscd_wait(&ctx->wait, &nscdb->db_mutex,
-					&this_stats->status);
+			(void) nscd_wait(ctx, nscdb, this_entry);
 			(void) _nscd_release_clearance(&ctx->throttle_sema);
 			continue;
 		}
@@ -1557,7 +1556,7 @@
 		(void) _nscd_release_clearance(&ctx->throttle_sema);
 
 		/* signal waiting threads */
-		(void) nscd_signal(&ctx->wait, &this_stats->status);
+		(void) nscd_signal(ctx, nscdb, this_entry);
 
 		_NSCD_LOG(NSCD_LOG_CACHE, NSCD_LOG_LEVEL_DEBUG)
 		(me, "%s: name service lookup status = %d\n",
--- a/usr/src/cmd/nscd/cache.h	Mon Apr 30 13:20:49 2007 -0700
+++ b/usr/src/cmd/nscd/cache.h	Mon Apr 30 14:34:54 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -117,15 +117,6 @@
 } nsc_action_t;
 
 /*
- * Structure to handle waiting for pending name service requests
- */
-typedef struct waiter {
-	cond_t		w_waitcv;
-	uint8_t		*w_key;
-	struct waiter	*w_next, *w_prev;
-} waiter_t;
-
-/*
  *  What each entry in the nameserver cache looks like.
  */
 
@@ -152,6 +143,16 @@
 } nsc_keephot_t;
 
 /*
+ * Structure to handle waiting for pending name service requests
+ */
+typedef struct waiter {
+	cond_t		w_waitcv;
+	uint8_t		w_signaled;
+	nsc_entry_t	*w_key;
+	struct waiter	*w_next, *w_prev;
+} waiter_t;
+
+/*
  * Macros used by hash table
  *
  * _NSC_HTSIZE_PRIMES are prime numbers that are used as hash table
@@ -249,6 +250,7 @@
 	int		dbop;
 	char 		*name;
 	mutex_t		db_mutex;
+	waiter_t	db_wait;	/* lookup wait CV */
 	int		htsize;
 	enum hash_type {
 		nsc_ht_default = 0,
@@ -290,7 +292,6 @@
 	const char 	*file_name;		/* filename for check_files */
 	int		db_count;		/* number of caches */
 	nsc_db_t 	*nsc_db[_NSC_MAX_DB];	/* caches */
-	waiter_t	wait;			/* lookup wait CV */
 	sema_t		throttle_sema;		/* throttle lookups */
 	sema_t		revalidate_sema;	/* revalidation threads */
 	nscd_bool_t	revalidate_on;		/* reval. thread started */
@@ -329,8 +330,8 @@
 extern void tnrhdb_init_ctx(nsc_ctx_t *);
 
 /* Functions used to throttle threads */
-extern int nscd_wait(waiter_t *, mutex_t *, uint8_t *);
-extern int nscd_signal(waiter_t *, uint8_t *);
+extern int nscd_wait(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *);
+extern int nscd_signal(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *);
 
 /* Cache creation and initialization */
 extern nscd_rc_t init_cache();
--- a/usr/src/cmd/nscd/nscd_wait.c	Mon Apr 30 13:20:49 2007 -0700
+++ b/usr/src/cmd/nscd/nscd_wait.c	Mon Apr 30 14:34:54 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,19 +32,26 @@
 #include "cache.h"
 
 int
-nscd_wait(waiter_t *wchan,  mutex_t *lock, uint8_t *key)
+nscd_wait(nsc_ctx_t *ctx, nsc_db_t *nscdb, nsc_entry_t *entry)
 {
-	waiter_t mywait;
+	waiter_t	mywait;
+	waiter_t	*wchan = &nscdb->db_wait;
+
 	(void) cond_init(&(mywait.w_waitcv), USYNC_THREAD, 0);
-	mywait.w_key = key;
+	mywait.w_key = entry;
+	mywait.w_signaled = 0;
 	mywait.w_next = wchan->w_next;
 	mywait.w_prev = wchan;
 	if (mywait.w_next)
 		mywait.w_next->w_prev = &mywait;
 	wchan->w_next = &mywait;
 
-	while (*key & ST_PENDING)
-		(void) cond_wait(&(mywait.w_waitcv), lock);
+	(void) mutex_lock(&ctx->stats_mutex);
+	ctx->stats.wait_count++;
+	(void) mutex_unlock(&ctx->stats_mutex);
+
+	while (!mywait.w_signaled)
+		(void) cond_wait(&(mywait.w_waitcv), &nscdb->db_mutex);
 	if (mywait.w_prev)
 		mywait.w_prev->w_next = mywait.w_next;
 	if (mywait.w_next)
@@ -53,14 +60,20 @@
 }
 
 int
-nscd_signal(waiter_t *wchan, uint8_t *key)
+nscd_signal(nsc_ctx_t *ctx, nsc_db_t *nscdb, nsc_entry_t *entry)
 {
-	int c = 0;
-	waiter_t *tmp = wchan->w_next;
+	int		c = 0;
+	waiter_t	*wchan = &nscdb->db_wait;
+	waiter_t	*tmp = wchan->w_next;
 
 	while (tmp) {
-		if (tmp->w_key == key) {
+		if (tmp->w_key == entry) {
 			(void) cond_signal(&(tmp->w_waitcv));
+			tmp->w_signaled = 1;
+
+			(void) mutex_lock(&ctx->stats_mutex);
+			ctx->stats.wait_count--;
+			(void) mutex_unlock(&ctx->stats_mutex);
 			c++;
 		}
 		tmp = tmp->w_next;