summaryrefslogtreecommitdiff
path: root/sys/kern/kern_bufq.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2010-07-19 21:39:16 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2010-07-19 21:39:16 +0000
commit91ea221999a3fbd0f2b8687c99f4474b676d1bc7 (patch)
treece75be306186ce1af955ec04ef8a10878b9c1fa3 /sys/kern/kern_bufq.c
parentfdd4e4c86885800c16ecf900412f1dcac4d91637 (diff)
Avoid interleaving of mutexes that would leave is with the wrong spl after
calling bufq_quiesce(). Problem spotted by matthew@. ok matthew@, thib@
Diffstat (limited to 'sys/kern/kern_bufq.c')
-rw-r--r--sys/kern/kern_bufq.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/sys/kern/kern_bufq.c b/sys/kern/kern_bufq.c
index 31b69639d15..e59cac2faf5 100644
--- a/sys/kern/kern_bufq.c
+++ b/sys/kern/kern_bufq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_bufq.c,v 1.13 2010/07/08 23:18:55 dlg Exp $ */
+/* $OpenBSD: kern_bufq.c,v 1.14 2010/07/19 21:39:15 kettenis Exp $ */
/*
* Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org>
*
@@ -27,7 +27,7 @@
#include <sys/disklabel.h>
SLIST_HEAD(, bufq) bufqs = SLIST_HEAD_INITIALIZER(&bufq);
-struct mutex bufqs_mtx = MUTEX_INITIALIZER(IPL_BIO);
+struct mutex bufqs_mtx = MUTEX_INITIALIZER(IPL_NONE);
int bufqs_stop;
struct buf *(*bufq_dequeuev[BUFQ_HOWMANY])(struct bufq *, int) = {
@@ -71,6 +71,9 @@ bufq_init(int type)
KASSERT(error == 0);
mtx_enter(&bufqs_mtx);
+ while (bufqs_stop) {
+ msleep(&bufqs_stop, &bufqs_mtx, PRIBIO, "bqinit", 0);
+ }
SLIST_INSERT_HEAD(&bufqs, bq, bufq_entries);
mtx_leave(&bufqs_mtx);
@@ -87,7 +90,7 @@ bufq_destroy(struct bufq *bq)
mtx_enter(&bufqs_mtx);
while (bufqs_stop) {
- msleep(&bufqs_stop, &bufqs_mtx, PRIBIO, "bufqstop", 0);
+ msleep(&bufqs_stop, &bufqs_mtx, PRIBIO, "bqdest", 0);
}
SLIST_REMOVE(&bufqs, bq, bufq, bufq_entries);
mtx_leave(&bufqs_mtx);
@@ -100,7 +103,7 @@ bufq_queue(struct bufq *bq, struct buf *bp)
{
mtx_enter(&bq->bufq_mtx);
while (bq->bufq_stop) {
- msleep(&bq->bufq_stop, &bq->bufq_mtx, PRIBIO, "bufqstop", 0);
+ msleep(&bq->bufq_stop, &bq->bufq_mtx, PRIBIO, "bqqueue", 0);
}
bufq_queuev[bq->bufq_type](bq, bp);
mtx_leave(&bq->bufq_mtx);
@@ -146,21 +149,18 @@ bufq_quiesce(void)
{
struct bufq *bq;
-restart:
mtx_enter(&bufqs_mtx);
bufqs_stop = 1;
+ mtx_leave(&bufqs_mtx);
SLIST_FOREACH(bq, &bufqs, bufq_entries) {
mtx_enter(&bq->bufq_mtx);
bq->bufq_stop = 1;
- if (bq->bufq_outstanding) {
- mtx_leave(&bufqs_mtx);
+ while (bq->bufq_outstanding) {
msleep(&bq->bufq_outstanding, &bq->bufq_mtx,
- PRIBIO | PNORELOCK, "bufqqui", 0);
- goto restart;
+ PRIBIO, "bqquies", 0);
}
mtx_leave(&bq->bufq_mtx);
}
- mtx_leave(&bufqs_mtx);
}
void