aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2023-09-11 11:46:09 +0200
committerKevin Wolf <kwolf@redhat.com>2023-09-20 17:46:01 +0200
commit7d4ca9d25bce7e7cd3f1188ec5e5c46c649310c7 (patch)
treea19f7499b05ddafe813f3466a864a73d22417d61 /block
parent2f64e1fc57f1a275637ff6c34cb1a7207dc9e8c8 (diff)
block: Mark bdrv_attach_child_common() GRAPH_WRLOCK
Instead of taking the writer lock internally, require callers to already hold it when calling bdrv_attach_child_common(). 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. Note that the transaction callbacks still take the lock internally, so tran_finalize() must be called without the lock held. This is because bdrv_append() also calls bdrv_replace_node_noperm(), which currently requires the transaction callbacks to be called unlocked. In the next step, both of them can be switched to locked tran_finalize() calls together. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-ID: <20230911094620.45040-11-kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/stream.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/block/stream.c b/block/stream.c
index e522bbdec5..e4da214f1f 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -54,6 +54,7 @@ static int stream_prepare(Job *job)
{
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
+ BlockDriverState *unfiltered_bs_cow = bdrv_cow_bs(unfiltered_bs);
BlockDriverState *base;
BlockDriverState *unfiltered_base;
Error *local_err = NULL;
@@ -64,13 +65,18 @@ static int stream_prepare(Job *job)
s->cor_filter_bs = NULL;
/*
- * bdrv_set_backing_hd() requires that unfiltered_bs is drained. Drain
- * already here and use bdrv_set_backing_hd_drained() instead because
- * the polling during drained_begin() might change the graph, and if we do
- * this only later, we may end up working with the wrong base node (or it
- * might even have gone away by the time we want to use it).
+ * bdrv_set_backing_hd() requires that the unfiltered_bs and the COW child
+ * of unfiltered_bs is drained. Drain already here and use
+ * bdrv_set_backing_hd_drained() instead because the polling during
+ * drained_begin() might change the graph, and if we do this only later, we
+ * may end up working with the wrong base node (or it might even have gone
+ * away by the time we want to use it).
*/
bdrv_drained_begin(unfiltered_bs);
+ if (unfiltered_bs_cow) {
+ bdrv_ref(unfiltered_bs_cow);
+ bdrv_drained_begin(unfiltered_bs_cow);
+ }
base = bdrv_filter_or_cow_bs(s->above_base);
unfiltered_base = bdrv_skip_filters(base);
@@ -100,6 +106,10 @@ static int stream_prepare(Job *job)
}
out:
+ if (unfiltered_bs_cow) {
+ bdrv_drained_end(unfiltered_bs_cow);
+ bdrv_unref(unfiltered_bs_cow);
+ }
bdrv_drained_end(unfiltered_bs);
return ret;
}