The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-123.1.2.vz7.5.1 ------> commit a5678140dd8f793272b5e562e81e27e2a249e4fd Author: Andrey Smetanin <asmeta...@virtuozzo.com> Date: Tue May 19 08:27:11 2015 +0400
ploop: fix busyloop on secondary discard bio After diff-ploop-add-a-separate-queue-for-discard-bio-s, ploop_thread() skips processing previously queued discard bio-s if any discard bio is already under processing (fbd->fbd_dbl is not empty). ploop_wait() must take care about such a case, otherwise a busyloop may happen: ploop_thread() believes that it has to go to sleep because all incoming queues are empty excepting plo->bio_discard_list which cannot be processed by now and calls ploop_wait(); the latter returns immediately because plo->bio_discard_list is not empty and hence needs for processing. The patch also fixes a trivial bug in discard bio accounting: ploop_bio_queue() is called for all bio-s including discard bio-s and it decrements bio_qlen unconditionally. This is incorrect: it has to decrement either bio_qlen or discard_bio_qlen dependently on the type of bio. https://jira.sw.ru/browse/PSBM-30451 https://bugzilla.openvz.org/show_bug.cgi?id=3124 Signed-off-by: Maxim Patlasov <mpatla...@parallels.com> Acked-by: Andrew Vagin <ava...@parallels.com> --- drivers/block/ploop/dev.c | 9 +++++++-- drivers/block/ploop/freeblks.c | 12 ++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c index e2ff0aa..ac0f28f 100644 --- a/drivers/block/ploop/dev.c +++ b/drivers/block/ploop/dev.c @@ -551,7 +551,11 @@ ploop_bio_queue(struct ploop_device * plo, struct bio * bio, __TRACE("A %p %u\n", preq, preq->req_cluster); - plo->bio_qlen--; + if (unlikely(bio->bi_rw & REQ_DISCARD)) + plo->bio_discard_qlen--; + else + plo->bio_qlen--; + ploop_entry_add(plo, preq); if (bio->bi_size && !(bio->bi_rw & REQ_DISCARD)) @@ -2563,7 +2567,8 @@ static void ploop_wait(struct ploop_device * plo, int once, struct blk_plug *plu !plo->active_reqs)) break; } else if (plo->bio_head || - !bio_list_empty(&plo->bio_discard_list)) { + (!bio_list_empty(&plo->bio_discard_list) && + !ploop_discard_is_inprogress(plo->fbd))) { /* ready_queue and entry_queue are empty, but * bio list not. Obviously, we'd like to process * bio_list instead of sleeping */ diff --git a/drivers/block/ploop/freeblks.c b/drivers/block/ploop/freeblks.c index cf48d3a..89108c7 100644 --- a/drivers/block/ploop/freeblks.c +++ b/drivers/block/ploop/freeblks.c @@ -696,20 +696,24 @@ int ploop_fb_get_free_block(struct ploop_freeblks_desc *fbd, static void fbd_complete_bio(struct ploop_freeblks_desc *fbd, int err) { + struct ploop_device *plo = fbd->plo; unsigned int nr_completed = 0; while (fbd->fbd_dbl.head) { struct bio * bio = fbd->fbd_dbl.head; fbd->fbd_dbl.head = bio->bi_next; bio->bi_next = NULL; - BIO_ENDIO(fbd->plo->queue, bio, err); + BIO_ENDIO(plo->queue, bio, err); nr_completed++; } fbd->fbd_dbl.tail = NULL; - spin_lock_irq(&fbd->plo->lock); - fbd->plo->bio_total -= nr_completed; - spin_unlock_irq(&fbd->plo->lock); + spin_lock_irq(&plo->lock); + plo->bio_total -= nr_completed; + if (!bio_list_empty(&plo->bio_discard_list) && + waitqueue_active(&plo->waitq)) + wake_up_interruptible(&plo->waitq); + spin_unlock_irq(&plo->lock); } void ploop_fb_reinit(struct ploop_freeblks_desc *fbd, int err) _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel