aboutsummaryrefslogtreecommitdiff
path: root/sys/geom
diff options
context:
space:
mode:
authorPawel Jakub Dawidek <pjd@FreeBSD.org>2006-04-28 12:18:03 +0000
committerPawel Jakub Dawidek <pjd@FreeBSD.org>2006-04-28 12:18:03 +0000
commit84edb86df6f02dd4fb740700cee8b21346cd1551 (patch)
treeb4dea786dd60330354d599d5d4ad481ec276b163 /sys/geom
parenta2fe5c6676fe165b82917db14d61c82e884b364f (diff)
downloadsrc-84edb86df6f02dd4fb740700cee8b21346cd1551.tar.gz
src-84edb86df6f02dd4fb740700cee8b21346cd1551.zip
- Don't hold the device sx lock when going to sleep.
- Prevent possible live-lock in case of memory problems by freeing already completed requests first. Reported and tested by: markus, Bradley W. Dutton <brad-fbsd-stable@duttonbros.com> MFC after: 1 day
Notes
Notes: svn path=/head/; revision=158117
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/raid3/g_raid3.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c
index bb4f042f3522..2a71e94b4796 100644
--- a/sys/geom/raid3/g_raid3.c
+++ b/sys/geom/raid3/g_raid3.c
@@ -2031,6 +2031,7 @@ g_raid3_worker(void *arg)
G_RAID3_DEBUG(5, "%s: I'm here 4.", __func__);
continue;
}
+process:
bioq_remove(&sc->sc_queue, bp);
mtx_unlock(&sc->sc_queue_mtx);
@@ -2038,13 +2039,29 @@ g_raid3_worker(void *arg)
g_raid3_regular_request(bp);
else if ((bp->bio_cflags & G_RAID3_BIO_CFLAG_SYNC) != 0)
g_raid3_sync_request(bp);
- else {
- if (g_raid3_register_request(bp) != 0) {
- mtx_lock(&sc->sc_queue_mtx);
- bioq_insert_head(&sc->sc_queue, bp);
- MSLEEP(&sc->sc_queue, &sc->sc_queue_mtx,
- PRIBIO | PDROP, "r3:lowmem", hz / 10);
+ else if (g_raid3_register_request(bp) != 0) {
+ mtx_lock(&sc->sc_queue_mtx);
+ bioq_insert_head(&sc->sc_queue, bp);
+ /*
+ * We are short in memory, let see if there are finished
+ * request we can free.
+ */
+ TAILQ_FOREACH(bp, &sc->sc_queue.queue, bio_queue) {
+ if (bp->bio_cflags & G_RAID3_BIO_CFLAG_REGULAR)
+ goto process;
}
+ /*
+ * No finished regular request, so at least keep
+ * synchronization running.
+ */
+ TAILQ_FOREACH(bp, &sc->sc_queue.queue, bio_queue) {
+ if (bp->bio_cflags & G_RAID3_BIO_CFLAG_SYNC)
+ goto process;
+ }
+ sx_xunlock(&sc->sc_lock);
+ MSLEEP(&sc->sc_queue, &sc->sc_queue_mtx, PRIBIO | PDROP,
+ "r3:lowmem", hz / 10);
+ sx_xlock(&sc->sc_lock);
}
G_RAID3_DEBUG(5, "%s: I'm here 9.", __func__);
}