diff options
author | Yogita Urade <yogita.urade@windriver.com> | 2024-08-21 09:01:03 +0000 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2024-09-03 05:39:12 -0700 |
commit | 8c533e92423a77efe3b5d1419ec69723d7e23146 (patch) | |
tree | 853bddcc5cfbaecfcbfb45a71eddcdca7f5758d6 | |
parent | c5627ab06fc07221237b9a7059ac378ea80578f8 (diff) | |
download | poky-8c533e92423a77efe3b5d1419ec69723d7e23146.tar.gz |
qemu: fix CVE-2024-4467
A flaw was found in the QEMU disk image utility (qemu-img) 'info'
command. A specially crafted image file containing a `json:{}`
value describing block devices in QMP could cause the qemu-img
process on the host to consume large amounts of memory or CPU time,
leading to denial of service or read/write to an existing external file
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-4467
Upstream Patches:
https://gitlab.com/qemu-project/qemu/-/commit/bd385a5298d7062668e804d73944d52aec9549f1
https://gitlab.com/qemu-project/qemu/-/commit/2eb42a728d27a43fdcad5f37d3f65706ce6deba5
https://gitlab.com/qemu-project/qemu/-/commit/7e1110664ecbc4826f3c978ccb06b6c1bce823e6
https://gitlab.com/qemu-project/qemu/-/commit/6bc30f19498547fac9cef98316a65cf6c1f14205
https://gitlab.com/qemu-project/qemu/-/commit/7ead946998610657d38d1a505d5f25300d4ca613
(From OE-Core rev: 0e309919b8807950cebc8924fc1e15763548b1f1)
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r-- | meta/recipes-devtools/qemu/qemu.inc | 5 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch | 112 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch | 55 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch | 57 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch | 1187 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch | 239 |
6 files changed, 1655 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc index 3643b9a544..50d92b04bd 100644 --- a/meta/recipes-devtools/qemu/qemu.inc +++ b/meta/recipes-devtools/qemu/qemu.inc | |||
@@ -40,6 +40,11 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \ | |||
40 | file://0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch \ | 40 | file://0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch \ |
41 | file://qemu-guest-agent.init \ | 41 | file://qemu-guest-agent.init \ |
42 | file://qemu-guest-agent.udev \ | 42 | file://qemu-guest-agent.udev \ |
43 | file://CVE-2024-4467-0001.patch \ | ||
44 | file://CVE-2024-4467-0002.patch \ | ||
45 | file://CVE-2024-4467-0003.patch \ | ||
46 | file://CVE-2024-4467-0004.patch \ | ||
47 | file://CVE-2024-4467-0005.patch \ | ||
43 | " | 48 | " |
44 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" | 49 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" |
45 | 50 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch new file mode 100644 index 0000000000..dbcc71bb4e --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch | |||
@@ -0,0 +1,112 @@ | |||
1 | From bd385a5298d7062668e804d73944d52aec9549f1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kevin Wolf <kwolf@redhat.com> | ||
3 | Date: Fri, 16 Aug 2024 08:29:04 +0000 | ||
4 | Subject: [PATCH] qcow2: Don't open data_file with BDRV_O_NO_IO | ||
5 | |||
6 | One use case for 'qemu-img info' is verifying that untrusted images | ||
7 | don't reference an unwanted external file, be it as a backing file or an | ||
8 | external data file. To make sure that calling 'qemu-img info' can't | ||
9 | already have undesired side effects with a malicious image, just don't | ||
10 | open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do | ||
11 | I/O, we don't need to have it open. | ||
12 | |||
13 | This changes the output of iotests case 061, which used 'qemu-img info' | ||
14 | to show that opening an image with an invalid data file fails. After | ||
15 | this patch, it succeeds. Replace this part of the test with a qemu-io | ||
16 | call, but keep the final 'qemu-img info' to show that the invalid data | ||
17 | file is correctly displayed in the output. | ||
18 | |||
19 | Fixes: CVE-2024-4467 | ||
20 | Cc: qemu-stable@nongnu.org | ||
21 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
22 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
23 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
24 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
25 | |||
26 | CVE: CVE-2024-4667 | ||
27 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/bd385a5298d7062668e804d73944d52aec9549f1] | ||
28 | |||
29 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
30 | --- | ||
31 | block/qcow2.c | 17 ++++++++++++++++- | ||
32 | tests/qemu-iotests/061 | 6 ++++-- | ||
33 | tests/qemu-iotests/061.out | 8 ++++++-- | ||
34 | 3 files changed, 26 insertions(+), 5 deletions(-) | ||
35 | |||
36 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
37 | index 13e032bd5..7af7c0bee 100644 | ||
38 | --- a/block/qcow2.c | ||
39 | +++ b/block/qcow2.c | ||
40 | @@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, | ||
41 | goto fail; | ||
42 | } | ||
43 | |||
44 | - if (open_data_file) { | ||
45 | + if (open_data_file && (flags & BDRV_O_NO_IO)) { | ||
46 | + /* | ||
47 | + * Don't open the data file for 'qemu-img info' so that it can be used | ||
48 | + * to verify that an untrusted qcow2 image doesn't refer to external | ||
49 | + * files. | ||
50 | + * | ||
51 | + * Note: This still makes has_data_file() return true. | ||
52 | + */ | ||
53 | + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { | ||
54 | + s->data_file = NULL; | ||
55 | + } else { | ||
56 | + s->data_file = bs->file; | ||
57 | + } | ||
58 | + qdict_extract_subqdict(options, NULL, "data-file."); | ||
59 | + qdict_del(options, "data-file"); | ||
60 | + } else if (open_data_file) { | ||
61 | /* Open external data file */ | ||
62 | bdrv_graph_co_rdunlock(); | ||
63 | s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs, | ||
64 | diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 | ||
65 | index 53c7d428e..b71ac097d 100755 | ||
66 | --- a/tests/qemu-iotests/061 | ||
67 | +++ b/tests/qemu-iotests/061 | ||
68 | @@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||
69 | echo | ||
70 | _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M | ||
71 | $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||
72 | -_img_info --format-specific | ||
73 | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt | ||
74 | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io | ||
75 | TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||
76 | |||
77 | echo | ||
78 | $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" | ||
79 | -_img_info --format-specific | ||
80 | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt | ||
81 | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io | ||
82 | TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||
83 | |||
84 | echo | ||
85 | diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out | ||
86 | index 139fc6817..24c33add7 100644 | ||
87 | --- a/tests/qemu-iotests/061.out | ||
88 | +++ b/tests/qemu-iotests/061.out | ||
89 | @@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
90 | qemu-img: data-file can only be set for images that use an external data file | ||
91 | |||
92 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data | ||
93 | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory | ||
94 | +qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory | ||
95 | +read 4096/4096 bytes at offset 0 | ||
96 | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
97 | image: TEST_DIR/t.IMGFMT | ||
98 | file format: IMGFMT | ||
99 | virtual size: 64 MiB (67108864 bytes) | ||
100 | @@ -560,7 +562,9 @@ Format specific information: | ||
101 | corrupt: false | ||
102 | extended l2: false | ||
103 | |||
104 | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image | ||
105 | +qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image | ||
106 | +read 4096/4096 bytes at offset 0 | ||
107 | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
108 | image: TEST_DIR/t.IMGFMT | ||
109 | file format: IMGFMT | ||
110 | virtual size: 64 MiB (67108864 bytes) | ||
111 | -- | ||
112 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch new file mode 100644 index 0000000000..686176189c --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch | |||
@@ -0,0 +1,55 @@ | |||
1 | From 2eb42a728d27a43fdcad5f37d3f65706ce6deba5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kevin Wolf <kwolf@redhat.com> | ||
3 | Date: Fri, 16 Aug 2024 09:35:24 +0000 | ||
4 | Subject: [PATCH] iotests/244: Don't store data-file with protocol in image | ||
5 | |||
6 | We want to disable filename parsing for data files because it's too easy | ||
7 | to abuse in malicious image files. Make the test ready for the change by | ||
8 | passing the data file explicitly in command line options. | ||
9 | |||
10 | Cc: qemu-stable@nongnu.org | ||
11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
13 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
15 | |||
16 | CVE: CVE-2024-4467 | ||
17 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/2eb42a728d27a43fdcad5f37d3f65706ce6deba5] | ||
18 | |||
19 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
20 | --- | ||
21 | tests/qemu-iotests/244 | 19 ++++++++++++++++--- | ||
22 | 1 file changed, 16 insertions(+), 3 deletions(-) | ||
23 | |||
24 | diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 | ||
25 | index 3e61fa25b..bb9cc6512 100755 | ||
26 | --- a/tests/qemu-iotests/244 | ||
27 | +++ b/tests/qemu-iotests/244 | ||
28 | @@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" | ||
29 | $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||
30 | |||
31 | # blkdebug doesn't support copy offloading, so this tests the error path | ||
32 | -$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG" | ||
33 | -$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" | ||
34 | -$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||
35 | +test_img_with_blkdebug="json:{ | ||
36 | + 'driver': 'qcow2', | ||
37 | + 'file': { | ||
38 | + 'driver': 'file', | ||
39 | + 'filename': '$TEST_IMG' | ||
40 | + }, | ||
41 | + 'data-file': { | ||
42 | + 'driver': 'blkdebug', | ||
43 | + 'image': { | ||
44 | + 'driver': 'file', | ||
45 | + 'filename': '$TEST_IMG.data' | ||
46 | + } | ||
47 | + } | ||
48 | +}" | ||
49 | +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug" | ||
50 | +$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug" | ||
51 | |||
52 | echo | ||
53 | echo "=== Flushing should flush the data file ===" | ||
54 | -- | ||
55 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch new file mode 100644 index 0000000000..02611d6732 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch | |||
@@ -0,0 +1,57 @@ | |||
1 | From 7e1110664ecbc4826f3c978ccb06b6c1bce823e6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kevin Wolf <kwolf@redhat.com> | ||
3 | Date: Fri, 16 Aug 2024 10:24:58 +0000 | ||
4 | Subject: [PATCH] iotests/270: Don't store data-file with json: prefix in image | ||
5 | |||
6 | We want to disable filename parsing for data files because it's too easy | ||
7 | to abuse in malicious image files. Make the test ready for the change by | ||
8 | passing the data file explicitly in command line options. | ||
9 | |||
10 | Cc: qemu-stable@nongnu.org | ||
11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
13 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
14 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
15 | |||
16 | CVE: CVE-2024-4467 | ||
17 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/7e1110664ecbc4826f3c978ccb06b6c1bce823e6] | ||
18 | |||
19 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
20 | --- | ||
21 | tests/qemu-iotests/270 | 14 +++++++++++--- | ||
22 | 1 file changed, 11 insertions(+), 3 deletions(-) | ||
23 | |||
24 | diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270 | ||
25 | index 74352342d..c37b674aa 100755 | ||
26 | --- a/tests/qemu-iotests/270 | ||
27 | +++ b/tests/qemu-iotests/270 | ||
28 | @@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \ | ||
29 | # "write" 2G of data without using any space. | ||
30 | # (qemu-img create does not like it, though, because null-co does not | ||
31 | # support image creation.) | ||
32 | -$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ | ||
33 | - "$TEST_IMG" | ||
34 | +test_img_with_null_data="json:{ | ||
35 | + 'driver': '$IMGFMT', | ||
36 | + 'file': { | ||
37 | + 'filename': '$TEST_IMG' | ||
38 | + }, | ||
39 | + 'data-file': { | ||
40 | + 'driver': 'null-co', | ||
41 | + 'size':'4294967296' | ||
42 | + } | ||
43 | +}" | ||
44 | |||
45 | # This gives us a range of: | ||
46 | # 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31 | ||
47 | @@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ | ||
48 | # on L2 boundaries, we need large L2 tables; hence the cluster size of | ||
49 | # 2 MB. (Anything from 256 kB should work, though, because then one L2 | ||
50 | # table covers 8 GB.) | ||
51 | -$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io | ||
52 | +$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io | ||
53 | |||
54 | _check_test_img | ||
55 | |||
56 | -- | ||
57 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch new file mode 100644 index 0000000000..7568a453c4 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch | |||
@@ -0,0 +1,1187 @@ | |||
1 | From 6bc30f19498547fac9cef98316a65cf6c1f14205 Mon Sep 17 00:00:00 2001 | ||
2 | From: Stefan Hajnoczi <stefanha@redhat.com> | ||
3 | Date: Tue, 5 Dec 2023 13:20:02 -0500 | ||
4 | Subject: [PATCH] graph-lock: remove AioContext locking | ||
5 | |||
6 | Stop acquiring/releasing the AioContext lock in | ||
7 | bdrv_graph_wrlock()/bdrv_graph_unlock() since the lock no longer has any | ||
8 | effect. | ||
9 | |||
10 | The distinction between bdrv_graph_wrunlock() and | ||
11 | bdrv_graph_wrunlock_ctx() becomes meaningless and they can be collapsed | ||
12 | into one function. | ||
13 | |||
14 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
15 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
16 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
17 | Message-ID: <20231205182011.1976568-6-stefanha@redhat.com> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
19 | |||
20 | CVE: CVE-2024-4467 | ||
21 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/6bc30f19498547fac9cef98316a65cf6c1f14205] | ||
22 | |||
23 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
24 | --- | ||
25 | block.c | 50 +++++++++++++++--------------- | ||
26 | block/backup.c | 4 +-- | ||
27 | block/blklogwrites.c | 8 ++--- | ||
28 | block/blkverify.c | 4 +-- | ||
29 | block/block-backend.c | 11 +++---- | ||
30 | block/commit.c | 16 +++++----- | ||
31 | block/graph-lock.c | 44 ++------------------------ | ||
32 | block/mirror.c | 22 ++++++------- | ||
33 | block/qcow2.c | 4 +-- | ||
34 | block/quorum.c | 8 ++--- | ||
35 | block/replication.c | 14 ++++----- | ||
36 | block/snapshot.c | 4 +-- | ||
37 | block/stream.c | 12 +++---- | ||
38 | block/vmdk.c | 20 ++++++------ | ||
39 | blockdev.c | 8 ++--- | ||
40 | blockjob.c | 12 +++---- | ||
41 | include/block/graph-lock.h | 21 ++----------- | ||
42 | scripts/block-coroutine-wrapper.py | 4 +-- | ||
43 | tests/unit/test-bdrv-drain.c | 40 ++++++++++++------------ | ||
44 | tests/unit/test-bdrv-graph-mod.c | 20 ++++++------ | ||
45 | 20 files changed, 133 insertions(+), 193 deletions(-) | ||
46 | |||
47 | diff --git a/block.c b/block.c | ||
48 | index bfb0861ec..25e1ebc60 100644 | ||
49 | --- a/block.c | ||
50 | +++ b/block.c | ||
51 | @@ -1708,12 +1708,12 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name, | ||
52 | open_failed: | ||
53 | bs->drv = NULL; | ||
54 | |||
55 | - bdrv_graph_wrlock(NULL); | ||
56 | + bdrv_graph_wrlock(); | ||
57 | if (bs->file != NULL) { | ||
58 | bdrv_unref_child(bs, bs->file); | ||
59 | assert(!bs->file); | ||
60 | } | ||
61 | - bdrv_graph_wrunlock(NULL); | ||
62 | + bdrv_graph_wrunlock(); | ||
63 | |||
64 | g_free(bs->opaque); | ||
65 | bs->opaque = NULL; | ||
66 | @@ -3575,9 +3575,9 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, | ||
67 | |||
68 | bdrv_ref(drain_bs); | ||
69 | bdrv_drained_begin(drain_bs); | ||
70 | - bdrv_graph_wrlock(backing_hd); | ||
71 | + bdrv_graph_wrlock(); | ||
72 | ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp); | ||
73 | - bdrv_graph_wrunlock(backing_hd); | ||
74 | + bdrv_graph_wrunlock(); | ||
75 | bdrv_drained_end(drain_bs); | ||
76 | bdrv_unref(drain_bs); | ||
77 | |||
78 | @@ -3790,13 +3790,13 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
79 | return NULL; | ||
80 | } | ||
81 | |||
82 | - bdrv_graph_wrlock(NULL); | ||
83 | + bdrv_graph_wrlock(); | ||
84 | ctx = bdrv_get_aio_context(bs); | ||
85 | aio_context_acquire(ctx); | ||
86 | child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
87 | errp); | ||
88 | aio_context_release(ctx); | ||
89 | - bdrv_graph_wrunlock(NULL); | ||
90 | + bdrv_graph_wrunlock(); | ||
91 | |||
92 | return child; | ||
93 | } | ||
94 | @@ -4650,9 +4650,9 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) | ||
95 | aio_context_release(ctx); | ||
96 | } | ||
97 | |||
98 | - bdrv_graph_wrlock(NULL); | ||
99 | + bdrv_graph_wrlock(); | ||
100 | tran_commit(tran); | ||
101 | - bdrv_graph_wrunlock(NULL); | ||
102 | + bdrv_graph_wrunlock(); | ||
103 | |||
104 | QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) { | ||
105 | BlockDriverState *bs = bs_entry->state.bs; | ||
106 | @@ -4669,9 +4669,9 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) | ||
107 | goto cleanup; | ||
108 | |||
109 | abort: | ||
110 | - bdrv_graph_wrlock(NULL); | ||
111 | + bdrv_graph_wrlock(); | ||
112 | tran_abort(tran); | ||
113 | - bdrv_graph_wrunlock(NULL); | ||
114 | + bdrv_graph_wrunlock(); | ||
115 | |||
116 | QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { | ||
117 | if (bs_entry->prepared) { | ||
118 | @@ -4852,12 +4852,12 @@ bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state, | ||
119 | } | ||
120 | |||
121 | bdrv_graph_rdunlock_main_loop(); | ||
122 | - bdrv_graph_wrlock(new_child_bs); | ||
123 | + bdrv_graph_wrlock(); | ||
124 | |||
125 | ret = bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing, | ||
126 | tran, errp); | ||
127 | |||
128 | - bdrv_graph_wrunlock_ctx(ctx); | ||
129 | + bdrv_graph_wrunlock(); | ||
130 | |||
131 | if (old_ctx != ctx) { | ||
132 | aio_context_release(ctx); | ||
133 | @@ -5209,14 +5209,14 @@ static void bdrv_close(BlockDriverState *bs) | ||
134 | bs->drv = NULL; | ||
135 | } | ||
136 | |||
137 | - bdrv_graph_wrlock(bs); | ||
138 | + bdrv_graph_wrlock(); | ||
139 | QLIST_FOREACH_SAFE(child, &bs->children, next, next) { | ||
140 | bdrv_unref_child(bs, child); | ||
141 | } | ||
142 | |||
143 | assert(!bs->backing); | ||
144 | assert(!bs->file); | ||
145 | - bdrv_graph_wrunlock(bs); | ||
146 | + bdrv_graph_wrunlock(); | ||
147 | |||
148 | g_free(bs->opaque); | ||
149 | bs->opaque = NULL; | ||
150 | @@ -5509,9 +5509,9 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp) | ||
151 | bdrv_graph_rdunlock_main_loop(); | ||
152 | |||
153 | bdrv_drained_begin(child_bs); | ||
154 | - bdrv_graph_wrlock(bs); | ||
155 | + bdrv_graph_wrlock(); | ||
156 | ret = bdrv_replace_node_common(bs, child_bs, true, true, errp); | ||
157 | - bdrv_graph_wrunlock(bs); | ||
158 | + bdrv_graph_wrunlock(); | ||
159 | bdrv_drained_end(child_bs); | ||
160 | |||
161 | return ret; | ||
162 | @@ -5561,7 +5561,7 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, | ||
163 | aio_context_acquire(old_context); | ||
164 | new_context = NULL; | ||
165 | |||
166 | - bdrv_graph_wrlock(bs_top); | ||
167 | + bdrv_graph_wrlock(); | ||
168 | |||
169 | child = bdrv_attach_child_noperm(bs_new, bs_top, "backing", | ||
170 | &child_of_bds, bdrv_backing_role(bs_new), | ||
171 | @@ -5593,7 +5593,7 @@ out: | ||
172 | tran_finalize(tran, ret); | ||
173 | |||
174 | bdrv_refresh_limits(bs_top, NULL, NULL); | ||
175 | - bdrv_graph_wrunlock(bs_top); | ||
176 | + bdrv_graph_wrunlock(); | ||
177 | |||
178 | bdrv_drained_end(bs_top); | ||
179 | bdrv_drained_end(bs_new); | ||
180 | @@ -5620,7 +5620,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, | ||
181 | bdrv_ref(old_bs); | ||
182 | bdrv_drained_begin(old_bs); | ||
183 | bdrv_drained_begin(new_bs); | ||
184 | - bdrv_graph_wrlock(new_bs); | ||
185 | + bdrv_graph_wrlock(); | ||
186 | |||
187 | bdrv_replace_child_tran(child, new_bs, tran); | ||
188 | |||
189 | @@ -5631,7 +5631,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, | ||
190 | |||
191 | tran_finalize(tran, ret); | ||
192 | |||
193 | - bdrv_graph_wrunlock(new_bs); | ||
194 | + bdrv_graph_wrunlock(); | ||
195 | bdrv_drained_end(old_bs); | ||
196 | bdrv_drained_end(new_bs); | ||
197 | bdrv_unref(old_bs); | ||
198 | @@ -5718,9 +5718,9 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options, | ||
199 | bdrv_ref(bs); | ||
200 | bdrv_drained_begin(bs); | ||
201 | bdrv_drained_begin(new_node_bs); | ||
202 | - bdrv_graph_wrlock(new_node_bs); | ||
203 | + bdrv_graph_wrlock(); | ||
204 | ret = bdrv_replace_node(bs, new_node_bs, errp); | ||
205 | - bdrv_graph_wrunlock(new_node_bs); | ||
206 | + bdrv_graph_wrunlock(); | ||
207 | bdrv_drained_end(new_node_bs); | ||
208 | bdrv_drained_end(bs); | ||
209 | bdrv_unref(bs); | ||
210 | @@ -5975,7 +5975,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
211 | |||
212 | bdrv_ref(top); | ||
213 | bdrv_drained_begin(base); | ||
214 | - bdrv_graph_wrlock(base); | ||
215 | + bdrv_graph_wrlock(); | ||
216 | |||
217 | if (!top->drv || !base->drv) { | ||
218 | goto exit_wrlock; | ||
219 | @@ -6015,7 +6015,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
220 | * That's a FIXME. | ||
221 | */ | ||
222 | bdrv_replace_node_common(top, base, false, false, &local_err); | ||
223 | - bdrv_graph_wrunlock(base); | ||
224 | + bdrv_graph_wrunlock(); | ||
225 | |||
226 | if (local_err) { | ||
227 | error_report_err(local_err); | ||
228 | @@ -6052,7 +6052,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
229 | goto exit; | ||
230 | |||
231 | exit_wrlock: | ||
232 | - bdrv_graph_wrunlock(base); | ||
233 | + bdrv_graph_wrunlock(); | ||
234 | exit: | ||
235 | bdrv_drained_end(base); | ||
236 | bdrv_unref(top); | ||
237 | diff --git a/block/backup.c b/block/backup.c | ||
238 | index 8aae5836d..ec29d6b81 100644 | ||
239 | --- a/block/backup.c | ||
240 | +++ b/block/backup.c | ||
241 | @@ -496,10 +496,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, | ||
242 | block_copy_set_speed(bcs, speed); | ||
243 | |||
244 | /* Required permissions are taken by copy-before-write filter target */ | ||
245 | - bdrv_graph_wrlock(target); | ||
246 | + bdrv_graph_wrlock(); | ||
247 | block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL, | ||
248 | &error_abort); | ||
249 | - bdrv_graph_wrunlock(target); | ||
250 | + bdrv_graph_wrunlock(); | ||
251 | |||
252 | return &job->common; | ||
253 | |||
254 | diff --git a/block/blklogwrites.c b/block/blklogwrites.c | ||
255 | index 84e03f309..ba717dab4 100644 | ||
256 | --- a/block/blklogwrites.c | ||
257 | +++ b/block/blklogwrites.c | ||
258 | @@ -251,9 +251,9 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, | ||
259 | ret = 0; | ||
260 | fail_log: | ||
261 | if (ret < 0) { | ||
262 | - bdrv_graph_wrlock(NULL); | ||
263 | + bdrv_graph_wrlock(); | ||
264 | bdrv_unref_child(bs, s->log_file); | ||
265 | - bdrv_graph_wrunlock(NULL); | ||
266 | + bdrv_graph_wrunlock(); | ||
267 | s->log_file = NULL; | ||
268 | } | ||
269 | fail: | ||
270 | @@ -265,10 +265,10 @@ static void blk_log_writes_close(BlockDriverState *bs) | ||
271 | { | ||
272 | BDRVBlkLogWritesState *s = bs->opaque; | ||
273 | |||
274 | - bdrv_graph_wrlock(NULL); | ||
275 | + bdrv_graph_wrlock(); | ||
276 | bdrv_unref_child(bs, s->log_file); | ||
277 | s->log_file = NULL; | ||
278 | - bdrv_graph_wrunlock(NULL); | ||
279 | + bdrv_graph_wrunlock(); | ||
280 | } | ||
281 | |||
282 | static int64_t coroutine_fn GRAPH_RDLOCK | ||
283 | diff --git a/block/blkverify.c b/block/blkverify.c | ||
284 | index 9b17c4664..ec45d8335 100644 | ||
285 | --- a/block/blkverify.c | ||
286 | +++ b/block/blkverify.c | ||
287 | @@ -151,10 +151,10 @@ static void blkverify_close(BlockDriverState *bs) | ||
288 | { | ||
289 | BDRVBlkverifyState *s = bs->opaque; | ||
290 | |||
291 | - bdrv_graph_wrlock(NULL); | ||
292 | + bdrv_graph_wrlock(); | ||
293 | bdrv_unref_child(bs, s->test_file); | ||
294 | s->test_file = NULL; | ||
295 | - bdrv_graph_wrunlock(NULL); | ||
296 | + bdrv_graph_wrunlock(); | ||
297 | } | ||
298 | |||
299 | static int64_t coroutine_fn GRAPH_RDLOCK | ||
300 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
301 | index 86315d62c..a2348b31e 100644 | ||
302 | --- a/block/block-backend.c | ||
303 | +++ b/block/block-backend.c | ||
304 | @@ -885,7 +885,6 @@ void blk_remove_bs(BlockBackend *blk) | ||
305 | { | ||
306 | ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | ||
307 | BdrvChild *root; | ||
308 | - AioContext *ctx; | ||
309 | |||
310 | GLOBAL_STATE_CODE(); | ||
311 | |||
312 | @@ -915,10 +914,9 @@ void blk_remove_bs(BlockBackend *blk) | ||
313 | root = blk->root; | ||
314 | blk->root = NULL; | ||
315 | |||
316 | - ctx = bdrv_get_aio_context(root->bs); | ||
317 | - bdrv_graph_wrlock(root->bs); | ||
318 | + bdrv_graph_wrlock(); | ||
319 | bdrv_root_unref_child(root); | ||
320 | - bdrv_graph_wrunlock_ctx(ctx); | ||
321 | + bdrv_graph_wrunlock(); | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | @@ -929,16 +927,15 @@ void blk_remove_bs(BlockBackend *blk) | ||
326 | int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) | ||
327 | { | ||
328 | ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | ||
329 | - AioContext *ctx = bdrv_get_aio_context(bs); | ||
330 | |||
331 | GLOBAL_STATE_CODE(); | ||
332 | bdrv_ref(bs); | ||
333 | - bdrv_graph_wrlock(bs); | ||
334 | + bdrv_graph_wrlock(); | ||
335 | blk->root = bdrv_root_attach_child(bs, "root", &child_root, | ||
336 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
337 | blk->perm, blk->shared_perm, | ||
338 | blk, errp); | ||
339 | - bdrv_graph_wrunlock_ctx(ctx); | ||
340 | + bdrv_graph_wrunlock(); | ||
341 | if (blk->root == NULL) { | ||
342 | return -EPERM; | ||
343 | } | ||
344 | diff --git a/block/commit.c b/block/commit.c | ||
345 | index 69cc75be0..1dd7a65ff 100644 | ||
346 | --- a/block/commit.c | ||
347 | +++ b/block/commit.c | ||
348 | @@ -100,9 +100,9 @@ static void commit_abort(Job *job) | ||
349 | bdrv_graph_rdunlock_main_loop(); | ||
350 | |||
351 | bdrv_drained_begin(commit_top_backing_bs); | ||
352 | - bdrv_graph_wrlock(commit_top_backing_bs); | ||
353 | + bdrv_graph_wrlock(); | ||
354 | bdrv_replace_node(s->commit_top_bs, commit_top_backing_bs, &error_abort); | ||
355 | - bdrv_graph_wrunlock(commit_top_backing_bs); | ||
356 | + bdrv_graph_wrunlock(); | ||
357 | bdrv_drained_end(commit_top_backing_bs); | ||
358 | |||
359 | bdrv_unref(s->commit_top_bs); | ||
360 | @@ -339,7 +339,7 @@ void commit_start(const char *job_id, BlockDriverState *bs, | ||
361 | * this is the responsibility of the interface (i.e. whoever calls | ||
362 | * commit_start()). | ||
363 | */ | ||
364 | - bdrv_graph_wrlock(top); | ||
365 | + bdrv_graph_wrlock(); | ||
366 | s->base_overlay = bdrv_find_overlay(top, base); | ||
367 | assert(s->base_overlay); | ||
368 | |||
369 | @@ -370,19 +370,19 @@ void commit_start(const char *job_id, BlockDriverState *bs, | ||
370 | ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, | ||
371 | iter_shared_perms, errp); | ||
372 | if (ret < 0) { | ||
373 | - bdrv_graph_wrunlock(top); | ||
374 | + bdrv_graph_wrunlock(); | ||
375 | goto fail; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) { | ||
380 | - bdrv_graph_wrunlock(top); | ||
381 | + bdrv_graph_wrunlock(); | ||
382 | goto fail; | ||
383 | } | ||
384 | s->chain_frozen = true; | ||
385 | |||
386 | ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp); | ||
387 | - bdrv_graph_wrunlock(top); | ||
388 | + bdrv_graph_wrunlock(); | ||
389 | |||
390 | if (ret < 0) { | ||
391 | goto fail; | ||
392 | @@ -434,9 +434,9 @@ fail: | ||
393 | * otherwise this would fail because of lack of permissions. */ | ||
394 | if (commit_top_bs) { | ||
395 | bdrv_drained_begin(top); | ||
396 | - bdrv_graph_wrlock(top); | ||
397 | + bdrv_graph_wrlock(); | ||
398 | bdrv_replace_node(commit_top_bs, top, &error_abort); | ||
399 | - bdrv_graph_wrunlock(top); | ||
400 | + bdrv_graph_wrunlock(); | ||
401 | bdrv_drained_end(top); | ||
402 | } | ||
403 | } | ||
404 | diff --git a/block/graph-lock.c b/block/graph-lock.c | ||
405 | index 079e878d9..c81162b14 100644 | ||
406 | --- a/block/graph-lock.c | ||
407 | +++ b/block/graph-lock.c | ||
408 | @@ -106,27 +106,12 @@ static uint32_t reader_count(void) | ||
409 | return rd; | ||
410 | } | ||
411 | |||
412 | -void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs) | ||
413 | +void no_coroutine_fn bdrv_graph_wrlock(void) | ||
414 | { | ||
415 | - AioContext *ctx = NULL; | ||
416 | - | ||
417 | GLOBAL_STATE_CODE(); | ||
418 | assert(!qatomic_read(&has_writer)); | ||
419 | assert(!qemu_in_coroutine()); | ||
420 | |||
421 | - /* | ||
422 | - * Release only non-mainloop AioContext. The mainloop often relies on the | ||
423 | - * BQL and doesn't lock the main AioContext before doing things. | ||
424 | - */ | ||
425 | - if (bs) { | ||
426 | - ctx = bdrv_get_aio_context(bs); | ||
427 | - if (ctx != qemu_get_aio_context()) { | ||
428 | - aio_context_release(ctx); | ||
429 | - } else { | ||
430 | - ctx = NULL; | ||
431 | - } | ||
432 | - } | ||
433 | - | ||
434 | /* Make sure that constantly arriving new I/O doesn't cause starvation */ | ||
435 | bdrv_drain_all_begin_nopoll(); | ||
436 | |||
437 | @@ -155,27 +140,13 @@ void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs) | ||
438 | } while (reader_count() >= 1); | ||
439 | |||
440 | bdrv_drain_all_end(); | ||
441 | - | ||
442 | - if (ctx) { | ||
443 | - aio_context_acquire(bdrv_get_aio_context(bs)); | ||
444 | - } | ||
445 | } | ||
446 | |||
447 | -void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx) | ||
448 | +void no_coroutine_fn bdrv_graph_wrunlock(void) | ||
449 | { | ||
450 | GLOBAL_STATE_CODE(); | ||
451 | assert(qatomic_read(&has_writer)); | ||
452 | |||
453 | - /* | ||
454 | - * Release only non-mainloop AioContext. The mainloop often relies on the | ||
455 | - * BQL and doesn't lock the main AioContext before doing things. | ||
456 | - */ | ||
457 | - if (ctx && ctx != qemu_get_aio_context()) { | ||
458 | - aio_context_release(ctx); | ||
459 | - } else { | ||
460 | - ctx = NULL; | ||
461 | - } | ||
462 | - | ||
463 | WITH_QEMU_LOCK_GUARD(&aio_context_list_lock) { | ||
464 | /* | ||
465 | * No need for memory barriers, this works in pair with | ||
466 | @@ -197,17 +168,6 @@ void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx) | ||
467 | * progress. | ||
468 | */ | ||
469 | aio_bh_poll(qemu_get_aio_context()); | ||
470 | - | ||
471 | - if (ctx) { | ||
472 | - aio_context_acquire(ctx); | ||
473 | - } | ||
474 | -} | ||
475 | - | ||
476 | -void no_coroutine_fn bdrv_graph_wrunlock(BlockDriverState *bs) | ||
477 | -{ | ||
478 | - AioContext *ctx = bs ? bdrv_get_aio_context(bs) : NULL; | ||
479 | - | ||
480 | - bdrv_graph_wrunlock_ctx(ctx); | ||
481 | } | ||
482 | |||
483 | void coroutine_fn bdrv_graph_co_rdlock(void) | ||
484 | diff --git a/block/mirror.c b/block/mirror.c | ||
485 | index abbddb39e..f9db6f0f7 100644 | ||
486 | --- a/block/mirror.c | ||
487 | +++ b/block/mirror.c | ||
488 | @@ -768,7 +768,7 @@ static int mirror_exit_common(Job *job) | ||
489 | * check for an op blocker on @to_replace, and we have our own | ||
490 | * there. | ||
491 | */ | ||
492 | - bdrv_graph_wrlock(target_bs); | ||
493 | + bdrv_graph_wrlock(); | ||
494 | if (bdrv_recurse_can_replace(src, to_replace)) { | ||
495 | bdrv_replace_node(to_replace, target_bs, &local_err); | ||
496 | } else { | ||
497 | @@ -777,7 +777,7 @@ static int mirror_exit_common(Job *job) | ||
498 | "would not lead to an abrupt change of visible data", | ||
499 | to_replace->node_name, target_bs->node_name); | ||
500 | } | ||
501 | - bdrv_graph_wrunlock(target_bs); | ||
502 | + bdrv_graph_wrunlock(); | ||
503 | bdrv_drained_end(to_replace); | ||
504 | if (local_err) { | ||
505 | error_report_err(local_err); | ||
506 | @@ -800,9 +800,9 @@ static int mirror_exit_common(Job *job) | ||
507 | * valid. | ||
508 | */ | ||
509 | block_job_remove_all_bdrv(bjob); | ||
510 | - bdrv_graph_wrlock(mirror_top_bs); | ||
511 | + bdrv_graph_wrlock(); | ||
512 | bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); | ||
513 | - bdrv_graph_wrunlock(mirror_top_bs); | ||
514 | + bdrv_graph_wrunlock(); | ||
515 | |||
516 | bdrv_drained_end(target_bs); | ||
517 | bdrv_unref(target_bs); | ||
518 | @@ -1916,13 +1916,13 @@ static BlockJob *mirror_start_job( | ||
519 | */ | ||
520 | bdrv_disable_dirty_bitmap(s->dirty_bitmap); | ||
521 | |||
522 | - bdrv_graph_wrlock(bs); | ||
523 | + bdrv_graph_wrlock(); | ||
524 | ret = block_job_add_bdrv(&s->common, "source", bs, 0, | ||
525 | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE | | ||
526 | BLK_PERM_CONSISTENT_READ, | ||
527 | errp); | ||
528 | if (ret < 0) { | ||
529 | - bdrv_graph_wrunlock(bs); | ||
530 | + bdrv_graph_wrunlock(); | ||
531 | goto fail; | ||
532 | } | ||
533 | |||
534 | @@ -1967,17 +1967,17 @@ static BlockJob *mirror_start_job( | ||
535 | ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, | ||
536 | iter_shared_perms, errp); | ||
537 | if (ret < 0) { | ||
538 | - bdrv_graph_wrunlock(bs); | ||
539 | + bdrv_graph_wrunlock(); | ||
540 | goto fail; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) { | ||
545 | - bdrv_graph_wrunlock(bs); | ||
546 | + bdrv_graph_wrunlock(); | ||
547 | goto fail; | ||
548 | } | ||
549 | } | ||
550 | - bdrv_graph_wrunlock(bs); | ||
551 | + bdrv_graph_wrunlock(); | ||
552 | |||
553 | QTAILQ_INIT(&s->ops_in_flight); | ||
554 | |||
555 | @@ -2003,12 +2003,12 @@ fail: | ||
556 | |||
557 | bs_opaque->stop = true; | ||
558 | bdrv_drained_begin(bs); | ||
559 | - bdrv_graph_wrlock(bs); | ||
560 | + bdrv_graph_wrlock(); | ||
561 | assert(mirror_top_bs->backing->bs == bs); | ||
562 | bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, | ||
563 | &error_abort); | ||
564 | bdrv_replace_node(mirror_top_bs, bs, &error_abort); | ||
565 | - bdrv_graph_wrunlock(bs); | ||
566 | + bdrv_graph_wrunlock(); | ||
567 | bdrv_drained_end(bs); | ||
568 | |||
569 | bdrv_unref(mirror_top_bs); | ||
570 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
571 | index 7af7c0bee..77dd49d4f 100644 | ||
572 | --- a/block/qcow2.c | ||
573 | +++ b/block/qcow2.c | ||
574 | @@ -2822,9 +2822,9 @@ qcow2_do_close(BlockDriverState *bs, bool close_data_file) | ||
575 | if (close_data_file && has_data_file(bs)) { | ||
576 | GLOBAL_STATE_CODE(); | ||
577 | bdrv_graph_rdunlock_main_loop(); | ||
578 | - bdrv_graph_wrlock(NULL); | ||
579 | + bdrv_graph_wrlock(); | ||
580 | bdrv_unref_child(bs, s->data_file); | ||
581 | - bdrv_graph_wrunlock(NULL); | ||
582 | + bdrv_graph_wrunlock(); | ||
583 | s->data_file = NULL; | ||
584 | bdrv_graph_rdlock_main_loop(); | ||
585 | } | ||
586 | diff --git a/block/quorum.c b/block/quorum.c | ||
587 | index 505b8b3e1..db8fe891c 100644 | ||
588 | --- a/block/quorum.c | ||
589 | +++ b/block/quorum.c | ||
590 | @@ -1037,14 +1037,14 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, | ||
591 | |||
592 | close_exit: | ||
593 | /* cleanup on error */ | ||
594 | - bdrv_graph_wrlock(NULL); | ||
595 | + bdrv_graph_wrlock(); | ||
596 | for (i = 0; i < s->num_children; i++) { | ||
597 | if (!opened[i]) { | ||
598 | continue; | ||
599 | } | ||
600 | bdrv_unref_child(bs, s->children[i]); | ||
601 | } | ||
602 | - bdrv_graph_wrunlock(NULL); | ||
603 | + bdrv_graph_wrunlock(); | ||
604 | g_free(s->children); | ||
605 | g_free(opened); | ||
606 | exit: | ||
607 | @@ -1057,11 +1057,11 @@ static void quorum_close(BlockDriverState *bs) | ||
608 | BDRVQuorumState *s = bs->opaque; | ||
609 | int i; | ||
610 | |||
611 | - bdrv_graph_wrlock(NULL); | ||
612 | + bdrv_graph_wrlock(); | ||
613 | for (i = 0; i < s->num_children; i++) { | ||
614 | bdrv_unref_child(bs, s->children[i]); | ||
615 | } | ||
616 | - bdrv_graph_wrunlock(NULL); | ||
617 | + bdrv_graph_wrunlock(); | ||
618 | |||
619 | g_free(s->children); | ||
620 | } | ||
621 | diff --git a/block/replication.c b/block/replication.c | ||
622 | index 5ded5f1ca..424b537ff 100644 | ||
623 | --- a/block/replication.c | ||
624 | +++ b/block/replication.c | ||
625 | @@ -560,7 +560,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
626 | return; | ||
627 | } | ||
628 | |||
629 | - bdrv_graph_wrlock(bs); | ||
630 | + bdrv_graph_wrlock(); | ||
631 | |||
632 | bdrv_ref(hidden_disk->bs); | ||
633 | s->hidden_disk = bdrv_attach_child(bs, hidden_disk->bs, "hidden disk", | ||
634 | @@ -568,7 +568,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
635 | &local_err); | ||
636 | if (local_err) { | ||
637 | error_propagate(errp, local_err); | ||
638 | - bdrv_graph_wrunlock(bs); | ||
639 | + bdrv_graph_wrunlock(); | ||
640 | aio_context_release(aio_context); | ||
641 | return; | ||
642 | } | ||
643 | @@ -579,7 +579,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
644 | BDRV_CHILD_DATA, &local_err); | ||
645 | if (local_err) { | ||
646 | error_propagate(errp, local_err); | ||
647 | - bdrv_graph_wrunlock(bs); | ||
648 | + bdrv_graph_wrunlock(); | ||
649 | aio_context_release(aio_context); | ||
650 | return; | ||
651 | } | ||
652 | @@ -592,7 +592,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
653 | if (!top_bs || !bdrv_is_root_node(top_bs) || | ||
654 | !check_top_bs(top_bs, bs)) { | ||
655 | error_setg(errp, "No top_bs or it is invalid"); | ||
656 | - bdrv_graph_wrunlock(bs); | ||
657 | + bdrv_graph_wrunlock(); | ||
658 | reopen_backing_file(bs, false, NULL); | ||
659 | aio_context_release(aio_context); | ||
660 | return; | ||
661 | @@ -600,7 +600,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
662 | bdrv_op_block_all(top_bs, s->blocker); | ||
663 | bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker); | ||
664 | |||
665 | - bdrv_graph_wrunlock(bs); | ||
666 | + bdrv_graph_wrunlock(); | ||
667 | |||
668 | s->backup_job = backup_job_create( | ||
669 | NULL, s->secondary_disk->bs, s->hidden_disk->bs, | ||
670 | @@ -691,12 +691,12 @@ static void replication_done(void *opaque, int ret) | ||
671 | if (ret == 0) { | ||
672 | s->stage = BLOCK_REPLICATION_DONE; | ||
673 | |||
674 | - bdrv_graph_wrlock(NULL); | ||
675 | + bdrv_graph_wrlock(); | ||
676 | bdrv_unref_child(bs, s->secondary_disk); | ||
677 | s->secondary_disk = NULL; | ||
678 | bdrv_unref_child(bs, s->hidden_disk); | ||
679 | s->hidden_disk = NULL; | ||
680 | - bdrv_graph_wrunlock(NULL); | ||
681 | + bdrv_graph_wrunlock(); | ||
682 | |||
683 | s->error = 0; | ||
684 | } else { | ||
685 | diff --git a/block/snapshot.c b/block/snapshot.c | ||
686 | index c4d40e80d..6fd720aef 100644 | ||
687 | --- a/block/snapshot.c | ||
688 | +++ b/block/snapshot.c | ||
689 | @@ -292,9 +292,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs, | ||
690 | } | ||
691 | |||
692 | /* .bdrv_open() will re-attach it */ | ||
693 | - bdrv_graph_wrlock(NULL); | ||
694 | + bdrv_graph_wrlock(); | ||
695 | bdrv_unref_child(bs, fallback); | ||
696 | - bdrv_graph_wrunlock(NULL); | ||
697 | + bdrv_graph_wrunlock(); | ||
698 | |||
699 | ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp); | ||
700 | open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err); | ||
701 | diff --git a/block/stream.c b/block/stream.c | ||
702 | index 01fe7c0f1..048c2d282 100644 | ||
703 | --- a/block/stream.c | ||
704 | +++ b/block/stream.c | ||
705 | @@ -99,9 +99,9 @@ static int stream_prepare(Job *job) | ||
706 | } | ||
707 | } | ||
708 | |||
709 | - bdrv_graph_wrlock(s->target_bs); | ||
710 | + bdrv_graph_wrlock(); | ||
711 | bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err); | ||
712 | - bdrv_graph_wrunlock(s->target_bs); | ||
713 | + bdrv_graph_wrunlock(); | ||
714 | |||
715 | /* | ||
716 | * This call will do I/O, so the graph can change again from here on. | ||
717 | @@ -366,10 +366,10 @@ void stream_start(const char *job_id, BlockDriverState *bs, | ||
718 | * already have our own plans. Also don't allow resize as the image size is | ||
719 | * queried only at the job start and then cached. | ||
720 | */ | ||
721 | - bdrv_graph_wrlock(bs); | ||
722 | + bdrv_graph_wrlock(); | ||
723 | if (block_job_add_bdrv(&s->common, "active node", bs, 0, | ||
724 | basic_flags | BLK_PERM_WRITE, errp)) { | ||
725 | - bdrv_graph_wrunlock(bs); | ||
726 | + bdrv_graph_wrunlock(); | ||
727 | goto fail; | ||
728 | } | ||
729 | |||
730 | @@ -389,11 +389,11 @@ void stream_start(const char *job_id, BlockDriverState *bs, | ||
731 | ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, | ||
732 | basic_flags, errp); | ||
733 | if (ret < 0) { | ||
734 | - bdrv_graph_wrunlock(bs); | ||
735 | + bdrv_graph_wrunlock(); | ||
736 | goto fail; | ||
737 | } | ||
738 | } | ||
739 | - bdrv_graph_wrunlock(bs); | ||
740 | + bdrv_graph_wrunlock(); | ||
741 | |||
742 | s->base_overlay = base_overlay; | ||
743 | s->above_base = above_base; | ||
744 | diff --git a/block/vmdk.c b/block/vmdk.c | ||
745 | index d6971c706..bf78e1238 100644 | ||
746 | --- a/block/vmdk.c | ||
747 | +++ b/block/vmdk.c | ||
748 | @@ -272,7 +272,7 @@ static void vmdk_free_extents(BlockDriverState *bs) | ||
749 | BDRVVmdkState *s = bs->opaque; | ||
750 | VmdkExtent *e; | ||
751 | |||
752 | - bdrv_graph_wrlock(NULL); | ||
753 | + bdrv_graph_wrlock(); | ||
754 | for (i = 0; i < s->num_extents; i++) { | ||
755 | e = &s->extents[i]; | ||
756 | g_free(e->l1_table); | ||
757 | @@ -283,7 +283,7 @@ static void vmdk_free_extents(BlockDriverState *bs) | ||
758 | bdrv_unref_child(bs, e->file); | ||
759 | } | ||
760 | } | ||
761 | - bdrv_graph_wrunlock(NULL); | ||
762 | + bdrv_graph_wrunlock(); | ||
763 | |||
764 | g_free(s->extents); | ||
765 | } | ||
766 | @@ -1247,9 +1247,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
767 | 0, 0, 0, 0, 0, &extent, errp); | ||
768 | if (ret < 0) { | ||
769 | bdrv_graph_rdunlock_main_loop(); | ||
770 | - bdrv_graph_wrlock(NULL); | ||
771 | + bdrv_graph_wrlock(); | ||
772 | bdrv_unref_child(bs, extent_file); | ||
773 | - bdrv_graph_wrunlock(NULL); | ||
774 | + bdrv_graph_wrunlock(); | ||
775 | bdrv_graph_rdlock_main_loop(); | ||
776 | goto out; | ||
777 | } | ||
778 | @@ -1266,9 +1266,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
779 | g_free(buf); | ||
780 | if (ret) { | ||
781 | bdrv_graph_rdunlock_main_loop(); | ||
782 | - bdrv_graph_wrlock(NULL); | ||
783 | + bdrv_graph_wrlock(); | ||
784 | bdrv_unref_child(bs, extent_file); | ||
785 | - bdrv_graph_wrunlock(NULL); | ||
786 | + bdrv_graph_wrunlock(); | ||
787 | bdrv_graph_rdlock_main_loop(); | ||
788 | goto out; | ||
789 | } | ||
790 | @@ -1277,9 +1277,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
791 | ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp); | ||
792 | if (ret) { | ||
793 | bdrv_graph_rdunlock_main_loop(); | ||
794 | - bdrv_graph_wrlock(NULL); | ||
795 | + bdrv_graph_wrlock(); | ||
796 | bdrv_unref_child(bs, extent_file); | ||
797 | - bdrv_graph_wrunlock(NULL); | ||
798 | + bdrv_graph_wrunlock(); | ||
799 | bdrv_graph_rdlock_main_loop(); | ||
800 | goto out; | ||
801 | } | ||
802 | @@ -1287,9 +1287,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
803 | } else { | ||
804 | error_setg(errp, "Unsupported extent type '%s'", type); | ||
805 | bdrv_graph_rdunlock_main_loop(); | ||
806 | - bdrv_graph_wrlock(NULL); | ||
807 | + bdrv_graph_wrlock(); | ||
808 | bdrv_unref_child(bs, extent_file); | ||
809 | - bdrv_graph_wrunlock(NULL); | ||
810 | + bdrv_graph_wrunlock(); | ||
811 | bdrv_graph_rdlock_main_loop(); | ||
812 | ret = -ENOTSUP; | ||
813 | goto out; | ||
814 | diff --git a/blockdev.c b/blockdev.c | ||
815 | index c91f49e7b..9e1381169 100644 | ||
816 | --- a/blockdev.c | ||
817 | +++ b/blockdev.c | ||
818 | @@ -1611,9 +1611,9 @@ static void external_snapshot_abort(void *opaque) | ||
819 | } | ||
820 | |||
821 | bdrv_drained_begin(state->new_bs); | ||
822 | - bdrv_graph_wrlock(state->old_bs); | ||
823 | + bdrv_graph_wrlock(); | ||
824 | bdrv_replace_node(state->new_bs, state->old_bs, &error_abort); | ||
825 | - bdrv_graph_wrunlock(state->old_bs); | ||
826 | + bdrv_graph_wrunlock(); | ||
827 | bdrv_drained_end(state->new_bs); | ||
828 | |||
829 | bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */ | ||
830 | @@ -3657,7 +3657,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child, | ||
831 | BlockDriverState *parent_bs, *new_bs = NULL; | ||
832 | BdrvChild *p_child; | ||
833 | |||
834 | - bdrv_graph_wrlock(NULL); | ||
835 | + bdrv_graph_wrlock(); | ||
836 | |||
837 | parent_bs = bdrv_lookup_bs(parent, parent, errp); | ||
838 | if (!parent_bs) { | ||
839 | @@ -3693,7 +3693,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child, | ||
840 | } | ||
841 | |||
842 | out: | ||
843 | - bdrv_graph_wrunlock(NULL); | ||
844 | + bdrv_graph_wrunlock(); | ||
845 | } | ||
846 | |||
847 | BlockJobInfoList *qmp_query_block_jobs(Error **errp) | ||
848 | diff --git a/blockjob.c b/blockjob.c | ||
849 | index b7a29052b..731041231 100644 | ||
850 | --- a/blockjob.c | ||
851 | +++ b/blockjob.c | ||
852 | @@ -199,7 +199,7 @@ void block_job_remove_all_bdrv(BlockJob *job) | ||
853 | * to process an already freed BdrvChild. | ||
854 | */ | ||
855 | aio_context_release(job->job.aio_context); | ||
856 | - bdrv_graph_wrlock(NULL); | ||
857 | + bdrv_graph_wrlock(); | ||
858 | aio_context_acquire(job->job.aio_context); | ||
859 | while (job->nodes) { | ||
860 | GSList *l = job->nodes; | ||
861 | @@ -212,7 +212,7 @@ void block_job_remove_all_bdrv(BlockJob *job) | ||
862 | |||
863 | g_slist_free_1(l); | ||
864 | } | ||
865 | - bdrv_graph_wrunlock_ctx(job->job.aio_context); | ||
866 | + bdrv_graph_wrunlock(); | ||
867 | } | ||
868 | |||
869 | bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) | ||
870 | @@ -514,7 +514,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, | ||
871 | int ret; | ||
872 | GLOBAL_STATE_CODE(); | ||
873 | |||
874 | - bdrv_graph_wrlock(bs); | ||
875 | + bdrv_graph_wrlock(); | ||
876 | |||
877 | if (job_id == NULL && !(flags & JOB_INTERNAL)) { | ||
878 | job_id = bdrv_get_device_name(bs); | ||
879 | @@ -523,7 +523,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, | ||
880 | job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs), | ||
881 | flags, cb, opaque, errp); | ||
882 | if (job == NULL) { | ||
883 | - bdrv_graph_wrunlock(bs); | ||
884 | + bdrv_graph_wrunlock(); | ||
885 | return NULL; | ||
886 | } | ||
887 | |||
888 | @@ -563,11 +563,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, | ||
889 | goto fail; | ||
890 | } | ||
891 | |||
892 | - bdrv_graph_wrunlock(bs); | ||
893 | + bdrv_graph_wrunlock(); | ||
894 | return job; | ||
895 | |||
896 | fail: | ||
897 | - bdrv_graph_wrunlock(bs); | ||
898 | + bdrv_graph_wrunlock(); | ||
899 | job_early_fail(&job->job); | ||
900 | return NULL; | ||
901 | } | ||
902 | diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h | ||
903 | index 22b5db1ed..d7545e82d 100644 | ||
904 | --- a/include/block/graph-lock.h | ||
905 | +++ b/include/block/graph-lock.h | ||
906 | @@ -110,34 +110,17 @@ void unregister_aiocontext(AioContext *ctx); | ||
907 | * | ||
908 | * The wrlock can only be taken from the main loop, with BQL held, as only the | ||
909 | * main loop is allowed to modify the graph. | ||
910 | - * | ||
911 | - * If @bs is non-NULL, its AioContext is temporarily released. | ||
912 | - * | ||
913 | - * This function polls. Callers must not hold the lock of any AioContext other | ||
914 | - * than the current one and the one of @bs. | ||
915 | */ | ||
916 | void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA | ||
917 | -bdrv_graph_wrlock(BlockDriverState *bs); | ||
918 | +bdrv_graph_wrlock(void); | ||
919 | |||
920 | /* | ||
921 | * bdrv_graph_wrunlock: | ||
922 | * Write finished, reset global has_writer to 0 and restart | ||
923 | * all readers that are waiting. | ||
924 | - * | ||
925 | - * If @bs is non-NULL, its AioContext is temporarily released. | ||
926 | - */ | ||
927 | -void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA | ||
928 | -bdrv_graph_wrunlock(BlockDriverState *bs); | ||
929 | - | ||
930 | -/* | ||
931 | - * bdrv_graph_wrunlock_ctx: | ||
932 | - * Write finished, reset global has_writer to 0 and restart | ||
933 | - * all readers that are waiting. | ||
934 | - * | ||
935 | - * If @ctx is non-NULL, its lock is temporarily released. | ||
936 | */ | ||
937 | void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA | ||
938 | -bdrv_graph_wrunlock_ctx(AioContext *ctx); | ||
939 | +bdrv_graph_wrunlock(void); | ||
940 | |||
941 | /* | ||
942 | * bdrv_graph_co_rdlock: | ||
943 | diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py | ||
944 | index a38e5833f..38364fa55 100644 | ||
945 | --- a/scripts/block-coroutine-wrapper.py | ||
946 | +++ b/scripts/block-coroutine-wrapper.py | ||
947 | @@ -261,8 +261,8 @@ def gen_no_co_wrapper(func: FuncDecl) -> str: | ||
948 | graph_lock=' bdrv_graph_rdlock_main_loop();' | ||
949 | graph_unlock=' bdrv_graph_rdunlock_main_loop();' | ||
950 | elif func.graph_wrlock: | ||
951 | - graph_lock=' bdrv_graph_wrlock(NULL);' | ||
952 | - graph_unlock=' bdrv_graph_wrunlock(NULL);' | ||
953 | + graph_lock=' bdrv_graph_wrlock();' | ||
954 | + graph_unlock=' bdrv_graph_wrunlock();' | ||
955 | |||
956 | return f"""\ | ||
957 | /* | ||
958 | diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c | ||
959 | index 704d1a3f3..d9754dfeb 100644 | ||
960 | --- a/tests/unit/test-bdrv-drain.c | ||
961 | +++ b/tests/unit/test-bdrv-drain.c | ||
962 | @@ -807,9 +807,9 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, | ||
963 | tjob->bs = src; | ||
964 | job = &tjob->common; | ||
965 | |||
966 | - bdrv_graph_wrlock(target); | ||
967 | + bdrv_graph_wrlock(); | ||
968 | block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort); | ||
969 | - bdrv_graph_wrunlock(target); | ||
970 | + bdrv_graph_wrunlock(); | ||
971 | |||
972 | switch (result) { | ||
973 | case TEST_JOB_SUCCESS: | ||
974 | @@ -991,11 +991,11 @@ static void bdrv_test_top_close(BlockDriverState *bs) | ||
975 | { | ||
976 | BdrvChild *c, *next_c; | ||
977 | |||
978 | - bdrv_graph_wrlock(NULL); | ||
979 | + bdrv_graph_wrlock(); | ||
980 | QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) { | ||
981 | bdrv_unref_child(bs, c); | ||
982 | } | ||
983 | - bdrv_graph_wrunlock(NULL); | ||
984 | + bdrv_graph_wrunlock(); | ||
985 | } | ||
986 | |||
987 | static int coroutine_fn GRAPH_RDLOCK | ||
988 | @@ -1085,10 +1085,10 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, | ||
989 | |||
990 | null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, | ||
991 | &error_abort); | ||
992 | - bdrv_graph_wrlock(NULL); | ||
993 | + bdrv_graph_wrlock(); | ||
994 | bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, | ||
995 | BDRV_CHILD_DATA, &error_abort); | ||
996 | - bdrv_graph_wrunlock(NULL); | ||
997 | + bdrv_graph_wrunlock(); | ||
998 | |||
999 | /* This child will be the one to pass to requests through to, and | ||
1000 | * it will stall until a drain occurs */ | ||
1001 | @@ -1096,21 +1096,21 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, | ||
1002 | &error_abort); | ||
1003 | child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS; | ||
1004 | /* Takes our reference to child_bs */ | ||
1005 | - bdrv_graph_wrlock(NULL); | ||
1006 | + bdrv_graph_wrlock(); | ||
1007 | tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", | ||
1008 | &child_of_bds, | ||
1009 | BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY, | ||
1010 | &error_abort); | ||
1011 | - bdrv_graph_wrunlock(NULL); | ||
1012 | + bdrv_graph_wrunlock(); | ||
1013 | |||
1014 | /* This child is just there to be deleted | ||
1015 | * (for detach_instead_of_delete == true) */ | ||
1016 | null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, | ||
1017 | &error_abort); | ||
1018 | - bdrv_graph_wrlock(NULL); | ||
1019 | + bdrv_graph_wrlock(); | ||
1020 | bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA, | ||
1021 | &error_abort); | ||
1022 | - bdrv_graph_wrunlock(NULL); | ||
1023 | + bdrv_graph_wrunlock(); | ||
1024 | |||
1025 | blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); | ||
1026 | blk_insert_bs(blk, bs, &error_abort); | ||
1027 | @@ -1193,14 +1193,14 @@ static void no_coroutine_fn detach_indirect_bh(void *opaque) | ||
1028 | |||
1029 | bdrv_dec_in_flight(data->child_b->bs); | ||
1030 | |||
1031 | - bdrv_graph_wrlock(NULL); | ||
1032 | + bdrv_graph_wrlock(); | ||
1033 | bdrv_unref_child(data->parent_b, data->child_b); | ||
1034 | |||
1035 | bdrv_ref(data->c); | ||
1036 | data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C", | ||
1037 | &child_of_bds, BDRV_CHILD_DATA, | ||
1038 | &error_abort); | ||
1039 | - bdrv_graph_wrunlock(NULL); | ||
1040 | + bdrv_graph_wrunlock(); | ||
1041 | } | ||
1042 | |||
1043 | static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret) | ||
1044 | @@ -1298,7 +1298,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb) | ||
1045 | /* Set child relationships */ | ||
1046 | bdrv_ref(b); | ||
1047 | bdrv_ref(a); | ||
1048 | - bdrv_graph_wrlock(NULL); | ||
1049 | + bdrv_graph_wrlock(); | ||
1050 | child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds, | ||
1051 | BDRV_CHILD_DATA, &error_abort); | ||
1052 | child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds, | ||
1053 | @@ -1308,7 +1308,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb) | ||
1054 | bdrv_attach_child(parent_a, a, "PA-A", | ||
1055 | by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class, | ||
1056 | BDRV_CHILD_DATA, &error_abort); | ||
1057 | - bdrv_graph_wrunlock(NULL); | ||
1058 | + bdrv_graph_wrunlock(); | ||
1059 | |||
1060 | g_assert_cmpint(parent_a->refcnt, ==, 1); | ||
1061 | g_assert_cmpint(parent_b->refcnt, ==, 1); | ||
1062 | @@ -1727,7 +1727,7 @@ static void test_drop_intermediate_poll(void) | ||
1063 | * Establish the chain last, so the chain links are the first | ||
1064 | * elements in the BDS.parents lists | ||
1065 | */ | ||
1066 | - bdrv_graph_wrlock(NULL); | ||
1067 | + bdrv_graph_wrlock(); | ||
1068 | for (i = 0; i < 3; i++) { | ||
1069 | if (i) { | ||
1070 | /* Takes the reference to chain[i - 1] */ | ||
1071 | @@ -1735,7 +1735,7 @@ static void test_drop_intermediate_poll(void) | ||
1072 | &chain_child_class, BDRV_CHILD_COW, &error_abort); | ||
1073 | } | ||
1074 | } | ||
1075 | - bdrv_graph_wrunlock(NULL); | ||
1076 | + bdrv_graph_wrunlock(); | ||
1077 | |||
1078 | job = block_job_create("job", &test_simple_job_driver, NULL, job_node, | ||
1079 | 0, BLK_PERM_ALL, 0, 0, NULL, NULL, &error_abort); | ||
1080 | @@ -1982,10 +1982,10 @@ static void do_test_replace_child_mid_drain(int old_drain_count, | ||
1081 | new_child_bs->total_sectors = 1; | ||
1082 | |||
1083 | bdrv_ref(old_child_bs); | ||
1084 | - bdrv_graph_wrlock(NULL); | ||
1085 | + bdrv_graph_wrlock(); | ||
1086 | bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds, | ||
1087 | BDRV_CHILD_COW, &error_abort); | ||
1088 | - bdrv_graph_wrunlock(NULL); | ||
1089 | + bdrv_graph_wrunlock(); | ||
1090 | parent_s->setup_completed = true; | ||
1091 | |||
1092 | for (i = 0; i < old_drain_count; i++) { | ||
1093 | @@ -2016,9 +2016,9 @@ static void do_test_replace_child_mid_drain(int old_drain_count, | ||
1094 | g_assert(parent_bs->quiesce_counter == old_drain_count); | ||
1095 | bdrv_drained_begin(old_child_bs); | ||
1096 | bdrv_drained_begin(new_child_bs); | ||
1097 | - bdrv_graph_wrlock(NULL); | ||
1098 | + bdrv_graph_wrlock(); | ||
1099 | bdrv_replace_node(old_child_bs, new_child_bs, &error_abort); | ||
1100 | - bdrv_graph_wrunlock(NULL); | ||
1101 | + bdrv_graph_wrunlock(); | ||
1102 | bdrv_drained_end(new_child_bs); | ||
1103 | bdrv_drained_end(old_child_bs); | ||
1104 | g_assert(parent_bs->quiesce_counter == new_drain_count); | ||
1105 | diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c | ||
1106 | index 074adcbb9..8ee6ef38d 100644 | ||
1107 | --- a/tests/unit/test-bdrv-graph-mod.c | ||
1108 | +++ b/tests/unit/test-bdrv-graph-mod.c | ||
1109 | @@ -137,10 +137,10 @@ static void test_update_perm_tree(void) | ||
1110 | |||
1111 | blk_insert_bs(root, bs, &error_abort); | ||
1112 | |||
1113 | - bdrv_graph_wrlock(NULL); | ||
1114 | + bdrv_graph_wrlock(); | ||
1115 | bdrv_attach_child(filter, bs, "child", &child_of_bds, | ||
1116 | BDRV_CHILD_DATA, &error_abort); | ||
1117 | - bdrv_graph_wrunlock(NULL); | ||
1118 | + bdrv_graph_wrunlock(); | ||
1119 | |||
1120 | aio_context_acquire(qemu_get_aio_context()); | ||
1121 | ret = bdrv_append(filter, bs, NULL); | ||
1122 | @@ -206,11 +206,11 @@ static void test_should_update_child(void) | ||
1123 | |||
1124 | bdrv_set_backing_hd(target, bs, &error_abort); | ||
1125 | |||
1126 | - bdrv_graph_wrlock(NULL); | ||
1127 | + bdrv_graph_wrlock(); | ||
1128 | g_assert(target->backing->bs == bs); | ||
1129 | bdrv_attach_child(filter, target, "target", &child_of_bds, | ||
1130 | BDRV_CHILD_DATA, &error_abort); | ||
1131 | - bdrv_graph_wrunlock(NULL); | ||
1132 | + bdrv_graph_wrunlock(); | ||
1133 | aio_context_acquire(qemu_get_aio_context()); | ||
1134 | bdrv_append(filter, bs, &error_abort); | ||
1135 | aio_context_release(qemu_get_aio_context()); | ||
1136 | @@ -248,7 +248,7 @@ static void test_parallel_exclusive_write(void) | ||
1137 | bdrv_ref(base); | ||
1138 | bdrv_ref(fl1); | ||
1139 | |||
1140 | - bdrv_graph_wrlock(NULL); | ||
1141 | + bdrv_graph_wrlock(); | ||
1142 | bdrv_attach_child(top, fl1, "backing", &child_of_bds, | ||
1143 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
1144 | &error_abort); | ||
1145 | @@ -260,7 +260,7 @@ static void test_parallel_exclusive_write(void) | ||
1146 | &error_abort); | ||
1147 | |||
1148 | bdrv_replace_node(fl1, fl2, &error_abort); | ||
1149 | - bdrv_graph_wrunlock(NULL); | ||
1150 | + bdrv_graph_wrunlock(); | ||
1151 | |||
1152 | bdrv_drained_end(fl2); | ||
1153 | bdrv_drained_end(fl1); | ||
1154 | @@ -367,7 +367,7 @@ static void test_parallel_perm_update(void) | ||
1155 | */ | ||
1156 | bdrv_ref(base); | ||
1157 | |||
1158 | - bdrv_graph_wrlock(NULL); | ||
1159 | + bdrv_graph_wrlock(); | ||
1160 | bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA, | ||
1161 | &error_abort); | ||
1162 | c_fl1 = bdrv_attach_child(ws, fl1, "first", &child_of_bds, | ||
1163 | @@ -380,7 +380,7 @@ static void test_parallel_perm_update(void) | ||
1164 | bdrv_attach_child(fl2, base, "backing", &child_of_bds, | ||
1165 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
1166 | &error_abort); | ||
1167 | - bdrv_graph_wrunlock(NULL); | ||
1168 | + bdrv_graph_wrunlock(); | ||
1169 | |||
1170 | /* Select fl1 as first child to be active */ | ||
1171 | s->selected = c_fl1; | ||
1172 | @@ -434,11 +434,11 @@ static void test_append_greedy_filter(void) | ||
1173 | BlockDriverState *base = no_perm_node("base"); | ||
1174 | BlockDriverState *fl = exclusive_writer_node("fl1"); | ||
1175 | |||
1176 | - bdrv_graph_wrlock(NULL); | ||
1177 | + bdrv_graph_wrlock(); | ||
1178 | bdrv_attach_child(top, base, "backing", &child_of_bds, | ||
1179 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
1180 | &error_abort); | ||
1181 | - bdrv_graph_wrunlock(NULL); | ||
1182 | + bdrv_graph_wrunlock(); | ||
1183 | |||
1184 | aio_context_acquire(qemu_get_aio_context()); | ||
1185 | bdrv_append(fl, base, &error_abort); | ||
1186 | -- | ||
1187 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch new file mode 100644 index 0000000000..bcdd0fbed8 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch | |||
@@ -0,0 +1,239 @@ | |||
1 | From 7ead946998610657d38d1a505d5f25300d4ca613 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kevin Wolf <kwolf@redhat.com> | ||
3 | Date: Thu, 25 Apr 2024 14:56:02 +0000 | ||
4 | Subject: [PATCH] block: Parse filenames only when explicitly requested | ||
5 | |||
6 | When handling image filenames from legacy options such as -drive or from | ||
7 | tools, these filenames are parsed for protocol prefixes, including for | ||
8 | the json:{} pseudo-protocol. | ||
9 | |||
10 | This behaviour is intended for filenames that come directly from the | ||
11 | command line and for backing files, which may come from the image file | ||
12 | itself. Higher level management tools generally take care to verify that | ||
13 | untrusted images don't contain a bad (or any) backing file reference; | ||
14 | 'qemu-img info' is a suitable tool for this. | ||
15 | |||
16 | However, for other files that can be referenced in images, such as | ||
17 | qcow2 data files or VMDK extents, the string from the image file is | ||
18 | usually not verified by management tools - and 'qemu-img info' wouldn't | ||
19 | be suitable because in contrast to backing files, it already opens these | ||
20 | other referenced files. So here the string should be interpreted as a | ||
21 | literal local filename. More complex configurations need to be specified | ||
22 | explicitly on the command line or in QMP... | ||
23 | |||
24 | CVE: CVE-2024-4467 | ||
25 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/7ead946998610657d38d1a505d5f25300d4ca613] | ||
26 | |||
27 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
28 | --- | ||
29 | block.c | 94 ++++++++++++++++++++++++++++++++++----------------------- | ||
30 | 1 file changed, 57 insertions(+), 37 deletions(-) | ||
31 | |||
32 | diff --git a/block.c b/block.c | ||
33 | index 25e1ebc60..f3cb32cd7 100644 | ||
34 | --- a/block.c | ||
35 | +++ b/block.c | ||
36 | @@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
37 | BlockDriverState *parent, | ||
38 | const BdrvChildClass *child_class, | ||
39 | BdrvChildRole child_role, | ||
40 | + bool parse_filename, | ||
41 | Error **errp); | ||
42 | |||
43 | static bool bdrv_recurse_has_child(BlockDriverState *bs, | ||
44 | @@ -2047,7 +2048,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename, | ||
45 | * block driver has been specified explicitly. | ||
46 | */ | ||
47 | static int bdrv_fill_options(QDict **options, const char *filename, | ||
48 | - int *flags, Error **errp) | ||
49 | + int *flags, bool allow_parse_filename, | ||
50 | + Error **errp) | ||
51 | { | ||
52 | const char *drvname; | ||
53 | bool protocol = *flags & BDRV_O_PROTOCOL; | ||
54 | @@ -2089,7 +2091,7 @@ static int bdrv_fill_options(QDict **options, const char *filename, | ||
55 | if (protocol && filename) { | ||
56 | if (!qdict_haskey(*options, "filename")) { | ||
57 | qdict_put_str(*options, "filename", filename); | ||
58 | - parse_filename = true; | ||
59 | + parse_filename = allow_parse_filename; | ||
60 | } else { | ||
61 | error_setg(errp, "Can't specify 'file' and 'filename' options at " | ||
62 | "the same time"); | ||
63 | @@ -3675,7 +3677,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, | ||
64 | } | ||
65 | |||
66 | backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, | ||
67 | - &child_of_bds, bdrv_backing_role(bs), errp); | ||
68 | + &child_of_bds, bdrv_backing_role(bs), true, | ||
69 | + errp); | ||
70 | if (!backing_hd) { | ||
71 | bs->open_flags |= BDRV_O_NO_BACKING; | ||
72 | error_prepend(errp, "Could not open backing file: "); | ||
73 | @@ -3712,7 +3715,8 @@ free_exit: | ||
74 | static BlockDriverState * | ||
75 | bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||
76 | BlockDriverState *parent, const BdrvChildClass *child_class, | ||
77 | - BdrvChildRole child_role, bool allow_none, Error **errp) | ||
78 | + BdrvChildRole child_role, bool allow_none, | ||
79 | + bool parse_filename, Error **errp) | ||
80 | { | ||
81 | BlockDriverState *bs = NULL; | ||
82 | QDict *image_options; | ||
83 | @@ -3743,7 +3747,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||
84 | } | ||
85 | |||
86 | bs = bdrv_open_inherit(filename, reference, image_options, 0, | ||
87 | - parent, child_class, child_role, errp); | ||
88 | + parent, child_class, child_role, parse_filename, | ||
89 | + errp); | ||
90 | if (!bs) { | ||
91 | goto done; | ||
92 | } | ||
93 | @@ -3753,6 +3758,33 @@ done: | ||
94 | return bs; | ||
95 | } | ||
96 | |||
97 | +static BdrvChild *bdrv_open_child_common(const char *filename, | ||
98 | + QDict *options, const char *bdref_key, | ||
99 | + BlockDriverState *parent, | ||
100 | + const BdrvChildClass *child_class, | ||
101 | + BdrvChildRole child_role, | ||
102 | + bool allow_none, bool parse_filename, | ||
103 | + Error **errp) | ||
104 | +{ | ||
105 | + BlockDriverState *bs; | ||
106 | + BdrvChild *child; | ||
107 | + | ||
108 | + GLOBAL_STATE_CODE(); | ||
109 | + | ||
110 | + bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, | ||
111 | + child_role, allow_none, parse_filename, errp); | ||
112 | + if (bs == NULL) { | ||
113 | + return NULL; | ||
114 | + } | ||
115 | + | ||
116 | + bdrv_graph_wrlock(); | ||
117 | + child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
118 | + errp); | ||
119 | + bdrv_graph_wrunlock(); | ||
120 | + | ||
121 | + return child; | ||
122 | +} | ||
123 | + | ||
124 | /* | ||
125 | * Opens a disk image whose options are given as BlockdevRef in another block | ||
126 | * device's options. | ||
127 | @@ -3778,31 +3810,15 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
128 | BdrvChildRole child_role, | ||
129 | bool allow_none, Error **errp) | ||
130 | { | ||
131 | - BlockDriverState *bs; | ||
132 | - BdrvChild *child; | ||
133 | - AioContext *ctx; | ||
134 | - | ||
135 | - GLOBAL_STATE_CODE(); | ||
136 | - | ||
137 | - bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, | ||
138 | - child_role, allow_none, errp); | ||
139 | - if (bs == NULL) { | ||
140 | - return NULL; | ||
141 | - } | ||
142 | - | ||
143 | - bdrv_graph_wrlock(); | ||
144 | - ctx = bdrv_get_aio_context(bs); | ||
145 | - aio_context_acquire(ctx); | ||
146 | - child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
147 | - errp); | ||
148 | - aio_context_release(ctx); | ||
149 | - bdrv_graph_wrunlock(); | ||
150 | - | ||
151 | - return child; | ||
152 | + return bdrv_open_child_common(filename, options, bdref_key, parent, | ||
153 | + child_class, child_role, allow_none, false, | ||
154 | + errp); | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | - * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. | ||
159 | + * This does mostly the same as bdrv_open_child(), but for opening the primary | ||
160 | + * child of a node. A notable difference from bdrv_open_child() is that it | ||
161 | + * enables filename parsing for protocol names (including json:). | ||
162 | * | ||
163 | * The caller must hold the lock of the main AioContext and no other AioContext. | ||
164 | * @parent can move to a different AioContext in this function. Callers must | ||
165 | @@ -3819,8 +3835,8 @@ int bdrv_open_file_child(const char *filename, | ||
166 | role = parent->drv->is_filter ? | ||
167 | (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; | ||
168 | |||
169 | - if (!bdrv_open_child(filename, options, bdref_key, parent, | ||
170 | - &child_of_bds, role, false, errp)) | ||
171 | + if (!bdrv_open_child_common(filename, options, bdref_key, parent, | ||
172 | + &child_of_bds, role, false, true, errp)) | ||
173 | { | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | @@ -3865,7 +3881,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) | ||
177 | |||
178 | } | ||
179 | |||
180 | - bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp); | ||
181 | + bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false, | ||
182 | + errp); | ||
183 | obj = NULL; | ||
184 | qobject_unref(obj); | ||
185 | visit_free(v); | ||
186 | @@ -3962,7 +3979,7 @@ static BlockDriverState * no_coroutine_fn | ||
187 | bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
188 | int flags, BlockDriverState *parent, | ||
189 | const BdrvChildClass *child_class, BdrvChildRole child_role, | ||
190 | - Error **errp) | ||
191 | + bool parse_filename, Error **errp) | ||
192 | { | ||
193 | int ret; | ||
194 | BlockBackend *file = NULL; | ||
195 | @@ -4011,9 +4028,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
196 | } | ||
197 | |||
198 | /* json: syntax counts as explicit options, as if in the QDict */ | ||
199 | - parse_json_protocol(options, &filename, &local_err); | ||
200 | - if (local_err) { | ||
201 | - goto fail; | ||
202 | + if (parse_filename) { | ||
203 | + parse_json_protocol(options, &filename, &local_err); | ||
204 | + if (local_err) { | ||
205 | + goto fail; | ||
206 | + } | ||
207 | } | ||
208 | |||
209 | bs->explicit_options = qdict_clone_shallow(options); | ||
210 | @@ -4038,7 +4057,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
211 | parent->open_flags, parent->options); | ||
212 | } | ||
213 | |||
214 | - ret = bdrv_fill_options(&options, filename, &flags, &local_err); | ||
215 | + ret = bdrv_fill_options(&options, filename, &flags, parse_filename, | ||
216 | + &local_err); | ||
217 | if (ret < 0) { | ||
218 | goto fail; | ||
219 | } | ||
220 | @@ -4107,7 +4127,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
221 | |||
222 | file_bs = bdrv_open_child_bs(filename, options, "file", bs, | ||
223 | &child_of_bds, BDRV_CHILD_IMAGE, | ||
224 | - true, &local_err); | ||
225 | + true, true, &local_err); | ||
226 | if (local_err) { | ||
227 | goto fail; | ||
228 | } | ||
229 | @@ -4270,7 +4290,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, | ||
230 | GLOBAL_STATE_CODE(); | ||
231 | |||
232 | return bdrv_open_inherit(filename, reference, options, flags, NULL, | ||
233 | - NULL, 0, errp); | ||
234 | + NULL, 0, true, errp); | ||
235 | } | ||
236 | |||
237 | /* Return true if the NULL-terminated @list contains @str */ | ||
238 | -- | ||
239 | 2.40.0 | ||