From c33849dc41d24ae1362682bce0b8ebce43af556a Mon Sep 17 00:00:00 2001 From: pjd Date: Tue, 31 Oct 2006 21:23:51 +0000 Subject: Implement BIO_FLUSH handling by simply passing it down to the components. Sponsored by: home.pl --- sys/geom/concat/g_concat.c | 39 ++++++++++++++++++++++++++++++++++++++ sys/geom/eli/g_eli.c | 2 ++ sys/geom/geom_slice.c | 2 ++ sys/geom/mirror/g_mirror.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ sys/geom/raid3/g_raid3.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ sys/geom/stripe/g_stripe.c | 42 ++++++++++++++++++++++++++++++++++++++--- 6 files changed, 174 insertions(+), 3 deletions(-) (limited to 'sys/geom') diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index 8838e1a..9dae373 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -212,6 +212,42 @@ g_concat_access(struct g_provider *pp, int dr, int dw, int de) } static void +g_concat_flush(struct g_concat_softc *sc, struct bio *bp) +{ + struct bio_queue_head queue; + struct g_consumer *cp; + struct bio *cbp; + u_int no; + + bioq_init(&queue); + for (no = 0; no < sc->sc_ndisks; no++) { + 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); + cbp->bio_done = g_std_done; + cbp->bio_caller1 = sc->sc_disks[no].d_consumer; + cbp->bio_to = sc->sc_disks[no].d_consumer->provider; + } + for (cbp = bioq_first(&queue); cbp != NULL; cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + G_CONCAT_LOGREQ(cbp, "Sending request."); + cp = cbp->bio_caller1; + cbp->bio_caller1 = NULL; + g_io_request(cbp, cp); + } +} + +static void g_concat_start(struct bio *bp) { struct bio_queue_head queue; @@ -240,6 +276,9 @@ g_concat_start(struct bio *bp) case BIO_WRITE: case BIO_DELETE: break; + case BIO_FLUSH: + g_concat_flush(sc, bp); + return; case BIO_GETATTR: /* To which provider it should be delivered? */ default: diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 4c58fdd..a1965b8 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -258,6 +258,7 @@ g_eli_start(struct bio *bp) case BIO_READ: case BIO_WRITE: case BIO_GETATTR: + case BIO_FLUSH: break; case BIO_DELETE: /* @@ -298,6 +299,7 @@ g_eli_start(struct bio *bp) wakeup(sc); break; case BIO_GETATTR: + case BIO_FLUSH: cbp->bio_done = g_std_done; cp = LIST_FIRST(&sc->sc_geom->consumer); cbp->bio_to = cp->provider; diff --git a/sys/geom/geom_slice.c b/sys/geom/geom_slice.c index 2cf3385..c85e4a0 100644 --- a/sys/geom/geom_slice.c +++ b/sys/geom/geom_slice.c @@ -260,6 +260,8 @@ g_slice_start(struct bio *bp) gkd->length = gsp->slices[idx].length; /* now, pass it on downwards... */ } + /* FALLTHROUGH */ + case BIO_FLUSH: bp2 = g_clone_bio(bp); if (bp2 == NULL) { g_io_deliver(bp, ENOMEM); diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index fa956e2..f03da3b 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -1042,6 +1042,48 @@ g_mirror_kernel_dump(struct bio *bp) } static void +g_mirror_flush(struct g_mirror_softc *sc, struct bio *bp) +{ + struct bio_queue_head queue; + struct g_mirror_disk *disk; + struct g_consumer *cp; + struct bio *cbp; + + bioq_init(&queue); + LIST_FOREACH(disk, &sc->sc_disks, d_next) { + if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE) + continue; + 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); + cbp->bio_done = g_std_done; + cbp->bio_caller1 = disk; + cbp->bio_to = disk->d_consumer->provider; + } + for (cbp = bioq_first(&queue); cbp != NULL; cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + G_MIRROR_LOGREQ(3, cbp, "Sending request."); + disk = cbp->bio_caller1; + cbp->bio_caller1 = NULL; + cp = disk->d_consumer; + KASSERT(cp->acr >= 1 && cp->acw >= 1 && cp->ace >= 1, + ("Consumer %s not opened (r%dw%de%d).", cp->provider->name, + cp->acr, cp->acw, cp->ace)); + g_io_request(cbp, disk->d_consumer); + } +} + +static void g_mirror_start(struct bio *bp) { struct g_mirror_softc *sc; @@ -1061,6 +1103,9 @@ g_mirror_start(struct bio *bp) case BIO_WRITE: case BIO_DELETE: break; + case BIO_FLUSH: + g_mirror_flush(sc, bp); + return; case BIO_GETATTR: if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) { g_mirror_kernel_dump(bp); diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c index 66383bc..3cb1c6c 100644 --- a/sys/geom/raid3/g_raid3.c +++ b/sys/geom/raid3/g_raid3.c @@ -1370,6 +1370,50 @@ g_raid3_sync_done(struct bio *bp) } static void +g_raid3_flush(struct g_raid3_softc *sc, struct bio *bp) +{ + struct bio_queue_head queue; + struct g_raid3_disk *disk; + struct g_consumer *cp; + struct bio *cbp; + u_int i; + + bioq_init(&queue); + for (i = 0; i < sc->sc_ndisks; i++) { + disk = &sc->sc_disks[i]; + if (disk->d_state != G_RAID3_DISK_STATE_ACTIVE) + continue; + 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); + cbp->bio_done = g_std_done; + cbp->bio_caller1 = disk; + cbp->bio_to = disk->d_consumer->provider; + } + for (cbp = bioq_first(&queue); cbp != NULL; cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + G_RAID3_LOGREQ(3, cbp, "Sending request."); + disk = cbp->bio_caller1; + cbp->bio_caller1 = NULL; + cp = disk->d_consumer; + KASSERT(cp->acr >= 1 && cp->acw >= 1 && cp->ace >= 1, + ("Consumer %s not opened (r%dw%de%d).", cp->provider->name, + cp->acr, cp->acw, cp->ace)); + g_io_request(cbp, disk->d_consumer); + } +} + +static void g_raid3_start(struct bio *bp) { struct g_raid3_softc *sc; @@ -1390,6 +1434,9 @@ g_raid3_start(struct bio *bp) case BIO_WRITE: case BIO_DELETE: break; + case BIO_FLUSH: + g_raid3_flush(sc, bp); + return; case BIO_GETATTR: default: g_io_deliver(bp, EOPNOTSUPP); diff --git a/sys/geom/stripe/g_stripe.c b/sys/geom/stripe/g_stripe.c index 4f99ba4..8f8de35 100644 --- a/sys/geom/stripe/g_stripe.c +++ b/sys/geom/stripe/g_stripe.c @@ -520,6 +520,42 @@ failure: } static void +g_stripe_flush(struct g_stripe_softc *sc, struct bio *bp) +{ + struct bio_queue_head queue; + struct g_consumer *cp; + struct bio *cbp; + u_int no; + + bioq_init(&queue); + for (no = 0; no < sc->sc_ndisks; no++) { + 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); + cbp->bio_done = g_std_done; + cbp->bio_caller1 = sc->sc_disks[no]; + cbp->bio_to = sc->sc_disks[no]->provider; + } + for (cbp = bioq_first(&queue); cbp != NULL; cbp = bioq_first(&queue)) { + bioq_remove(&queue, cbp); + G_STRIPE_LOGREQ(cbp, "Sending request."); + cp = cbp->bio_caller1; + cbp->bio_caller1 = NULL; + g_io_request(cbp, cp); + } +} + +static void g_stripe_start(struct bio *bp) { off_t offset, start, length, nstripe; @@ -542,10 +578,10 @@ g_stripe_start(struct bio *bp) case BIO_READ: case BIO_WRITE: case BIO_DELETE: - /* - * Only those requests are supported. - */ break; + case BIO_FLUSH: + g_stripe_flush(sc, bp); + return; case BIO_GETATTR: /* To which provider it should be delivered? */ default: -- cgit v1.1