From 8bbb2fba43dfa487685677b4a83d34de08775925 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 6 Nov 2010 10:29:46 -0700 Subject: [PATCH] kernel - Fix spinlock held on switch * flushbufqueues() was holding bufqspin through a buffer cache callback, causing a kernel panic if the callback winds up blocking. This only effected UFS not HAMMER). * Release the spinlock a little earlier so it isn't held around the callback. * Make a minor semantics change to bio_track_wait() to deal with potential compiler optimizations messing up the cmpxchg loop. Reported-by: "goetz@net-amp.com" --- sys/kern/vfs_bio.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 759c85c0b0..9f913438b7 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -602,6 +602,7 @@ bio_track_wait(struct bio_track *track, int slp_flags, int slp_timo) */ error = 0; while ((active = track->bk_active) != 0) { + cpu_ccfence(); desired = active | 0x80000000; tsleep_interlock(track, slp_flags); if (atomic_cmpset_int(&track->bk_active, active, desired)) { @@ -2606,9 +2607,14 @@ flushbufqueues(bufq_type_t q) break; } + spin_unlock(&bufqspin); + spun = 0; + if (LIST_FIRST(&bp->b_dep) != NULL && (bp->b_flags & B_DEFERRED) == 0 && buf_countdeps(bp, 0)) { + spin_lock(&bufqspin); + spun = 1; TAILQ_REMOVE(&bufqueues[q], bp, b_freelist); TAILQ_INSERT_TAIL(&bufqueues[q], bp, b_freelist); bp->b_flags |= B_DEFERRED; @@ -2626,9 +2632,6 @@ flushbufqueues(bufq_type_t q) * * NOTE: buf_checkwrite is MPSAFE. */ - spin_unlock(&bufqspin); - spun = 0; - if (LIST_FIRST(&bp->b_dep) != NULL && buf_checkwrite(bp)) { bremfree(bp); brelse(bp); -- 2.41.0