Blame SOURCES/kvm-util-async-use-atomic_mb_set-in-qemu_bh_cancel.patch

4a2fec
From 550b4bcc2758e8df86570bc1afb29de34a1694fe Mon Sep 17 00:00:00 2001
4a2fec
From: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
Date: Mon, 13 Nov 2017 16:29:39 +0100
4a2fec
Subject: [PATCH 03/30] util/async: use atomic_mb_set in qemu_bh_cancel
4a2fec
4a2fec
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
Message-id: <20171113162939.5486-2-stefanha@redhat.com>
4a2fec
Patchwork-id: 77665
4a2fec
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH 1/1] util/async: use atomic_mb_set in qemu_bh_cancel
4a2fec
Bugzilla: 1508886
4a2fec
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
RH-Acked-by: John Snow <jsnow@redhat.com>
4a2fec
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
4a2fec
4a2fec
From: Sergio Lopez <slp@redhat.com>
4a2fec
4a2fec
Commit b7a745d added a qemu_bh_cancel call to the completion function
4a2fec
as an optimization to prevent it from unnecessarily rescheduling itself.
4a2fec
4a2fec
This completion function is scheduled from worker_thread, after setting
4a2fec
the state of a ThreadPoolElement to THREAD_DONE.
4a2fec
4a2fec
This was considered to be safe, as the completion function restarts the
4a2fec
loop just after the call to qemu_bh_cancel. But, as this loop lacks a HW
4a2fec
memory barrier, the read of req->state may actually happen _before_ the
4a2fec
call, seeing it still as THREAD_QUEUED, and ending the completion
4a2fec
function without having processed a pending TPE linked at pool->head:
4a2fec
4a2fec
         worker thread             |            I/O thread
4a2fec
------------------------------------------------------------------------
4a2fec
                                   | speculatively read req->state
4a2fec
req->state = THREAD_DONE;          |
4a2fec
qemu_bh_schedule(p->completion_bh) |
4a2fec
  bh->scheduled = 1;               |
4a2fec
                                   | qemu_bh_cancel(p->completion_bh)
4a2fec
                                   |   bh->scheduled = 0;
4a2fec
                                   | if (req->state == THREAD_DONE)
4a2fec
                                   |   // sees THREAD_QUEUED
4a2fec
4a2fec
The source of the misunderstanding was that qemu_bh_cancel is now being
4a2fec
used by the _consumer_ rather than the producer, and therefore now needs
4a2fec
to have acquire semantics just like e.g. aio_bh_poll.
4a2fec
4a2fec
In some situations, if there are no other independent requests in the
4a2fec
same aio context that could eventually trigger the scheduling of the
4a2fec
completion function, the omitted TPE and all operations pending on it
4a2fec
will get stuck forever.
4a2fec
4a2fec
[Added Sergio's updated wording about the HW memory barrier.
4a2fec
--Stefan]
4a2fec
4a2fec
Signed-off-by: Sergio Lopez <slp@redhat.com>
4a2fec
Message-id: 20171108063447.2842-1-slp@redhat.com
4a2fec
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
4a2fec
(cherry picked from commit ef6dada8b44e1e7c4bec5c1115903af9af415b50)
4a2fec
4a2fec
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 util/async.c | 2 +-
4a2fec
 1 file changed, 1 insertion(+), 1 deletion(-)
4a2fec
4a2fec
diff --git a/util/async.c b/util/async.c
4a2fec
index 355af73..0e1bd87 100644
4a2fec
--- a/util/async.c
4a2fec
+++ b/util/async.c
4a2fec
@@ -174,7 +174,7 @@ void qemu_bh_schedule(QEMUBH *bh)
4a2fec
  */
4a2fec
 void qemu_bh_cancel(QEMUBH *bh)
4a2fec
 {
4a2fec
-    bh->scheduled = 0;
4a2fec
+    atomic_mb_set(&bh->scheduled, 0);
4a2fec
 }
4a2fec
 
4a2fec
 /* This func is async.The bottom half will do the delete action at the finial
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec