summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2010-03-30 18:31:55 +0000
committerjhb <jhb@FreeBSD.org>2010-03-30 18:31:55 +0000
commit5bba6cc028d8ca1d72fadfd8cd906007acbc202d (patch)
tree4f411c47827014cff506f58fe554d8c00a806e6c
parent81e9dfe51bebaf025e2a674e72f112a6774c279f (diff)
downloadFreeBSD-src-5bba6cc028d8ca1d72fadfd8cd906007acbc202d.zip
FreeBSD-src-5bba6cc028d8ca1d72fadfd8cd906007acbc202d.tar.gz
Defer freeing a kevent list until after dropping kqueue locks.
LOR: 185 Submitted by: Matthew Fleming @ Isilon MFC after: 1 week
-rw-r--r--sys/kern/kern_event.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index cb418fb..5df669d 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1218,7 +1218,7 @@ static int
kqueue_expand(struct kqueue *kq, struct filterops *fops, uintptr_t ident,
int waitok)
{
- struct klist *list, *tmp_knhash;
+ struct klist *list, *tmp_knhash, *to_free;
u_long tmp_knhashmask;
int size;
int fd;
@@ -1226,6 +1226,7 @@ kqueue_expand(struct kqueue *kq, struct filterops *fops, uintptr_t ident,
KQ_NOTOWNED(kq);
+ to_free = NULL;
if (fops->f_isfd) {
fd = ident;
if (kq->kq_knlistsize <= fd) {
@@ -1237,13 +1238,13 @@ kqueue_expand(struct kqueue *kq, struct filterops *fops, uintptr_t ident,
return ENOMEM;
KQ_LOCK(kq);
if (kq->kq_knlistsize > fd) {
- free(list, M_KQUEUE);
+ to_free = list;
list = NULL;
} else {
if (kq->kq_knlist != NULL) {
bcopy(kq->kq_knlist, list,
kq->kq_knlistsize * sizeof(*list));
- free(kq->kq_knlist, M_KQUEUE);
+ to_free = kq->kq_knlist;
kq->kq_knlist = NULL;
}
bzero((caddr_t)list +
@@ -1265,11 +1266,12 @@ kqueue_expand(struct kqueue *kq, struct filterops *fops, uintptr_t ident,
kq->kq_knhash = tmp_knhash;
kq->kq_knhashmask = tmp_knhashmask;
} else {
- free(tmp_knhash, M_KQUEUE);
+ to_free = tmp_knhash;
}
KQ_UNLOCK(kq);
}
}
+ free(to_free, M_KQUEUE);
KQ_NOTOWNED(kq);
return 0;
OpenPOWER on IntegriCloud