summaryrefslogtreecommitdiffstats
path: root/sys/geom/concat
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2005-04-03 14:55:49 +0000
committerpjd <pjd@FreeBSD.org>2005-04-03 14:55:49 +0000
commitae7daf0c96f3f26bb42733b649e01af87e4752b6 (patch)
tree03c48419f201c9e7b07efb31e0fefb8635d000bb /sys/geom/concat
parent89c98c3d5b1b5283351185bbd6504725cd0f07fa (diff)
downloadFreeBSD-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.c20
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
OpenPOWER on IntegriCloud