svn commit: r223061 - head/sys/kern

[ Available lists | Index of svn-src-head | Month of Jun 2011 | Week of 13 Jun 2011 | Raw email | View thread | Wrap long lines | Reply | Tag ]
From
Justin T. Gibbs <gibbs@FreeBSD.org>
Date
13 Jun 2011 21:21:03
Subject
svn commit: r223061 - head/sys/kern
Message-ID
201106132121.p5DLL2Fp099153@svn.freebsd.org


[ Hide this part ]
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);


Elapsed time: 0.112 seconds