From 173c72b7ff883e6effbab186448146172ed98c04 Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Wed, 31 Mar 2010 10:19:38 +0000 Subject: [PATCH] dsched_fq - properly drain all queues on teardown * Properly drain all fqp queues on teardown to ensure that no bios and especially fqps are left dangling around. * This should fix the occasional panic during policy switches. --- sys/dsched/fq/dsched_fq_core.c | 21 +++++++++++++++++++-- sys/dsched/fq/dsched_fq_diskops.c | 21 +++++++++++---------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/sys/dsched/fq/dsched_fq_core.c b/sys/dsched/fq/dsched_fq_core.c index d490af72c6..1425202068 100644 --- a/sys/dsched/fq/dsched_fq_core.c +++ b/sys/dsched/fq/dsched_fq_core.c @@ -368,7 +368,25 @@ fq_dispatcher(struct dsched_fq_dpriv *dpriv) * supposed to die away nicely or that the disk is idle. */ - if (dpriv->die == 1) { + if (__predict_false(dpriv->die == 1)) { + /* If we are supposed to die, drain all queues */ + TAILQ_FOREACH_MUTABLE(fqp, &dpriv->fq_priv_list, + dlink, fqp2) { + if (fqp->qlength == 0) + continue; + + FQ_FQP_LOCK(fqp); + TAILQ_FOREACH_MUTABLE(bio, &fqp->queue, + link, bio2) { + TAILQ_REMOVE(&fqp->queue, bio, + link); + --fqp->qlength; + fq_dispatch(dpriv, bio, fqp); + } + FQ_FQP_UNLOCK(fqp); + } + + /* Now we can safely unlock and exit */ FQ_DPRIV_UNLOCK(dpriv); kprintf("fq_dispatcher is peacefully dying\n"); lwkt_exit(); @@ -404,7 +422,6 @@ fq_dispatcher(struct dsched_fq_dpriv *dpriv) if ((fqp->max_tp > 0) && idle && (fqp->issued >= fqp->max_tp)) { fqp->max_tp += 5; - ++fqp->idle_generation; } TAILQ_FOREACH_MUTABLE(bio, &fqp->queue, link, bio2) { diff --git a/sys/dsched/fq/dsched_fq_diskops.c b/sys/dsched/fq/dsched_fq_diskops.c index 44edcfe992..ef2badcf9f 100644 --- a/sys/dsched/fq/dsched_fq_diskops.c +++ b/sys/dsched/fq/dsched_fq_diskops.c @@ -163,7 +163,7 @@ fq_teardown(struct disk *dp) * but how do we get rid of all loose fqps? * --> possibly same solution as devfs; tracking a list of * orphans. - * but for now we don't care much about this yet + * XXX XXX: this XXX is probably irrelevant by now :) */ } @@ -192,16 +192,17 @@ fq_cancel(struct disk *dp) */ FQ_DPRIV_LOCK(dpriv); TAILQ_FOREACH_MUTABLE(fqp, &dpriv->fq_priv_list, dlink, fqp2) { - if (fqp->qlength > 0) { - FQ_FQP_LOCK(fqp); - TAILQ_FOREACH_MUTABLE(bio, &fqp->queue, link, bio2) { - TAILQ_REMOVE(&fqp->queue, bio, link); - --fqp->qlength; - dsched_cancel_bio(bio); - atomic_add_int(&fq_stats.cancelled, 1); - } - FQ_FQP_UNLOCK(fqp); + if (fqp->qlength == 0) + continue; + + FQ_FQP_LOCK(fqp); + TAILQ_FOREACH_MUTABLE(bio, &fqp->queue, link, bio2) { + TAILQ_REMOVE(&fqp->queue, bio, link); + --fqp->qlength; + dsched_cancel_bio(bio); + atomic_add_int(&fq_stats.cancelled, 1); } + FQ_FQP_UNLOCK(fqp); } FQ_DPRIV_UNLOCK(dpriv); } -- 2.41.0