summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_resource.c
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2001-03-09 18:40:34 +0000
committeralfred <alfred@FreeBSD.org>2001-03-09 18:40:34 +0000
commit219bcef498e84c0cb3c8a61cc0a6b4e806b2ad93 (patch)
tree8d6e93f1fb7aeeffce63fa478f35b677e95e86b5 /sys/kern/kern_resource.c
parent80d8e16746a7e6c767e69f1dd26ae918524229ad (diff)
downloadFreeBSD-src-219bcef498e84c0cb3c8a61cc0a6b4e806b2ad93.zip
FreeBSD-src-219bcef498e84c0cb3c8a61cc0a6b4e806b2ad93.tar.gz
Don't call malloc with M_WAITOK while holding a mutex.
Diffstat (limited to 'sys/kern/kern_resource.c')
-rw-r--r--sys/kern/kern_resource.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 73ffb03..d4a61eb 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -69,7 +69,6 @@ static struct mtx uihashtbl_mtx;
static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
static u_long uihash; /* size of hash table - 1 */
-static struct uidinfo *uicreate __P((uid_t uid));
static struct uidinfo *uilookup __P((uid_t uid));
/*
@@ -733,25 +732,6 @@ uilookup(uid)
}
/*
- * Create a uidinfo struct for the parameter uid.
- * uihashtbl_mtx must be locked.
- */
-static struct uidinfo *
-uicreate(uid)
- uid_t uid;
-{
- struct uidinfo *uip;
-
- mtx_assert(&uihashtbl_mtx, MA_OWNED);
- MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO,
- M_WAITOK | M_ZERO);
- LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
- uip->ui_uid = uid;
- mtx_init(&uip->ui_mtx, "uidinfo struct", MTX_DEF);
- return (uip);
-}
-
-/*
* Find or allocate a struct uidinfo for a particular uid.
* Increase refcount on uidinfo struct returned.
* uifree() should be called on a struct uidinfo when released.
@@ -764,8 +744,27 @@ uifind(uid)
mtx_lock(&uihashtbl_mtx);
uip = uilookup(uid);
- if (uip == NULL)
- uip = uicreate(uid);
+ if (uip == NULL) {
+ struct uidinfo *old_uip;
+
+ mtx_unlock(&uihashtbl_mtx);
+ uip = malloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO);
+ mtx_lock(&uihashtbl_mtx);
+ /*
+ * There's a chance someone created our uidinfo while we
+ * were in malloc and not holding the lock, so we have to
+ * make sure we don't insert a duplicate uidinfo
+ */
+ if ((old_uip = uilookup(uid)) != NULL) {
+ /* someone else beat us to it */
+ free(uip, M_UIDINFO);
+ uip = old_uip;
+ } else {
+ mtx_init(&uip->ui_mtx, "uidinfo struct", MTX_DEF);
+ uip->ui_uid = uid;
+ LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
+ }
+ }
uihold(uip);
mtx_unlock(&uihashtbl_mtx);
return (uip);
OpenPOWER on IntegriCloud