block: Mark bdrv_unref_child() GRAPH_WRLOCK
Instead of taking the writer lock internally, require callers to already
hold it when calling bdrv_unref_child(). These callers will typically
already hold the graph lock once the locking work is completed, which
means that they can't call functions that take it internally.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20230911094620.45040-21-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/block.c b/block.c
index 9ea8333..e7f349b 100644
--- a/block.c
+++ b/block.c
@@ -1701,7 +1701,9 @@
open_failed:
bs->drv = NULL;
if (bs->file != NULL) {
+ bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, bs->file);
+ bdrv_graph_wrunlock();
assert(!bs->file);
}
g_free(bs->opaque);
@@ -3331,8 +3333,9 @@
* @root that point to @root, where necessary.
* @tran is allowed to be NULL. In this case no rollback is possible
*/
-static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child,
- Transaction *tran)
+static void GRAPH_WRLOCK
+bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child,
+ Transaction *tran)
{
BdrvChild *c;
@@ -3364,10 +3367,8 @@
return;
}
- bdrv_graph_wrlock(NULL);
bdrv_unset_inherits_from(parent, child, NULL);
bdrv_root_unref_child(child);
- bdrv_graph_wrunlock();
}
@@ -5164,9 +5165,11 @@
bs->drv = NULL;
}
+ bdrv_graph_wrlock(NULL);
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
bdrv_unref_child(bs, child);
}
+ bdrv_graph_wrunlock();
assert(!bs->backing);
assert(!bs->file);