summaryrefslogtreecommitdiffstats
path: root/sys/geom/vinum
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2004-10-26 21:01:42 +0000
committerle <le@FreeBSD.org>2004-10-26 21:01:42 +0000
commitd0679d2fdeeb0c9bb64e2ae78b7f98bc543d30d4 (patch)
tree382e6f6972c91797bf8981e2f40ccb5cbbeffc77 /sys/geom/vinum
parent2678190fba2279d62aa63ea24a5492273b2c4bce (diff)
downloadFreeBSD-src-d0679d2fdeeb0c9bb64e2ae78b7f98bc543d30d4.zip
FreeBSD-src-d0679d2fdeeb0c9bb64e2ae78b7f98bc543d30d4.tar.gz
Give each plex a separate queue where held back bios are put on.
This lowers the CPU usage of the worker thread and prevents a possible live lock on non-SMP machines. MFC candidate.
Diffstat (limited to 'sys/geom/vinum')
-rw-r--r--sys/geom/vinum/geom_vinum_plex.c18
-rw-r--r--sys/geom/vinum/geom_vinum_var.h1
2 files changed, 16 insertions, 3 deletions
diff --git a/sys/geom/vinum/geom_vinum_plex.c b/sys/geom/vinum/geom_vinum_plex.c
index 7ce5b08..31266f9 100644
--- a/sys/geom/vinum/geom_vinum_plex.c
+++ b/sys/geom/vinum/geom_vinum_plex.c
@@ -321,8 +321,9 @@ gv_plex_worker(void *arg)
} else if (bp->bio_cflags & GV_BIO_ONHOLD) {
/* Is it still locked out? */
if (gv_stripe_active(p, bp)) {
+ /* Park the bio on the waiting queue. */
mtx_lock(&p->bqueue_mtx);
- TAILQ_INSERT_TAIL(&p->bqueue, bq, queue);
+ TAILQ_INSERT_TAIL(&p->wqueue, bq, queue);
mtx_unlock(&p->bqueue_mtx);
} else {
g_free(bq);
@@ -371,8 +372,13 @@ gv_plex_completed_request(struct gv_plex *p, struct bio *bp)
}
if (TAILQ_EMPTY(&wp->bits)) {
bp->bio_parent->bio_completed += wp->length;
- if (wp->lockbase != -1)
+ if (wp->lockbase != -1) {
TAILQ_REMOVE(&p->packets, wp, list);
+ /* Bring the waiting bios back into the game. */
+ mtx_lock(&p->bqueue_mtx);
+ TAILQ_CONCAT(&p->bqueue, &p->wqueue, queue);
+ mtx_unlock(&p->bqueue_mtx);
+ }
g_free(wp);
}
@@ -413,6 +419,10 @@ gv_plex_completed_request(struct gv_plex *p, struct bio *bp)
} else {
bp->bio_parent->bio_completed += wp->length;
TAILQ_REMOVE(&p->packets, wp, list);
+ /* Bring the waiting bios back into the game. */
+ mtx_lock(&p->bqueue_mtx);
+ TAILQ_CONCAT(&p->bqueue, &p->wqueue, queue);
+ mtx_unlock(&p->bqueue_mtx);
g_free(wp);
}
}
@@ -569,11 +579,12 @@ gv_plex_normal_request(struct gv_plex *p, struct bio *bp)
*/
if (pbp->bio_driver1 != NULL &&
gv_stripe_active(p, pbp)) {
+ /* Park the bio on the waiting queue. */
pbp->bio_cflags |= GV_BIO_ONHOLD;
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = pbp;
mtx_lock(&p->bqueue_mtx);
- TAILQ_INSERT_TAIL(&p->bqueue, bq, queue);
+ TAILQ_INSERT_TAIL(&p->wqueue, bq, queue);
mtx_unlock(&p->bqueue_mtx);
} else
g_io_request(pbp, pbp->bio_caller2);
@@ -694,6 +705,7 @@ gv_plex_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
TAILQ_INIT(&p->packets);
TAILQ_INIT(&p->bqueue);
+ TAILQ_INIT(&p->wqueue);
mtx_init(&p->bqueue_mtx, "gv_plex", NULL, MTX_DEF);
kthread_create(gv_plex_worker, p, NULL, 0, 0, "gv_p %s",
p->name);
diff --git a/sys/geom/vinum/geom_vinum_var.h b/sys/geom/vinum/geom_vinum_var.h
index 196f7f8..95d8956 100644
--- a/sys/geom/vinum/geom_vinum_var.h
+++ b/sys/geom/vinum/geom_vinum_var.h
@@ -274,6 +274,7 @@ struct gv_plex {
struct mtx bqueue_mtx; /* Lock for the BIO queue. */
TAILQ_HEAD(,gv_bioq) bqueue; /* BIO queue. */
+ TAILQ_HEAD(,gv_bioq) wqueue; /* Waiting BIO queue. */
TAILQ_HEAD(,gv_raid5_packet) packets; /* RAID5 sub-requests. */
LIST_HEAD(,gv_sd) subdisks; /* List of attached subdisks. */
OpenPOWER on IntegriCloud