aio: fix qemu_bh_schedule() bh->ctx race condition

qemu_bh_schedule() is supposed to be thread-safe at least the first time
it is called.  Unfortunately this is not quite true:

  bh->scheduled = 1;
  aio_notify(bh->ctx);

Since another thread may run the BH callback once it has been scheduled,
there is a race condition if the callback frees the BH before
aio_notify(bh->ctx) has a chance to run.

Reported-by: Stefan Priebe <s.priebe@profihost.ag>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Stefan Priebe <s.priebe@profihost.ag>
This commit is contained in:
Stefan Hajnoczi 2014-06-03 11:21:01 +02:00
parent e00fcfeab3
commit 924fe1293c

14
async.c
View File

@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
void qemu_bh_schedule(QEMUBH *bh) void qemu_bh_schedule(QEMUBH *bh)
{ {
AioContext *ctx;
if (bh->scheduled) if (bh->scheduled)
return; return;
ctx = bh->ctx;
bh->idle = 0; bh->idle = 0;
/* Make sure that idle & any writes needed by the callback are done /* Make sure that:
* before the locations are read in the aio_bh_poll. * 1. idle & any writes needed by the callback are done before the
* locations are read in the aio_bh_poll.
* 2. ctx is loaded before scheduled is set and the callback has a chance
* to execute.
*/ */
smp_wmb(); smp_mb();
bh->scheduled = 1; bh->scheduled = 1;
aio_notify(bh->ctx); aio_notify(ctx);
} }