qemu-stable
[Top][All Lists]
Advanced

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

[Qemu-stable] [PATCH] stream: fix the deadlock bug when stream finish


From: Liu Yu
Subject: [Qemu-stable] [PATCH] stream: fix the deadlock bug when stream finish
Date: Sat, 23 Aug 2014 11:43:00 +0800
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0

From: Liu Yu <address@hidden>

The patch against branch stable-2.0

In case VM does IO while we run a stream job.
When stream finishes, the stream coroutine drains all IOs before
close the unused image, in bdrv_drain_all() it may find
a pending request which is submitted by guest IO coroutine.
In order to wait the pending req finish, the subsequent aio_poll()
call poll() to wait the req. however, if the req is already done by
threadpool and is waiting for the callback, there is no chance to switch
back to guest IO coroutine to call the callback and so that the stream
coroutine waits in poll() all the time.

The patch detects the deadlock case above and switch back to iothread
coroutine to handle the callback, and work on the stream coroutine
after the pending req get finished.

Signed-off-by: Liu Yu <address@hidden>
---
the issue can be reproduced by
1. guest does fio test
2. while host runs virsh blockpull repeatedly


 block.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/block.c b/block.c
index 990a754..f8c1a8d 100644
--- a/block.c
+++ b/block.c
@@ -1778,6 +1778,29 @@ static bool bdrv_requests_pending_all(void)
     return false;
 }
 
+static bool bdrv_request_coroutine_wait(void)
+{
+    BlockDriverState *bs;
+    Coroutine *co;
+
+    if (!qemu_in_coroutine())
+        return false;
+
+    co = qemu_coroutine_self();
+    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+        if (!QLIST_EMPTY(&bs->tracked_requests)) {
+            BdrvTrackedRequest *req = QLIST_FIRST(&bs->tracked_requests);
+
+            if(req->co == co)
+                continue;
+
+            qemu_co_queue_wait(&req->wait_queue);
+            return true;
+        }
+    }
+    return false;
+}
+
 /*
  * Wait for pending requests to complete across all BlockDriverStates
  *
@@ -1800,8 +1823,10 @@ void bdrv_drain_all(void)
         QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
             bdrv_start_throttled_reqs(bs);
         }
-
+recheck:
         busy = bdrv_requests_pending_all();
+        if (busy && bdrv_request_coroutine_wait())
+            goto recheck;
         busy |= aio_poll(qemu_get_aio_context(), busy);
     }
 }
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]