Subject: Initialising the same pool multiple times
To: None <tech-kern@netbsd.org>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-kern
Date: 02/13/2006 17:28:55
Hi folks,

At the moment, it's possible to call pool_init() multiple times for
same pool.  Currently, this corrupts the "all-pools" list such that
"vmstat -m" will now endlessly loop.  The patch below panics if this
happens when DIAGNOSTIC is enabled, and otherwise prints a warning
then returns early..

Is this the best way to handle this condition?  Should the warning be
inside an "#ifdef DEBUG" check?

This same problem also affects the netbsd-3 branch, but because
the all-pools list uses a tailq instead of a list, you need to
s/LIST_FOREACH/TAILQ_FOREACH/.

Note that if you have multiple raid sets with RAIDframe you'll
trigger this condition.  Greg Oster will fix that side of things
in the next day or so...

Cheers,
Simon.
--
Simon Burge                                   <simonb@wasabisystems.com>
NetBSD Development, Support and Service:   http://www.wasabisystems.com/


Index: subr_pool.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_pool.c,v
retrieving revision 1.111
diff -d -p -u -r1.111 subr_pool.c
--- subr_pool.c	26 Jan 2006 15:07:25 -0000	1.111
+++ subr_pool.c	13 Feb 2006 05:10:31 -0000
@@ -467,13 +467,29 @@ void
 pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags,
     const char *wchan, struct pool_allocator *palloc)
 {
-	int off, slack;
+	struct pool *pp1;
 	size_t trysize, phsize;
-	int s;
+	int off, slack, s;
 
 	KASSERT((1UL << (CHAR_BIT * sizeof(pool_item_freelist_t))) - 2 >=
 	    PHPOOL_FREELIST_NELEM(PHPOOL_MAX - 1));
 
+	/*
+	 * Check that the pool hasn't already been initialised and
+	 * added to the list of all pools.
+	 */
+	LIST_FOREACH(pp1, &pool_head, pr_poollist) {
+		if (pp == pp1) {
+#ifdef DIAGNOSTIC
+			panic("pool_init: pool %s already initialised",
+			    wchan);
+#endif
+			printf("pool_init: pool %s already initialised\n",
+			    wchan);
+			return;
+		}
+	}
+
 #ifdef POOL_DIAGNOSTIC
 	/*
 	 * Always log if POOL_DIAGNOSTIC is defined.