From 2a9bf55a3db6b1a4a20c07fa030fde5ded02cf92 Mon Sep 17 00:00:00 2001 From: Jeffrey Cody Date: Thu, 30 Nov 2017 22:49:12 +0100 Subject: [PATCH 08/21] block: Expect graph changes in bdrv_parent_drained_begin/end RH-Author: Jeffrey Cody Message-id: <09d305a1846240448bc742a53a49ea87950e427d.1511985875.git.jcody@redhat.com> Patchwork-id: 78047 O-Subject: [RHV7.5 qemu-kvm-rhev PATCH 08/11] block: Expect graph changes in bdrv_parent_drained_begin/end Bugzilla: 1506531 RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi RH-Acked-by: John Snow From: Kevin Wolf The .drained_begin/end callbacks can (directly or indirectly via aio_poll()) cause block nodes to be removed or the current BdrvChild to point to a different child node. Use QLIST_FOREACH_SAFE() to make sure we don't access invalid BlockDriverStates or accidentally continue iterating the parents of the new child node instead of the node we actually came from. Signed-off-by: Kevin Wolf Tested-by: Jeff Cody Reviewed-by: Stefan Hajnoczi Reviewed-by: Jeff Cody Reviewed-by: Alberto Garcia Reviewed-by: Fam Zheng Signed-off-by: Kevin Wolf (cherry picked from commit 02d213009d571bcd7171e3ff9234722a11d30d1b) Signed-off-by: Jeff Cody Signed-off-by: Miroslav Rezanina --- block/io.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/block/io.c b/block/io.c index 3a717bc..4ff2f25 100644 --- a/block/io.c +++ b/block/io.c @@ -39,9 +39,9 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, void bdrv_parent_drained_begin(BlockDriverState *bs) { - BdrvChild *c; + BdrvChild *c, *next; - QLIST_FOREACH(c, &bs->parents, next_parent) { + QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) { if (c->role->drained_begin) { c->role->drained_begin(c); } @@ -50,9 +50,9 @@ void bdrv_parent_drained_begin(BlockDriverState *bs) void bdrv_parent_drained_end(BlockDriverState *bs) { - BdrvChild *c; + BdrvChild *c, *next; - QLIST_FOREACH(c, &bs->parents, next_parent) { + QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) { if (c->role->drained_end) { c->role->drained_end(c); } -- 1.8.3.1