[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[qemu-xen staging-4.13] dma-helpers: ensure AIO callback is invoked after cancellation



commit fbde196c30e4797a51bda046ba514b187963d4ba
Author:     Paolo Bonzini <pbonzini@xxxxxxxxxx>
AuthorDate: Mon Jul 29 23:34:16 2019 +0200
Commit:     Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
CommitDate: Sun Oct 27 23:28:10 2019 -0500

    dma-helpers: ensure AIO callback is invoked after cancellation
    
    dma_aio_cancel unschedules the BH if there is one, which corresponds
    to the reschedule_dma case of dma_blk_cb.  This can stall the DMA
    permanently, because dma_complete will never get invoked and therefore
    nobody will ever invoke the original AIO callback in dbs->common.cb.
    
    Fix this by invoking the callback (which is ensured to happen after
    a bdrv_aio_cancel_async, or done manually in the dbs->bh case), and
    add assertions to check that the DMA state machine is indeed waiting
    for dma_complete or reschedule_dma, but never both.
    
    Reported-by: John Snow <jsnow@xxxxxxxxxx>
    Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
    Message-id: 20190729213416.1972-1-pbonzini@xxxxxxxxxx
    Signed-off-by: John Snow <jsnow@xxxxxxxxxx>
    (cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f)
    Signed-off-by: Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
---
 dma-helpers.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index 2d7e02d35e..d3871dc61e 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -90,6 +90,7 @@ static void reschedule_dma(void *opaque)
 {
     DMAAIOCB *dbs = (DMAAIOCB *)opaque;
 
+    assert(!dbs->acb && dbs->bh);
     qemu_bh_delete(dbs->bh);
     dbs->bh = NULL;
     dma_blk_cb(dbs, 0);
@@ -111,15 +112,12 @@ static void dma_complete(DMAAIOCB *dbs, int ret)
 {
     trace_dma_complete(dbs, ret, dbs->common.cb);
 
+    assert(!dbs->acb && !dbs->bh);
     dma_blk_unmap(dbs);
     if (dbs->common.cb) {
         dbs->common.cb(dbs->common.opaque, ret);
     }
     qemu_iovec_destroy(&dbs->iov);
-    if (dbs->bh) {
-        qemu_bh_delete(dbs->bh);
-        dbs->bh = NULL;
-    }
     qemu_aio_unref(dbs);
 }
 
@@ -179,14 +177,21 @@ static void dma_aio_cancel(BlockAIOCB *acb)
 
     trace_dma_aio_cancel(dbs);
 
+    assert(!(dbs->acb && dbs->bh));
     if (dbs->acb) {
+        /* This will invoke dma_blk_cb.  */
         blk_aio_cancel_async(dbs->acb);
+        return;
     }
+
     if (dbs->bh) {
         cpu_unregister_map_client(dbs->bh);
         qemu_bh_delete(dbs->bh);
         dbs->bh = NULL;
     }
+    if (dbs->common.cb) {
+        dbs->common.cb(dbs->common.opaque, -ECANCELED);
+    }
 }
 
 static AioContext *dma_get_aio_context(BlockAIOCB *acb)
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#staging-4.13



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.