aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-06-20 15:07:56 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-06-20 15:07:56 +0100
commitfd2590bccc0bd63833813592a3e193686cf1c623 (patch)
tree2be06d9fe8553ef621282a2f068b133e160eeec7 /block.c
parent5edbd4e30426d3a0d712510b2509a521e35192b1 (diff)
parent5ab4b69ce29908b327a91966dc78ea0fd7424075 (diff)
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
# gpg: Signature made Mon 20 Jun 2016 15:05:24 BST # gpg: using RSA key 0x9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/block-pull-request: backup: follow AioContext change gracefully mirror: follow AioContext change gracefully blockjob: add AioContext attached callback block: use safe iteration over AioContext notifiers blockjob: add block_job_get_aio_context() blockjob: add pause points blockjob: rename block_job_is_paused() blockjob: move iostatus reset out of block_job_enter() block: process before_write_notifiers in bdrv_co_discard block: fix race in bdrv_co_discard with drive-mirror block: fixed BdrvTrackedRequest filling in bdrv_co_discard libqos: add qvirtqueue_cleanup() libqos: drop duplicated virtio_pci.h definitions libqos: drop duplicated virtio_scsi.h definitions libqos: drop duplicated virtio_blk.h definitions libqos: drop duplicated virtio_vring.h structs libqos: drop duplicated virtio_ring.h bit definitions libqos: drop duplicated virtio_config.h definitions libqos: drop duplicated PCI vendor ID definition libqos: use virtio_ids.h for device ID definitions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block.c')
-rw-r--r--block.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/block.c b/block.c
index b331eb9d38..c0ccc27c73 100644
--- a/block.c
+++ b/block.c
@@ -3609,18 +3609,34 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
return bs->aio_context;
}
+static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
+{
+ QLIST_REMOVE(ban, list);
+ g_free(ban);
+}
+
void bdrv_detach_aio_context(BlockDriverState *bs)
{
- BdrvAioNotifier *baf;
+ BdrvAioNotifier *baf, *baf_tmp;
BdrvChild *child;
if (!bs->drv) {
return;
}
- QLIST_FOREACH(baf, &bs->aio_notifiers, list) {
- baf->detach_aio_context(baf->opaque);
+ assert(!bs->walking_aio_notifiers);
+ bs->walking_aio_notifiers = true;
+ QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
+ if (baf->deleted) {
+ bdrv_do_remove_aio_context_notifier(baf);
+ } else {
+ baf->detach_aio_context(baf->opaque);
+ }
}
+ /* Never mind iterating again to check for ->deleted. bdrv_close() will
+ * remove remaining aio notifiers if we aren't called again.
+ */
+ bs->walking_aio_notifiers = false;
if (bs->drv->bdrv_detach_aio_context) {
bs->drv->bdrv_detach_aio_context(bs);
@@ -3635,7 +3651,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
void bdrv_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
- BdrvAioNotifier *ban;
+ BdrvAioNotifier *ban, *ban_tmp;
BdrvChild *child;
if (!bs->drv) {
@@ -3651,9 +3667,16 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
bs->drv->bdrv_attach_aio_context(bs, new_context);
}
- QLIST_FOREACH(ban, &bs->aio_notifiers, list) {
- ban->attached_aio_context(new_context, ban->opaque);
+ assert(!bs->walking_aio_notifiers);
+ bs->walking_aio_notifiers = true;
+ QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_tmp) {
+ if (ban->deleted) {
+ bdrv_do_remove_aio_context_notifier(ban);
+ } else {
+ ban->attached_aio_context(new_context, ban->opaque);
+ }
}
+ bs->walking_aio_notifiers = false;
}
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
@@ -3695,11 +3718,14 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
if (ban->attached_aio_context == attached_aio_context &&
ban->detach_aio_context == detach_aio_context &&
- ban->opaque == opaque)
+ ban->opaque == opaque &&
+ ban->deleted == false)
{
- QLIST_REMOVE(ban, list);
- g_free(ban);
-
+ if (bs->walking_aio_notifiers) {
+ ban->deleted = true;
+ } else {
+ bdrv_do_remove_aio_context_notifier(ban);
+ }
return;
}
}