summaryrefslogtreecommitdiffstats
path: root/sys/geom/vinum
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2005-07-15 13:38:06 +0000
committerle <le@FreeBSD.org>2005-07-15 13:38:06 +0000
commitc23617fec8c38c111c576ad08e9138caa0fe68c6 (patch)
tree94aef383c080b25e0e277d262c9d1f1070fe144a /sys/geom/vinum
parent245772fc5aa2b0b9f17ff9107a4ae49d753af77a (diff)
downloadFreeBSD-src-c23617fec8c38c111c576ad08e9138caa0fe68c6.zip
FreeBSD-src-c23617fec8c38c111c576ad08e9138caa0fe68c6.tar.gz
*) Implement round-robin reads for multiplex volumes.
*) Plug a possible memory leak. [1] [1] obtained from: pjd@.
Diffstat (limited to 'sys/geom/vinum')
-rw-r--r--sys/geom/vinum/geom_vinum_var.h1
-rw-r--r--sys/geom/vinum/geom_vinum_volume.c60
2 files changed, 36 insertions, 25 deletions
diff --git a/sys/geom/vinum/geom_vinum_var.h b/sys/geom/vinum/geom_vinum_var.h
index afc0308..47da372 100644
--- a/sys/geom/vinum/geom_vinum_var.h
+++ b/sys/geom/vinum/geom_vinum_var.h
@@ -311,6 +311,7 @@ struct gv_volume {
LIST_HEAD(,gv_plex) plexes; /* List of attached plexes. */
LIST_ENTRY(gv_volume) volume; /* Entry in vinum config. */
+ struct gv_plex *last_read_plex;
struct g_geom *geom; /* The geom of this volume. */
struct gv_softc *vinumconf; /* Pointer to the vinum config. */
};
diff --git a/sys/geom/vinum/geom_vinum_volume.c b/sys/geom/vinum/geom_vinum_volume.c
index 1e89cf8..1ecb1da 100644
--- a/sys/geom/vinum/geom_vinum_volume.c
+++ b/sys/geom/vinum/geom_vinum_volume.c
@@ -226,9 +226,10 @@ gv_vol_completed_request(struct gv_volume *v, struct bio *bp)
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;
+ struct gv_plex *p, *lp;
+ struct bio *cbp;
gp = v->geom;
@@ -244,52 +245,61 @@ gv_vol_normal_request(struct gv_volume *v, struct bio *bp)
* Try to find a good plex where we can send the request to.
* The plex either has to be up, or it's a degraded RAID5 plex.
*/
- p = NULL;
- LIST_FOREACH(p, &v->plexes, in_volume) {
+ lp = v->last_read_plex;
+ if (lp == NULL)
+ lp = LIST_FIRST(&v->plexes);
+ p = LIST_NEXT(lp, in_volume);
+ do {
+ if (p == NULL)
+ p = LIST_FIRST(&v->plexes);
if ((p->state > GV_PLEX_DEGRADED) ||
(p->state >= GV_PLEX_DEGRADED &&
p->org == GV_PLEX_RAID5))
break;
- }
- if (p == NULL) {
+ p = LIST_NEXT(p, in_volume);
+ } while (p != lp);
+
+ if (p == NULL ||
+ (p->org == GV_PLEX_RAID5 && p->state < GV_PLEX_DEGRADED) ||
+ (p->state <= GV_PLEX_DEGRADED)) {
g_destroy_bio(cbp);
bp->bio_children--;
g_io_deliver(bp, ENXIO);
return;
}
g_io_request(cbp, p->consumer);
+ v->last_read_plex = p;
break;
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;
}
}
OpenPOWER on IntegriCloud