ide: Requeue request after DMA timeout
authorHerbert Xu <herbert@gondor.apana.org.au>
Wed, 31 Mar 2010 20:11:59 +0000 (20:11 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Apr 2010 08:31:13 +0000 (01:31 -0700)
I noticed that my KVM virtual machines were experiencing IDE
issues resulting in processes stuck on waiting for buffers to
complete.

The root cause is of course race conditions in the ancient qemu
backend that I'm using.  However, the fact that the guest isn't
recovering is a bug.

I've tracked it down to the change made last year to dequeue
requests at the start rather than at the end in the IDE layer.

commit 8f6205cd572fece673da0255d74843680f67f879
Author: Tejun Heo <tj@kernel.org>
Date:   Fri May 8 11:53:59 2009 +0900

    ide: dequeue in-flight request

The problem is that the function ide_dma_timeout_retry does not
requeue the current request, causing one request to be lost for
each DMA timeout.

This patch fixes this by requeueing the request.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/ide/ide-dma.c
drivers/ide/ide-io.c
include/linux/ide.h

index ee58c88dee5a61f51d437d1f618fd89745144785..fd40a8116574460883f964fe955be69ce8fed70f 100644 (file)
@@ -492,6 +492,7 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
        if (rq) {
                hwif->rq = NULL;
                rq->errors = 0;
+               ide_requeue_and_plug(drive, rq);
        }
        return ret;
 }
index db96138fefcdef55f923580a0404674f8178314b..172ac92181549ce09ba58126bf0a730f497f1666 100644 (file)
@@ -566,7 +566,7 @@ plug_device_2:
                blk_plug_device(q);
 }
 
-static void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
+void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
 {
        struct request_queue *q = drive->queue;
        unsigned long flags;
index 97e6ab43518469354dcebc3703d2aa7fa9c4ff5f..3239d1c10acb3479a823cbf37651419d1d1a93cf 100644 (file)
@@ -1169,6 +1169,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
 extern void ide_timer_expiry(unsigned long);
 extern irqreturn_t ide_intr(int irq, void *dev_id);
 extern void do_ide_request(struct request_queue *);
+extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);