diff options
author | alfred <alfred@FreeBSD.org> | 2001-03-09 18:40:34 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2001-03-09 18:40:34 +0000 |
commit | 219bcef498e84c0cb3c8a61cc0a6b4e806b2ad93 (patch) | |
tree | 8d6e93f1fb7aeeffce63fa478f35b677e95e86b5 /sys/kern/kern_resource.c | |
parent | 80d8e16746a7e6c767e69f1dd26ae918524229ad (diff) | |
download | FreeBSD-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.c | 43 |
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); |