diff options
author | Pawel Jakub Dawidek <pjd@FreeBSD.org> | 2006-04-28 12:18:03 +0000 |
---|---|---|
committer | Pawel Jakub Dawidek <pjd@FreeBSD.org> | 2006-04-28 12:18:03 +0000 |
commit | 84edb86df6f02dd4fb740700cee8b21346cd1551 (patch) | |
tree | b4dea786dd60330354d599d5d4ad481ec276b163 /sys/geom | |
parent | a2fe5c6676fe165b82917db14d61c82e884b364f (diff) | |
download | src-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.c | 29 |
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__); } |