diff options
author | pjd <pjd@FreeBSD.org> | 2005-04-03 14:55:49 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2005-04-03 14:55:49 +0000 |
commit | ae7daf0c96f3f26bb42733b649e01af87e4752b6 (patch) | |
tree | 03c48419f201c9e7b07efb31e0fefb8635d000bb /sys/geom/concat | |
parent | 89c98c3d5b1b5283351185bbd6504725cd0f07fa (diff) | |
download | FreeBSD-src-ae7daf0c96f3f26bb42733b649e01af87e4752b6.zip FreeBSD-src-ae7daf0c96f3f26bb42733b649e01af87e4752b6.tar.gz |
- Add a missing g_io_deliver() in case of allocation failure - we didn't
completed I/O requests here.
- First allocate all needed bios, so if any of allocations fail, we can
free memory before sending any I/O requests down.
Reported by: Pawel Malachowski
MFC after: 3 days
Diffstat (limited to 'sys/geom/concat')
-rw-r--r-- | sys/geom/concat/g_concat.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index 49087ca..f64ae0a 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -213,6 +213,7 @@ g_concat_access(struct g_provider *pp, int dr, int dw, int de) static void g_concat_start(struct bio *bp) { + struct bio_queue_head queue; struct g_concat_softc *sc; struct g_concat_disk *disk; struct g_provider *pp; @@ -250,6 +251,7 @@ g_concat_start(struct bio *bp) addr = bp->bio_data; end = offset + length; + bioq_init(&queue); for (no = 0; no < sc->sc_ndisks; no++) { disk = &sc->sc_disks[no]; if (disk->d_end <= offset) @@ -264,10 +266,17 @@ g_concat_start(struct bio *bp) cbp = g_clone_bio(bp); if (cbp == NULL) { + for (cbp = bioq_first(&queue); cbp != NULL; + cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + g_destroy_bio(cbp); + } if (bp->bio_error == 0) bp->bio_error = ENOMEM; + g_io_deliver(bp, bp->bio_error); return; } + bioq_insert_tail(&queue, cbp); /* * Fill in the component buf structure. */ @@ -277,16 +286,21 @@ g_concat_start(struct bio *bp) addr += len; cbp->bio_length = len; cbp->bio_to = disk->d_consumer->provider; - G_CONCAT_LOGREQ(cbp, "Sending request."); - g_io_request(cbp, disk->d_consumer); + cbp->bio_caller1 = disk; if (length == 0) break; } - KASSERT(length == 0, ("Length is still greater than 0 (class=%s, name=%s).", bp->bio_to->geom->class->name, bp->bio_to->geom->name)); + for (cbp = bioq_first(&queue); cbp != NULL; cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + G_CONCAT_LOGREQ(cbp, "Sending request."); + disk = cbp->bio_caller1; + cbp->bio_caller1 = NULL; + g_io_request(cbp, disk->d_consumer); + } } static void |