Index: geom_vinum_volume.c =================================================================== RCS file: /usr/repo/src/sys/geom/vinum/geom_vinum_volume.c,v retrieving revision 1.8 diff -u -p -r1.8 geom_vinum_volume.c --- geom_vinum_volume.c 23 Feb 2005 14:59:14 -0000 1.8 +++ geom_vinum_volume.c 11 May 2005 18:19:25 -0000 @@ -226,6 +226,7 @@ gv_vol_completed_request(struct gv_volum static void gv_vol_normal_request(struct gv_volume *v, struct bio *bp) { + struct bio_queue_head queue; struct g_geom *gp; struct gv_plex *p; struct bio *cbp, *pbp; @@ -263,33 +264,32 @@ gv_vol_normal_request(struct gv_volume * case BIO_WRITE: case BIO_DELETE: + bioq_init(&queue); LIST_FOREACH(p, &v->plexes, in_volume) { if (p->state < GV_PLEX_DEGRADED) continue; - cbp = g_clone_bio(bp); - if (cbp == NULL) /* XXX */ - g_io_deliver(bp, ENOMEM); - cbp->bio_done = gv_volume_done; - cbp->bio_caller2 = p->consumer; - - if (bp->bio_driver1 == NULL) { - bp->bio_driver1 = cbp; - } else { - pbp = bp->bio_driver1; - while (pbp->bio_caller1 != NULL) - pbp = pbp->bio_caller1; - pbp->bio_caller1 = cbp; + 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); + cbp->bio_done = gv_volume_done; + cbp->bio_caller1 = p->consumer; } - /* Fire off all sub-requests. */ - pbp = bp->bio_driver1; - while (pbp != NULL) { - g_io_request(pbp, pbp->bio_caller2); - pbp = pbp->bio_caller1; + for (cbp = bioq_first(&queue); cbp != NULL; + cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + g_io_request(cbp, cbp->bio_caller1); } - break; } }