1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-24 11:29:10 +00:00

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.
This commit is contained in:
Justin T. Gibbs 2011-06-13 21:21:02 +00:00
parent 454a02b372
commit 27c959cf05
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223061

View File

@ -49,8 +49,9 @@ static long devstat_generation = 1;
static int devstat_version = DEVSTAT_VERSION; static int devstat_version = DEVSTAT_VERSION;
static int devstat_current_devnumber; static int devstat_current_devnumber;
static struct mtx devstat_mutex; 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 struct devstat *devstat_alloc(void);
static void devstat_free(struct devstat *); static void devstat_free(struct devstat *);
static void devstat_add_entry(struct devstat *ds, const void *dev_name, 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) devstat_priority priority)
{ {
struct devstat *ds; 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); mtx_assert(&devstat_mutex, MA_NOTOWNED);
ds = devstat_alloc(); ds = devstat_alloc();
@ -475,10 +470,9 @@ devstat_alloc(void)
static int once; static int once;
mtx_assert(&devstat_mutex, MA_NOTOWNED); 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, make_dev_credf(MAKEDEV_ETERNAL, &devstat_cdevsw, 0, NULL,
UID_ROOT, GID_WHEEL, 0400, DEVSTAT_DEVICE_NAME); UID_ROOT, GID_WHEEL, 0400, DEVSTAT_DEVICE_NAME);
once = 1;
} }
spp2 = NULL; spp2 = NULL;
mtx_lock(&devstat_mutex); mtx_lock(&devstat_mutex);