Skip to content

Commit

Permalink
block: acquire AioContext in bdrv_drain_all()
Browse files Browse the repository at this point in the history
Modify bdrv_drain_all() to take into account that BlockDriverState
instances may be running in different AioContexts.

This patch changes the implementation of bdrv_drain_all() while
preserving the semantics.  Previously kicking throttled requests and
checking for pending requests were done across all BlockDriverState
instances in sequence.  Now we process each BlockDriverState in turn,
making sure to acquire and release its AioContext.

This prevents race conditions between the thread executing
bdrv_drain_all() and the thread running the AioContext.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
stefanhaRH committed Jun 4, 2014
1 parent ed78cda commit 9b536ad
Showing 1 changed file with 11 additions and 14 deletions.
25 changes: 11 additions & 14 deletions block.c
Expand Up @@ -1885,17 +1885,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
return false;
}

static bool bdrv_requests_pending_all(void)
{
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
if (bdrv_requests_pending(bs)) {
return true;
}
}
return false;
}

/*
* Wait for pending requests to complete across all BlockDriverStates
*
Expand All @@ -1915,12 +1904,20 @@ void bdrv_drain_all(void)
BlockDriverState *bs;

while (busy) {
busy = false;

QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
bool bs_busy;

aio_context_acquire(aio_context);
bdrv_start_throttled_reqs(bs);
}
bs_busy = bdrv_requests_pending(bs);
bs_busy |= aio_poll(aio_context, bs_busy);
aio_context_release(aio_context);

busy = bdrv_requests_pending_all();
busy |= aio_poll(qemu_get_aio_context(), busy);
busy |= bs_busy;
}
}
}

Expand Down

0 comments on commit 9b536ad

Please sign in to comment.