diff options
author | phk <phk@FreeBSD.org> | 2003-04-25 21:20:57 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2003-04-25 21:20:57 +0000 |
commit | 017246b9b8dd3b24cd66f34840cceef6336634fa (patch) | |
tree | b4c1b3cd5e4ab706ca890ba10d06b784be813d05 /sys/geom/bde/g_bde_work.c | |
parent | a8b06a6a441f76581f3147c70a105b334a9fbdea (diff) | |
download | FreeBSD-src-017246b9b8dd3b24cd66f34840cceef6336634fa.zip FreeBSD-src-017246b9b8dd3b24cd66f34840cceef6336634fa.tar.gz |
Fix a problem and slightly improve the ENOMEM handling:
Give up the entire bio as soon as we detect a problem.
When we detect a problem, give up the bio by contributing the
remainder with ENOMEM, rather than kicking the bio back right
away.
If we failed on a non-first iteration we previously could end up
modifying fields in the bio after we delivered it. This could
account for memory corruption (none directly reported) on machines
with GBDE.
Diffstat (limited to 'sys/geom/bde/g_bde_work.c')
-rw-r--r-- | sys/geom/bde/g_bde_work.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/sys/geom/bde/g_bde_work.c b/sys/geom/bde/g_bde_work.c index d8186ce..9375051 100644 --- a/sys/geom/bde/g_bde_work.c +++ b/sys/geom/bde/g_bde_work.c @@ -720,18 +720,19 @@ g_bde_start1(struct bio *bp) mtx_lock(&sc->worklist_mutex); for(done = 0; done < bp->bio_length; ) { wp = g_bde_new_work(sc); - if (wp == NULL) { - g_io_deliver(bp, ENOMEM); - mtx_unlock(&sc->worklist_mutex); - return; + if (wp != NULL) { + wp->bp = bp; + wp->offset = bp->bio_offset + done; + wp->data = bp->bio_data + done; + wp->length = bp->bio_length - done; + g_bde_map_sector(wp); + done += wp->length; + g_bde_start2(wp); + } + if (wp == NULL || bp->bio_error != 0) { + g_bde_contribute(bp, bp->bio_length - done, ENOMEM); + break; } - wp->bp = bp; - wp->offset = bp->bio_offset + done; - wp->data = bp->bio_data + done; - wp->length = bp->bio_length - done; - g_bde_map_sector(wp); - done += wp->length; - g_bde_start2(wp); } mtx_unlock(&sc->worklist_mutex); return; |