Implement BIO_FLUSH handling by simply passing it down to the components.

Sponsored by:	home.pl
This commit is contained in:
pjd 2006-10-31 21:23:51 +00:00
parent 51fb042070
commit c33849dc41
6 changed files with 174 additions and 3 deletions

View File

@ -211,6 +211,42 @@ g_concat_access(struct g_provider *pp, int dr, int dw, int de)
return (error); return (error);
} }
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 static void
g_concat_start(struct bio *bp) g_concat_start(struct bio *bp)
{ {
@ -240,6 +276,9 @@ g_concat_start(struct bio *bp)
case BIO_WRITE: case BIO_WRITE:
case BIO_DELETE: case BIO_DELETE:
break; break;
case BIO_FLUSH:
g_concat_flush(sc, bp);
return;
case BIO_GETATTR: case BIO_GETATTR:
/* To which provider it should be delivered? */ /* To which provider it should be delivered? */
default: default:

View File

@ -258,6 +258,7 @@ g_eli_start(struct bio *bp)
case BIO_READ: case BIO_READ:
case BIO_WRITE: case BIO_WRITE:
case BIO_GETATTR: case BIO_GETATTR:
case BIO_FLUSH:
break; break;
case BIO_DELETE: case BIO_DELETE:
/* /*
@ -298,6 +299,7 @@ g_eli_start(struct bio *bp)
wakeup(sc); wakeup(sc);
break; break;
case BIO_GETATTR: case BIO_GETATTR:
case BIO_FLUSH:
cbp->bio_done = g_std_done; cbp->bio_done = g_std_done;
cp = LIST_FIRST(&sc->sc_geom->consumer); cp = LIST_FIRST(&sc->sc_geom->consumer);
cbp->bio_to = cp->provider; cbp->bio_to = cp->provider;

View File

@ -260,6 +260,8 @@ g_slice_start(struct bio *bp)
gkd->length = gsp->slices[idx].length; gkd->length = gsp->slices[idx].length;
/* now, pass it on downwards... */ /* now, pass it on downwards... */
} }
/* FALLTHROUGH */
case BIO_FLUSH:
bp2 = g_clone_bio(bp); bp2 = g_clone_bio(bp);
if (bp2 == NULL) { if (bp2 == NULL) {
g_io_deliver(bp, ENOMEM); g_io_deliver(bp, ENOMEM);

View File

@ -1041,6 +1041,48 @@ g_mirror_kernel_dump(struct bio *bp)
g_mirror_get_diskname(disk)); g_mirror_get_diskname(disk));
} }
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 static void
g_mirror_start(struct bio *bp) g_mirror_start(struct bio *bp)
{ {
@ -1061,6 +1103,9 @@ g_mirror_start(struct bio *bp)
case BIO_WRITE: case BIO_WRITE:
case BIO_DELETE: case BIO_DELETE:
break; break;
case BIO_FLUSH:
g_mirror_flush(sc, bp);
return;
case BIO_GETATTR: case BIO_GETATTR:
if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) { if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) {
g_mirror_kernel_dump(bp); g_mirror_kernel_dump(bp);

View File

@ -1369,6 +1369,50 @@ g_raid3_sync_done(struct bio *bp)
mtx_unlock(&sc->sc_queue_mtx); mtx_unlock(&sc->sc_queue_mtx);
} }
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 static void
g_raid3_start(struct bio *bp) g_raid3_start(struct bio *bp)
{ {
@ -1390,6 +1434,9 @@ g_raid3_start(struct bio *bp)
case BIO_WRITE: case BIO_WRITE:
case BIO_DELETE: case BIO_DELETE:
break; break;
case BIO_FLUSH:
g_raid3_flush(sc, bp);
return;
case BIO_GETATTR: case BIO_GETATTR:
default: default:
g_io_deliver(bp, EOPNOTSUPP); g_io_deliver(bp, EOPNOTSUPP);

View File

@ -519,6 +519,42 @@ g_stripe_start_economic(struct bio *bp, u_int no, off_t offset, off_t length)
return (error); return (error);
} }
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 static void
g_stripe_start(struct bio *bp) g_stripe_start(struct bio *bp)
{ {
@ -542,10 +578,10 @@ g_stripe_start(struct bio *bp)
case BIO_READ: case BIO_READ:
case BIO_WRITE: case BIO_WRITE:
case BIO_DELETE: case BIO_DELETE:
/*
* Only those requests are supported.
*/
break; break;
case BIO_FLUSH:
g_stripe_flush(sc, bp);
return;
case BIO_GETATTR: case BIO_GETATTR:
/* To which provider it should be delivered? */ /* To which provider it should be delivered? */
default: default: