svn commit: r223061 - head/sys/kern

Justin T. Gibbs gibbs at FreeBSD.org
Mon Jun 13 21:21:03 UTC 2011


Author: gibbs
Date: Mon Jun 13 21:21:02 2011
New Revision: 223061
URL: http://svn.freebsd.org/changeset/base/223061

Log:
  Fix a couple of race conditions in devstat(9) initialization.
  
  In devstat_new_entry(), there is no need to initialize the queue
  and the mutex in this function.  There are ways to do static
  initialization on both, so use STAILQ_HEAD_INITIALIZER and
  MTX_SYSINIT to initialize the queue and the mutex.
  
  In devstat_alloc(), use an atomic test and set routine to guard
  making our entry in /dev.  Using just a plain static variable
  creates a race condition on multiprocessor machines.  If you
  attempt to create a second entry in devfs, the kernel will panic.
  
  Submitted by:	kdm
  Reviewed by:	gibbs
  Sponsored by:	Spectra Logic Corporation
  MFC after:	1 week.

Modified:
  head/sys/kern/subr_devstat.c

Modified: head/sys/kern/subr_devstat.c
==============================================================================
--- head/sys/kern/subr_devstat.c	Mon Jun 13 21:03:27 2011	(r223060)
+++ head/sys/kern/subr_devstat.c	Mon Jun 13 21:21:02 2011	(r223061)
@@ -49,8 +49,9 @@ static long devstat_generation = 1;
 static int devstat_version = DEVSTAT_VERSION;
 static int devstat_current_devnumber;
 static struct mtx devstat_mutex;
+MTX_SYSINIT(devstat_mutex, &devstat_mutex, "devstat", MTX_DEF);
 
-static struct devstatlist device_statq;
+static struct devstatlist device_statq = STAILQ_HEAD_INITIALIZER(device_statq);
 static struct devstat *devstat_alloc(void);
 static void devstat_free(struct devstat *);
 static void devstat_add_entry(struct devstat *ds, const void *dev_name, 
@@ -70,13 +71,7 @@ devstat_new_entry(const void *dev_name,
 		  devstat_priority priority)
 {
 	struct devstat *ds;
-	static int once;
 
-	if (!once) {
-		STAILQ_INIT(&device_statq);
-		mtx_init(&devstat_mutex, "devstat", NULL, MTX_DEF);
-		once = 1;
-	}
 	mtx_assert(&devstat_mutex, MA_NOTOWNED);
 
 	ds = devstat_alloc();
@@ -475,10 +470,9 @@ devstat_alloc(void)
 	static int once;
 
 	mtx_assert(&devstat_mutex, MA_NOTOWNED);
-	if (!once) {
+	if (!once && atomic_cmpset_int(&once, 0, 1)) {
 		make_dev_credf(MAKEDEV_ETERNAL, &devstat_cdevsw, 0, NULL,
 		    UID_ROOT, GID_WHEEL, 0400, DEVSTAT_DEVICE_NAME);
-		once = 1;
 	}
 	spp2 = NULL;
 	mtx_lock(&devstat_mutex);


More information about the svn-src-all mailing list