summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2006-10-31 21:23:51 +0000
committerpjd <pjd@FreeBSD.org>2006-10-31 21:23:51 +0000
commitc33849dc41d24ae1362682bce0b8ebce43af556a (patch)
treee1cf58f0328589a697dacbff3b7e0c1982735a33 /sys
parent51fb042070317c283395fd7170157adbbc879898 (diff)
downloadFreeBSD-src-c33849dc41d24ae1362682bce0b8ebce43af556a.zip
FreeBSD-src-c33849dc41d24ae1362682bce0b8ebce43af556a.tar.gz
Implement BIO_FLUSH handling by simply passing it down to the components.
Sponsored by: home.pl
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/concat/g_concat.c39
-rw-r--r--sys/geom/eli/g_eli.c2
-rw-r--r--sys/geom/geom_slice.c2
-rw-r--r--sys/geom/mirror/g_mirror.c45
-rw-r--r--sys/geom/raid3/g_raid3.c47
-rw-r--r--sys/geom/stripe/g_stripe.c42
6 files changed, 174 insertions, 3 deletions
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:
OpenPOWER on IntegriCloud