diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-07-19 21:39:16 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-07-19 21:39:16 +0000 |
commit | 91ea221999a3fbd0f2b8687c99f4474b676d1bc7 (patch) | |
tree | ce75be306186ce1af955ec04ef8a10878b9c1fa3 /sys/kern/kern_bufq.c | |
parent | fdd4e4c86885800c16ecf900412f1dcac4d91637 (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.c | 20 |
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 |