svn commit: r223061 - head/sys/kern

2011-06-13 Thread Justin T. Gibbs
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.cMon Jun 13 21:03:27 2011
(r223060)
+++ head/sys/kern/subr_devstat.cMon 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);
___
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to svn-src-all-unsubscr...@freebsd.org


Re: svn commit: r223061 - head/sys/kern

2011-06-13 Thread Kostik Belousov
On Mon, Jun 13, 2011 at 09:21:02PM +, Justin T. Gibbs wrote:
 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.
Devfs returns an error if MAKEDEV_CHECKNAME flag is supplied and
attempt is made to create the existing node. The static guard is
still useful, since make_dev() call is costly, but you can remove
the atomic, since the race should be of limited scope.


pgp7NTBL2jlKg.pgp
Description: PGP signature


Re: svn commit: r223061 - head/sys/kern

2011-06-13 Thread Kenneth D. Merry
On Tue, Jun 14, 2011 at 00:31:50 +0300, Kostik Belousov wrote:
 On Mon, Jun 13, 2011 at 09:21:02PM +, Justin T. Gibbs wrote:
  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.
 Devfs returns an error if MAKEDEV_CHECKNAME flag is supplied and
 attempt is made to create the existing node. The static guard is
 still useful, since make_dev() call is costly, but you can remove
 the atomic, since the race should be of limited scope.

Done, thanks for the suggestion!

Ken
-- 
Kenneth Merry
k...@freebsd.org
___
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to svn-src-all-unsubscr...@freebsd.org