1
The following changes since commit 79b677d658d3d35e1e776826ac4abb28cdce69b8:
1
The following changes since commit 239b8b0699a222fd21da1c5fdeba0a2456085a47:
2
2
3
Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into staging (2023-02-21 11:28:31 +0000)
3
Merge tag 'trivial-branch-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging (2023-01-19 15:05:29 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 0f385a2420d2c3f8ae7ed65fbe2712027664059e:
9
for you to fetch changes up to 4711b0a8490827c332b3f9281f689ce9555b7fab:
10
10
11
block/rbd: Add support for layered encryption (2023-02-23 19:49:35 +0100)
11
qemu-img: Change info key names for protocol nodes (2023-01-20 13:11:01 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- Lock the graph, part 2 (BlockDriver callbacks)
16
- qemu-img info: Show protocol-level information
17
- virtio-scsi: fix SCSIDevice hot unplug with IOThread
17
- Move more functions to coroutines
18
- rbd: Add support for layered encryption
18
- Make coroutine annotations ready for static analysis
19
- qemu-img: Fix exit code for errors closing the image
20
- qcow2 bitmaps: Fix theoretical corruption in error path
21
- pflash: Only load non-zero parts of backend image to save memory
22
- Code cleanup and test case improvements
19
23
20
----------------------------------------------------------------
24
----------------------------------------------------------------
21
Emanuele Giuseppe Esposito (5):
25
Alberto Faria (2):
22
block/qed: add missing graph rdlock in qed_need_check_timer_entry
26
coroutine: annotate coroutine_fn for libclang
23
block: Mark bdrv_co_flush() and callers GRAPH_RDLOCK
27
block: Add no_coroutine_fn and coroutine_mixed_fn marker
24
block: Mark bdrv_co_pdiscard() and callers GRAPH_RDLOCK
25
block: Mark bdrv_co_copy_range() GRAPH_RDLOCK
26
block: Mark bdrv_co_is_inserted() and callers GRAPH_RDLOCK
27
28
28
Kevin Wolf (18):
29
Emanuele Giuseppe Esposito (14):
29
block: Make bdrv_can_set_read_only() static
30
block-coroutine-wrapper: support void functions
30
mirror: Fix access of uninitialised fields during start
31
block: Convert bdrv_io_plug() to co_wrapper
31
block: Mark bdrv_co_truncate() and callers GRAPH_RDLOCK
32
block: Convert bdrv_io_unplug() to co_wrapper
32
block: Mark bdrv_co_block_status() and callers GRAPH_RDLOCK
33
block: Convert bdrv_is_inserted() to co_wrapper
33
block: Mark bdrv_co_ioctl() and callers GRAPH_RDLOCK
34
block: Rename refresh_total_sectors to bdrv_refresh_total_sectors
34
block: Mark bdrv_co_pwrite_zeroes() and callers GRAPH_RDLOCK
35
block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed
35
block: Mark read/write in block/io.c GRAPH_RDLOCK
36
block-backend: use bdrv_getlength instead of blk_getlength
36
block: Mark public read/write functions GRAPH_RDLOCK
37
block: use bdrv_co_refresh_total_sectors when possible
37
block: Mark bdrv_co_pwrite_sync() and callers GRAPH_RDLOCK
38
block: Convert bdrv_get_allocated_file_size() to co_wrapper
38
block: Mark bdrv_co_do_pwrite_zeroes() GRAPH_RDLOCK
39
block: Convert bdrv_get_info() to co_wrapper_mixed
39
block: Mark preadv_snapshot/snapshot_block_status GRAPH_RDLOCK
40
block: Convert bdrv_eject() to co_wrapper
40
block: Mark bdrv_co_create() and callers GRAPH_RDLOCK
41
block: Convert bdrv_lock_medium() to co_wrapper
41
block: Mark bdrv_co_io_(un)plug() and callers GRAPH_RDLOCK
42
block: Convert bdrv_debug_event() to co_wrapper_mixed
42
block: Mark bdrv_co_eject/lock_medium() and callers GRAPH_RDLOCK
43
block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate()
43
block: Mark bdrv_(un)register_buf() GRAPH_RDLOCK
44
block: Mark bdrv_co_delete_file() and callers GRAPH_RDLOCK
45
block: Mark bdrv_*_dirty_bitmap() and callers GRAPH_RDLOCK
46
block: Mark bdrv_co_refresh_total_sectors() and callers GRAPH_RDLOCK
47
44
48
Or Ozeri (3):
45
Hanna Reitz (12):
49
block/rbd: Remove redundant stack variable passphrase_len
46
block: Improve empty format-specific info dump
50
block/rbd: Add luks-any encryption opening option
47
block/file: Add file-specific image info
51
block/rbd: Add support for layered encryption
48
block/vmdk: Change extent info type
49
block: Split BlockNodeInfo off of ImageInfo
50
qemu-img: Use BlockNodeInfo
51
block/qapi: Let bdrv_query_image_info() recurse
52
block/qapi: Introduce BlockGraphInfo
53
block/qapi: Add indentation to bdrv_node_info_dump()
54
iotests: Filter child node information
55
iotests/106, 214, 308: Read only one size line
56
qemu-img: Let info print block graph
57
qemu-img: Change info key names for protocol nodes
52
58
53
Stefan Hajnoczi (3):
59
Kevin Wolf (4):
54
scsi: protect req->aiocb with AioContext lock
60
qcow2: Fix theoretical corruption in store_bitmap() error path
55
dma-helpers: prevent dma_blk_cb() vs dma_aio_cancel() race
61
qemu-img commit: Report errors while closing the image
56
virtio-scsi: reset SCSI devices from main loop thread
62
qemu-img bitmap: Report errors while closing the image
63
qemu-iotests: Test qemu-img bitmap/commit exit code on error
57
64
58
qapi/block-core.json | 27 +++++-
65
Paolo Bonzini (2):
59
block/coroutines.h | 2 +-
66
qemu-io: do not reinvent the blk_pwrite_zeroes wheel
60
block/qcow2.h | 27 ++++--
67
block: remove bdrv_coroutine_enter
61
block/qed.h | 45 +++++----
68
62
include/block/block-copy.h | 6 +-
69
Philippe Mathieu-Daudé (1):
63
include/block/block-global-state.h | 14 +--
70
block/nbd: Add missing <qemu/bswap.h> include
64
include/block/block-io.h | 110 ++++++++++++----------
71
65
include/block/block_int-common.h | 173 ++++++++++++++++++----------------
72
Thomas Huth (2):
66
include/block/block_int-io.h | 53 ++++++-----
73
tests/qemu-iotests/312: Mark "quorum" as required driver
67
include/block/dirty-bitmap.h | 12 +--
74
tests/qemu-iotests/262: Check for availability of "blkverify" first
68
include/hw/virtio/virtio-scsi.h | 11 ++-
75
69
include/sysemu/block-backend-io.h | 7 +-
76
Xiang Zheng (1):
70
block.c | 12 ++-
77
pflash: Only read non-zero parts of backend image
71
block/backup.c | 3 +
78
72
block/blkdebug.c | 19 ++--
79
qapi/block-core.json | 123 +++++++-
73
block/blklogwrites.c | 35 ++++---
80
include/block/block-common.h | 11 +-
74
block/blkreplay.c | 24 +++--
81
include/block/block-io.h | 41 ++-
75
block/blkverify.c | 5 +-
82
include/block/block_int-common.h | 26 +-
76
block/block-backend.c | 39 +++++---
83
include/block/block_int-io.h | 5 +-
77
block/block-copy.c | 32 ++++---
84
include/block/nbd.h | 1 +
78
block/bochs.c | 2 +-
85
include/block/qapi.h | 14 +-
79
block/commit.c | 5 +-
86
include/qemu/coroutine.h | 43 +++
80
block/copy-before-write.c | 33 ++++---
87
include/sysemu/block-backend-io.h | 31 +-
81
block/copy-on-read.c | 44 +++++----
88
block.c | 88 +++---
82
block/create.c | 9 +-
89
block/blkdebug.c | 11 +-
83
block/crypto.c | 16 ++--
90
block/blkio.c | 15 +-
84
block/dirty-bitmap.c | 2 +
91
block/blklogwrites.c | 6 +-
85
block/file-posix.c | 27 +++---
92
block/blkreplay.c | 6 +-
86
block/file-win32.c | 7 +-
93
block/blkverify.c | 6 +-
87
block/filter-compress.c | 36 ++++---
94
block/block-backend.c | 38 +--
88
block/io.c | 108 +++++++++++++--------
95
block/commit.c | 4 +-
89
block/iscsi.c | 28 +++---
96
block/copy-on-read.c | 18 +-
90
block/mirror.c | 59 ++++++++----
97
block/crypto.c | 14 +-
91
block/parallels.c | 33 +++----
98
block/curl.c | 10 +-
92
block/preallocate.c | 38 ++++----
99
block/file-posix.c | 137 +++++----
93
block/qcow.c | 46 +++++----
100
block/file-win32.c | 18 +-
94
block/qcow2-cluster.c | 17 ++--
101
block/filter-compress.c | 20 +-
95
block/qcow2.c | 136 +++++++++++++++------------
102
block/gluster.c | 23 +-
96
block/qed-check.c | 3 +-
103
block/io.c | 76 ++---
97
block/qed-table.c | 10 +-
104
block/iscsi.c | 17 +-
98
block/qed.c | 101 ++++++++++----------
105
block/mirror.c | 6 +-
99
block/quorum.c | 62 +++++++-----
106
block/monitor/block-hmp-cmds.c | 2 +-
100
block/raw-format.c | 76 ++++++++-------
107
block/nbd.c | 8 +-
101
block/rbd.c | 188 ++++++++++++++++++++++++++++++++++---
108
block/nfs.c | 4 +-
102
block/replication.c | 18 ++--
109
block/null.c | 13 +-
103
block/snapshot-access.c | 8 +-
110
block/nvme.c | 14 +-
104
block/stream.c | 40 ++++----
111
block/preallocate.c | 16 +-
105
block/throttle.c | 36 ++++---
112
block/qapi.c | 317 ++++++++++++++++-----
106
block/vdi.c | 11 +--
113
block/qcow.c | 5 +-
107
block/vhdx.c | 18 ++--
114
block/qcow2-bitmap.c | 5 +-
108
block/vmdk.c | 132 ++++++++++++--------------
115
block/qcow2-refcount.c | 2 +-
109
block/vpc.c | 11 +--
116
block/qcow2.c | 17 +-
110
hw/scsi/scsi-disk.c | 23 +++--
117
block/qed.c | 11 +-
111
hw/scsi/scsi-generic.c | 11 ++-
118
block/quorum.c | 8 +-
112
hw/scsi/virtio-scsi.c | 169 ++++++++++++++++++++++++++-------
119
block/raw-format.c | 25 +-
113
qemu-img.c | 8 +-
120
block/rbd.c | 9 +-
114
softmmu/dma-helpers.c | 12 ++-
121
block/replication.c | 6 +-
115
tests/unit/test-bdrv-drain.c | 20 ++--
122
block/ssh.c | 4 +-
116
tests/unit/test-block-iothread.c | 3 +-
123
block/throttle.c | 6 +-
117
59 files changed, 1355 insertions(+), 907 deletions(-)
124
block/vdi.c | 7 +-
125
block/vhdx.c | 5 +-
126
block/vmdk.c | 22 +-
127
block/vpc.c | 5 +-
128
blockdev.c | 8 +-
129
hw/block/block.c | 36 ++-
130
hw/scsi/scsi-disk.c | 5 +
131
qemu-img.c | 100 +++++--
132
qemu-io-cmds.c | 62 +---
133
tests/unit/test-block-iothread.c | 3 +
134
scripts/block-coroutine-wrapper.py | 20 +-
135
tests/qemu-iotests/iotests.py | 18 +-
136
block/meson.build | 1 +
137
tests/qemu-iotests/065 | 2 +-
138
tests/qemu-iotests/106 | 4 +-
139
tests/qemu-iotests/214 | 6 +-
140
tests/qemu-iotests/262 | 3 +-
141
tests/qemu-iotests/302.out | 5 +
142
tests/qemu-iotests/308 | 4 +-
143
tests/qemu-iotests/312 | 1 +
144
tests/qemu-iotests/common.filter | 22 +-
145
tests/qemu-iotests/common.rc | 22 +-
146
tests/qemu-iotests/tests/qemu-img-close-errors | 95 ++++++
147
tests/qemu-iotests/tests/qemu-img-close-errors.out | 23 ++
148
69 files changed, 1207 insertions(+), 552 deletions(-)
149
create mode 100755 tests/qemu-iotests/tests/qemu-img-close-errors
150
create mode 100644 tests/qemu-iotests/tests/qemu-img-close-errors.out
151
152
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
"quorum" is required by iotest 312 - if it is not compiled into the
4
QEMU binary, the test fails. Thus list "quorum" as required driver
5
so that the test gets skipped in case it is not available.
6
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Message-Id: <20230104114601.269351-1-thuth@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
tests/qemu-iotests/312 | 1 +
15
1 file changed, 1 insertion(+)
16
17
diff --git a/tests/qemu-iotests/312 b/tests/qemu-iotests/312
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/312
20
+++ b/tests/qemu-iotests/312
21
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
22
_supported_proto file
23
_supported_os Linux
24
_unsupported_imgopts cluster_size data_file
25
+_require_drivers quorum
26
27
echo
28
echo '### Create all images' # three source (quorum), one destination
29
--
30
2.38.1
31
32
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
In downstream RHEL builds, we do not have "blkverify" enabled, so
4
iotest 262 is currently failing there. Thus let's list "blkverify"
5
as required item so that the test properly gets skipped instead if
6
"blkverify" is missing.
7
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Message-Id: <20230104112850.261480-1-thuth@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
tests/qemu-iotests/262 | 3 ++-
15
1 file changed, 2 insertions(+), 1 deletion(-)
16
17
diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/262
20
+++ b/tests/qemu-iotests/262
21
@@ -XXX,XX +XXX,XX @@ import iotests
22
import os
23
24
iotests.script_initialize(supported_fmts=['qcow2'],
25
- supported_platforms=['linux'])
26
+ supported_platforms=['linux'],
27
+ required_fmts=['blkverify'])
28
29
with iotests.FilePath('img') as img_path, \
30
iotests.FilePath('mig_fifo') as fifo, \
31
--
32
2.38.1
33
34
diff view generated by jsdifflib
New patch
1
From: Xiang Zheng <zhengxiang9@huawei.com>
1
2
3
Currently we fill the VIRT_FLASH memory space with two 64MB NOR images
4
when using persistent UEFI variables on virt board. Actually we only use
5
a very small(non-zero) part of the memory while the rest significant
6
large(zero) part of memory is wasted.
7
8
So this patch checks the block status and only writes the non-zero part
9
into memory. This requires pflash devices to use sparse files for
10
backends.
11
12
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
13
14
[ kraxel: rebased to latest master ]
15
16
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
17
Message-Id: <20221220084246.1984871-1-kraxel@redhat.com>
18
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
19
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
22
hw/block/block.c | 36 +++++++++++++++++++++++++++++++++++-
23
1 file changed, 35 insertions(+), 1 deletion(-)
24
25
diff --git a/hw/block/block.c b/hw/block/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/block/block.c
28
+++ b/hw/block/block.c
29
@@ -XXX,XX +XXX,XX @@
30
#include "qapi/error.h"
31
#include "qapi/qapi-types-block.h"
32
33
+/*
34
+ * Read the non-zeroes parts of @blk into @buf
35
+ * Reading all of the @blk is expensive if the zeroes parts of @blk
36
+ * is large enough. Therefore check the block status and only write
37
+ * the non-zeroes block into @buf.
38
+ *
39
+ * Return 0 on success, non-zero on error.
40
+ */
41
+static int blk_pread_nonzeroes(BlockBackend *blk, hwaddr size, void *buf)
42
+{
43
+ int ret;
44
+ int64_t bytes, offset = 0;
45
+ BlockDriverState *bs = blk_bs(blk);
46
+
47
+ for (;;) {
48
+ bytes = MIN(size - offset, BDRV_REQUEST_MAX_SECTORS);
49
+ if (bytes <= 0) {
50
+ return 0;
51
+ }
52
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL);
53
+ if (ret < 0) {
54
+ return ret;
55
+ }
56
+ if (!(ret & BDRV_BLOCK_ZERO)) {
57
+ ret = bdrv_pread(bs->file, offset, bytes,
58
+ (uint8_t *) buf + offset, 0);
59
+ if (ret < 0) {
60
+ return ret;
61
+ }
62
+ }
63
+ offset += bytes;
64
+ }
65
+}
66
+
67
/*
68
* Read the entire contents of @blk into @buf.
69
* @blk's contents must be @size bytes, and @size must be at most
70
@@ -XXX,XX +XXX,XX @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
71
* block device and read only on demand.
72
*/
73
assert(size <= BDRV_REQUEST_MAX_BYTES);
74
- ret = blk_pread(blk, 0, size, buf, 0);
75
+ ret = blk_pread_nonzeroes(blk, size, buf);
76
if (ret < 0) {
77
error_setg_errno(errp, -ret, "can't read block backend");
78
return false;
79
--
80
2.38.1
81
82
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Clang has a generic __annotate__ attribute that can be used by
4
static analyzers to understand properties of functions and
5
analyze the control flow. Furthermore, unlike TSA annotations, the
6
__annotate__ attribute applies to function pointers as well.
7
8
As a first step towards static analysis of coroutine_fn markers,
9
attach the attribute to the marker when compiling with clang.
10
11
Signed-off-by: Alberto Faria <afaria@redhat.com>
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
13
Message-Id: <20221216110758.559947-2-pbonzini@redhat.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
include/qemu/coroutine.h | 4 ++++
18
1 file changed, 4 insertions(+)
19
20
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/qemu/coroutine.h
23
+++ b/include/qemu/coroutine.h
24
@@ -XXX,XX +XXX,XX @@
25
* ....
26
* }
27
*/
28
+#ifdef __clang__
29
+#define coroutine_fn __attribute__((__annotate__("coroutine_fn")))
30
+#else
31
#define coroutine_fn
32
+#endif
33
34
typedef struct Coroutine Coroutine;
35
36
--
37
2.38.1
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Add more annotations to functions, describing valid and invalid
4
calls from coroutine to non-coroutine context.
5
6
When applied to a function, no_coroutine_fn advertises that it should
7
not be called from coroutine_fn functions. This can be because the
8
function blocks or, in the case of generated_co_wrapper, to enforce
9
that coroutine_fn functions directly call the coroutine_fn that backs
10
the generated_co_wrapper.
11
12
coroutine_mixed_fn instead is for function that can be called in
13
both coroutine and non-coroutine context, but will suspend when
14
called in coroutine context. Annotating them is a first step
15
towards enforcing that non-annotated functions are absolutely
16
not going to suspend.
17
18
These can be used for example with the vrc tool:
19
20
# find functions that *really* cannot be called from no_coroutine_fn
21
(vrc) load --loader clang libblock.fa.p/meson-generated_.._block_block-gen.c.o
22
(vrc) paths [no_coroutine_fn,!coroutine_mixed_fn]
23
bdrv_remove_persistent_dirty_bitmap
24
bdrv_create
25
bdrv_can_store_new_dirty_bitmap
26
27
# find how coroutine_fns end up calling a mixed function
28
(vrc) load --loader clang --force libblock.fa.p/*.c.o
29
(vrc) paths [coroutine_fn] [!no_coroutine_fn]* [coroutine_mixed_fn]
30
...
31
bdrv_pread <- vhdx_log_write <- vhdx_log_write_and_flush <- vhdx_co_writev
32
...
33
34
Signed-off-by: Alberto Faria <afaria@redhat.com>
35
[Rebase, add coroutine_mixed_fn. - Paolo]
36
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
37
Message-Id: <20221216110758.559947-3-pbonzini@redhat.com>
38
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
39
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
40
---
41
include/block/block-common.h | 11 ++++++----
42
include/qemu/coroutine.h | 39 ++++++++++++++++++++++++++++++++++++
43
2 files changed, 46 insertions(+), 4 deletions(-)
44
45
diff --git a/include/block/block-common.h b/include/block/block-common.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block-common.h
48
+++ b/include/block/block-common.h
49
@@ -XXX,XX +XXX,XX @@
50
* - co_wrapper_mixed_bdrv_rdlock are co_wrapper_mixed functions but
51
* automatically take and release the graph rdlock when creating a new
52
* coroutine.
53
+ *
54
+ * These functions should not be called from a coroutine_fn; instead,
55
+ * call the wrapped function directly.
56
*/
57
-#define co_wrapper
58
-#define co_wrapper_mixed
59
-#define co_wrapper_bdrv_rdlock
60
-#define co_wrapper_mixed_bdrv_rdlock
61
+#define co_wrapper no_coroutine_fn
62
+#define co_wrapper_mixed no_coroutine_fn coroutine_mixed_fn
63
+#define co_wrapper_bdrv_rdlock no_coroutine_fn
64
+#define co_wrapper_mixed_bdrv_rdlock no_coroutine_fn coroutine_mixed_fn
65
66
#include "block/dirty-bitmap.h"
67
#include "block/blockjob.h"
68
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/qemu/coroutine.h
71
+++ b/include/qemu/coroutine.h
72
@@ -XXX,XX +XXX,XX @@
73
#define coroutine_fn
74
#endif
75
76
+/**
77
+ * Mark a function that can suspend when executed in coroutine context,
78
+ * but can handle running in non-coroutine context too.
79
+ */
80
+#ifdef __clang__
81
+#define coroutine_mixed_fn __attribute__((__annotate__("coroutine_mixed_fn")))
82
+#else
83
+#define coroutine_mixed_fn
84
+#endif
85
+
86
+/**
87
+ * Mark a function that should not be called from a coroutine context.
88
+ * Usually there will be an analogous, coroutine_fn function that should
89
+ * be used instead.
90
+ *
91
+ * When the function is also marked as coroutine_mixed_fn, the function should
92
+ * only be called if the caller does not know whether it is in coroutine
93
+ * context.
94
+ *
95
+ * Functions that are only no_coroutine_fn, on the other hand, should not
96
+ * be called from within coroutines at all. This for example includes
97
+ * functions that block.
98
+ *
99
+ * In the future it would be nice to enable compiler or static checker
100
+ * support for catching such errors. This annotation is the first step
101
+ * towards this, and in the meantime it serves as documentation.
102
+ *
103
+ * For example:
104
+ *
105
+ * static void no_coroutine_fn foo(void) {
106
+ * ....
107
+ * }
108
+ */
109
+#ifdef __clang__
110
+#define no_coroutine_fn __attribute__((__annotate__("no_coroutine_fn")))
111
+#else
112
+#define no_coroutine_fn
113
+#endif
114
+
115
typedef struct Coroutine Coroutine;
116
117
/**
118
--
119
2.38.1
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
dma_blk_cb() only takes the AioContext lock around ->io_func(). That
3
qemu-io's do_co_pwrite_zeroes is reinventing the coroutine wrapper
4
means the rest of dma_blk_cb() is not protected. In particular, the
4
blk_pwrite_zeroes. Just use the real thing directly.
5
DMAAIOCB field accesses happen outside the lock.
6
5
7
There is a race when the main loop thread holds the AioContext lock and
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
invokes scsi_device_purge_requests() -> bdrv_aio_cancel() ->
7
Message-Id: <20221215130225.476477-1-pbonzini@redhat.com>
9
dma_aio_cancel() while an IOThread executes dma_blk_cb(). The dbs->acb
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
field determines how cancellation proceeds. If dma_aio_cancel() sees
11
dbs->acb == NULL while dma_blk_cb() is still running, the request can be
12
completed twice (-ECANCELED and the actual return value).
13
14
The following assertion can occur with virtio-scsi when an IOThread is
15
used:
16
17
../hw/scsi/scsi-disk.c:368: scsi_dma_complete: Assertion `r->req.aiocb != NULL' failed.
18
19
Fix the race by holding the AioContext across dma_blk_cb(). Now
20
dma_aio_cancel() under the AioContext lock will not see
21
inconsistent/intermediate states.
22
23
Cc: Paolo Bonzini <pbonzini@redhat.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Message-Id: <20230221212218.1378734-3-stefanha@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
---
10
---
29
hw/scsi/scsi-disk.c | 4 +---
11
qemu-io-cmds.c | 57 +++++++++-----------------------------------------
30
softmmu/dma-helpers.c | 12 +++++++-----
12
1 file changed, 10 insertions(+), 47 deletions(-)
31
2 files changed, 8 insertions(+), 8 deletions(-)
32
13
33
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
14
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
34
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/scsi/scsi-disk.c
16
--- a/qemu-io-cmds.c
36
+++ b/hw/scsi/scsi-disk.c
17
+++ b/qemu-io-cmds.c
37
@@ -XXX,XX +XXX,XX @@ done:
18
@@ -XXX,XX +XXX,XX @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
38
scsi_req_unref(&r->req);
19
return 1;
39
}
20
}
40
21
41
+/* Called with AioContext lock held */
22
-typedef struct {
42
static void scsi_dma_complete(void *opaque, int ret)
23
- BlockBackend *blk;
24
- int64_t offset;
25
- int64_t bytes;
26
- int64_t *total;
27
- int flags;
28
- int ret;
29
- bool done;
30
-} CoWriteZeroes;
31
-
32
-static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
33
-{
34
- CoWriteZeroes *data = opaque;
35
-
36
- data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
37
- data->flags);
38
- data->done = true;
39
- if (data->ret < 0) {
40
- *data->total = data->ret;
41
- return;
42
- }
43
-
44
- *data->total = data->bytes;
45
-}
46
-
47
-static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
48
+static int do_pwrite_zeroes(BlockBackend *blk, int64_t offset,
49
int64_t bytes, int flags, int64_t *total)
43
{
50
{
44
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
51
- Coroutine *co;
45
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
52
- CoWriteZeroes data = {
46
53
- .blk = blk,
47
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
54
- .offset = offset,
55
- .bytes = bytes,
56
- .total = total,
57
- .flags = flags,
58
- .done = false,
59
- };
48
-
60
-
49
assert(r->req.aiocb != NULL);
61
- co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
50
r->req.aiocb = NULL;
62
- bdrv_coroutine_enter(blk_bs(blk), co);
51
63
- while (!data.done) {
52
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
64
- aio_poll(blk_get_aio_context(blk), true);
53
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
65
- }
66
- if (data.ret < 0) {
67
- return data.ret;
68
- } else {
69
- return 1;
70
+ int ret = blk_pwrite_zeroes(blk, offset, bytes,
71
+ flags | BDRV_REQ_ZERO_WRITE);
72
+
73
+ if (ret < 0) {
74
+ return ret;
54
}
75
}
55
scsi_dma_complete_noio(r, ret);
76
+ *total = bytes;
56
- aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
77
+ return 1;
57
}
78
}
58
79
59
static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
80
static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
60
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
81
@@ -XXX,XX +XXX,XX @@ static void write_help(void)
61
index XXXXXXX..XXXXXXX 100644
82
" -C, -- report statistics in a machine parsable format\n"
62
--- a/softmmu/dma-helpers.c
83
" -q, -- quiet mode, do not show I/O statistics\n"
63
+++ b/softmmu/dma-helpers.c
84
" -u, -- with -z, allow unmapping\n"
64
@@ -XXX,XX +XXX,XX @@ static void dma_complete(DMAAIOCB *dbs, int ret)
85
-" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
65
static void dma_blk_cb(void *opaque, int ret)
86
+" -z, -- write zeroes using blk_pwrite_zeroes\n"
66
{
87
"\n");
67
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
68
+ AioContext *ctx = dbs->ctx;
69
dma_addr_t cur_addr, cur_len;
70
void *mem;
71
72
trace_dma_blk_cb(dbs, ret);
73
74
+ aio_context_acquire(ctx);
75
dbs->acb = NULL;
76
dbs->offset += dbs->iov.size;
77
78
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
79
dma_complete(dbs, ret);
80
- return;
81
+ goto out;
82
}
83
dma_blk_unmap(dbs);
84
85
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
86
87
if (dbs->iov.size == 0) {
88
trace_dma_map_wait(dbs);
89
- dbs->bh = aio_bh_new(dbs->ctx, reschedule_dma, dbs);
90
+ dbs->bh = aio_bh_new(ctx, reschedule_dma, dbs);
91
cpu_register_map_client(dbs->bh);
92
- return;
93
+ goto out;
94
}
95
96
if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) {
97
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
98
QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align));
99
}
100
101
- aio_context_acquire(dbs->ctx);
102
dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
103
dma_blk_cb, dbs, dbs->io_func_opaque);
104
- aio_context_release(dbs->ctx);
105
assert(dbs->acb);
106
+out:
107
+ aio_context_release(ctx);
108
}
88
}
109
89
110
static void dma_aio_cancel(BlockAIOCB *acb)
90
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
91
if (bflag) {
92
ret = do_save_vmstate(blk, buf, offset, count, &total);
93
} else if (zflag) {
94
- ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
95
+ ret = do_pwrite_zeroes(blk, offset, count, flags, &total);
96
} else if (cflag) {
97
ret = do_write_compressed(blk, buf, offset, count, &total);
98
} else {
111
--
99
--
112
2.39.2
100
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
bdrv_co_ioctl() need to hold a reader lock for the graph.
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
It has only one caller---inline it and remove the function.
5
Message-Id: <20230203152202.49054-6-kwolf@redhat.com>
4
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Message-Id: <20221215130225.476477-2-pbonzini@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
---
9
include/block/block-io.h | 3 ++-
10
include/block/block-io.h | 5 -----
10
include/block/block_int-common.h | 9 +++++----
11
block.c | 6 ------
11
block/block-backend.c | 1 +
12
block/block-backend.c | 2 +-
12
block/io.c | 1 +
13
3 files changed, 1 insertion(+), 12 deletions(-)
13
block/raw-format.c | 4 ++--
14
5 files changed, 11 insertions(+), 7 deletions(-)
15
14
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
15
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-io.h
17
--- a/include/block/block-io.h
19
+++ b/include/block/block-io.h
18
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb);
19
@@ -XXX,XX +XXX,XX @@ AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs);
21
void bdrv_aio_cancel_async(BlockAIOCB *acb);
20
*/
22
21
void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
23
/* sg packet commands */
22
24
-int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
23
-/**
25
+int coroutine_fn GRAPH_RDLOCK
24
- * Transfer control to @co in the aio context of @bs
26
+bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
25
- */
27
26
-void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co);
28
/* Ensure contents are flushed to disk. */
27
-
29
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
28
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
30
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
29
30
void bdrv_io_plug(BlockDriverState *bs);
31
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block_int-common.h
33
--- a/block.c
33
+++ b/include/block/block_int-common.h
34
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
35
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_unlock(BlockDriverState *bs)
35
void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
36
}
36
37
}
37
/* to control generic scsi devices */
38
38
- BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
39
-void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
39
- unsigned long int req, void *buf,
40
-{
40
+ BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)(
41
- IO_CODE();
41
+ BlockDriverState *bs, unsigned long int req, void *buf,
42
- aio_co_enter(bdrv_get_aio_context(bs), co);
42
BlockCompletionFunc *cb, void *opaque);
43
-}
43
- int coroutine_fn (*bdrv_co_ioctl)(BlockDriverState *bs,
44
-
44
- unsigned long int req, void *buf);
45
static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
45
+
46
{
46
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_ioctl)(
47
GLOBAL_STATE_CODE();
47
+ BlockDriverState *bs, unsigned long int req, void *buf);
48
49
/*
50
* Returns 0 for completed check, -errno for internal errors.
51
diff --git a/block/block-backend.c b/block/block-backend.c
48
diff --git a/block/block-backend.c b/block/block-backend.c
52
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
53
--- a/block/block-backend.c
50
--- a/block/block-backend.c
54
+++ b/block/block-backend.c
51
+++ b/block/block-backend.c
55
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
52
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
56
IO_CODE();
53
acb->has_returned = false;
57
54
58
blk_wait_while_drained(blk);
55
co = qemu_coroutine_create(co_entry, acb);
59
+ GRAPH_RDLOCK_GUARD();
56
- bdrv_coroutine_enter(blk_bs(blk), co);
60
57
+ aio_co_enter(blk_get_aio_context(blk), co);
61
if (!blk_is_available(blk)) {
58
62
return -ENOMEDIUM;
59
acb->has_returned = true;
63
diff --git a/block/io.c b/block/io.c
60
if (acb->rwco.ret != NOT_DONE) {
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/io.c
66
+++ b/block/io.c
67
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
68
};
69
BlockAIOCB *acb;
70
IO_CODE();
71
+ assert_bdrv_graph_readable();
72
73
bdrv_inc_in_flight(bs);
74
if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) {
75
diff --git a/block/raw-format.c b/block/raw-format.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/raw-format.c
78
+++ b/block/raw-format.c
79
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
80
bdrv_co_lock_medium(bs->file->bs, locked);
81
}
82
83
-static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
84
- unsigned long int req, void *buf)
85
+static int coroutine_fn GRAPH_RDLOCK
86
+raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
87
{
88
BDRVRawState *s = bs->opaque;
89
if (s->offset || s->has_size) {
90
--
61
--
91
2.39.2
62
2.38.1
diff view generated by jsdifflib
New patch
1
In order to write the bitmap table to the image file, it is converted to
2
big endian. If the write fails, it is passed to clear_bitmap_table() to
3
free all of the clusters it had allocated before. However, if we don't
4
convert it back to native endianness first, we'll free things at a wrong
5
offset.
1
6
7
In practical terms, the offsets will be so high that we won't actually
8
free any allocated clusters, but just run into an error, but in theory
9
this can cause image corruption.
10
11
Cc: qemu-stable@nongnu.org
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230112191454.169353-2-kwolf@redhat.com>
14
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block/qcow2-bitmap.c | 5 +++--
19
1 file changed, 3 insertions(+), 2 deletions(-)
20
21
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-bitmap.c
24
+++ b/block/qcow2-bitmap.c
25
@@ -XXX,XX +XXX,XX @@ static int update_header_sync(BlockDriverState *bs)
26
return bdrv_flush(bs->file->bs);
27
}
28
29
-static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
30
+static inline void bitmap_table_bswap_be(uint64_t *bitmap_table, size_t size)
31
{
32
size_t i;
33
34
@@ -XXX,XX +XXX,XX @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
35
goto fail;
36
}
37
38
- bitmap_table_to_be(tb, tb_size);
39
+ bitmap_table_bswap_be(tb, tb_size);
40
ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0);
41
if (ret < 0) {
42
+ bitmap_table_bswap_be(tb, tb_size);
43
error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
44
bm_name);
45
goto fail;
46
--
47
2.38.1
48
49
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
blk_unref() can't report any errors that happen while closing the image.
2
bdrv_register_buf() and bdrv_unregister_buf() need to hold a reader lock
2
For example, if qcow2 hits an -ENOSPC error while writing out dirty
3
for the graph.
3
bitmaps when it's closed, it prints error messages to stderr, but
4
'qemu-img commit' won't see any error return value and will therefore
5
look successful with exit code 0.
6
7
In order to fix this, manually inactivate the image first before calling
8
blk_unref(). This already performs the operations that would be most
9
likely to fail while closing the image, but it can still return errors.
4
10
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20230203152202.49054-21-kwolf@redhat.com>
12
Message-Id: <20230112191454.169353-3-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
15
---
10
include/block/block_int-common.h | 7 ++++---
16
qemu-img.c | 13 +++++++++++++
11
block/io.c | 14 ++++++++++----
17
1 file changed, 13 insertions(+)
12
2 files changed, 14 insertions(+), 7 deletions(-)
13
18
14
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
19
diff --git a/qemu-img.c b/qemu-img.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block_int-common.h
21
--- a/qemu-img.c
17
+++ b/include/block/block_int-common.h
22
+++ b/qemu-img.c
18
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
23
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open(bool image_opts,
19
*
24
blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet,
20
* Returns: true on success, false on failure
25
force_share);
21
*/
26
}
22
- bool (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size,
27
+
23
- Error **errp);
28
+ if (blk) {
24
- void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host, size_t size);
29
+ blk_set_force_allow_inactivate(blk);
25
+ bool GRAPH_RDLOCK_PTR (*bdrv_register_buf)(
30
+ }
26
+ BlockDriverState *bs, void *host, size_t size, Error **errp);
31
+
27
+ void GRAPH_RDLOCK_PTR (*bdrv_unregister_buf)(
32
return blk;
28
+ BlockDriverState *bs, void *host, size_t size);
29
30
/*
31
* This field is modified only under the BQL, and is part of
32
diff --git a/block/io.c b/block/io.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/io.c
35
+++ b/block/io.c
36
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
37
}
33
}
38
34
39
/* Helper that undoes bdrv_register_buf() when it fails partway through */
35
@@ -XXX,XX +XXX,XX @@ unref_backing:
40
-static void bdrv_register_buf_rollback(BlockDriverState *bs,
36
done:
41
- void *host,
37
qemu_progress_end();
42
- size_t size,
38
43
- BdrvChild *final_child)
39
+ /*
44
+static void GRAPH_RDLOCK
40
+ * Manually inactivate the image first because this way we can know whether
45
+bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size,
41
+ * an error occurred. blk_unref() doesn't tell us about failures.
46
+ BdrvChild *final_child)
42
+ */
47
{
43
+ ret = bdrv_inactivate_all();
48
BdrvChild *child;
44
+ if (ret < 0 && !local_err) {
49
45
+ error_setg_errno(&local_err, -ret, "Error while closing the image");
50
+ GLOBAL_STATE_CODE();
46
+ }
51
+ assert_bdrv_graph_readable();
47
blk_unref(blk);
52
+
48
53
QLIST_FOREACH(child, &bs->children, next) {
49
if (local_err) {
54
if (child == final_child) {
55
break;
56
@@ -XXX,XX +XXX,XX @@ bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
57
BdrvChild *child;
58
59
GLOBAL_STATE_CODE();
60
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
61
+
62
if (bs->drv && bs->drv->bdrv_register_buf) {
63
if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) {
64
return false;
65
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
66
BdrvChild *child;
67
68
GLOBAL_STATE_CODE();
69
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
70
+
71
if (bs->drv && bs->drv->bdrv_unregister_buf) {
72
bs->drv->bdrv_unregister_buf(bs, host, size);
73
}
74
--
50
--
75
2.39.2
51
2.38.1
diff view generated by jsdifflib
New patch
1
blk_unref() can't report any errors that happen while closing the image.
2
For example, if qcow2 hits an -ENOSPC error while writing out dirty
3
bitmaps when it's closed, it prints error messages to stderr, but
4
'qemu-img bitmap' won't see any error return value and will therefore
5
look successful with exit code 0.
1
6
7
In order to fix this, manually inactivate the image first before calling
8
blk_unref(). This already performs the operations that would be most
9
likely to fail while closing the image, but it can still return errors.
10
11
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1330
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230112191454.169353-4-kwolf@redhat.com>
14
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
qemu-img.c | 11 +++++++++++
19
1 file changed, 11 insertions(+)
20
21
diff --git a/qemu-img.c b/qemu-img.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/qemu-img.c
24
+++ b/qemu-img.c
25
@@ -XXX,XX +XXX,XX @@ static int img_bitmap(int argc, char **argv)
26
QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
27
ImgBitmapAction *act, *act_next;
28
const char *op;
29
+ int inactivate_ret;
30
31
QSIMPLEQ_INIT(&actions);
32
33
@@ -XXX,XX +XXX,XX @@ static int img_bitmap(int argc, char **argv)
34
ret = 0;
35
36
out:
37
+ /*
38
+ * Manually inactivate the images first because this way we can know whether
39
+ * an error occurred. blk_unref() doesn't tell us about failures.
40
+ */
41
+ inactivate_ret = bdrv_inactivate_all();
42
+ if (inactivate_ret < 0) {
43
+ error_report("Error while closing the image: %s", strerror(-inactivate_ret));
44
+ ret = 1;
45
+ }
46
+
47
blk_unref(src);
48
blk_unref(blk);
49
qemu_opts_del(opts);
50
--
51
2.38.1
52
53
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
This tests that when an error happens while writing back bitmaps to the
2
bdrv_co_pwrite_sync() need to hold a reader lock for the graph.
2
image file in qcow2_inactivate(), 'qemu-img bitmap/commit' actually
3
3
return an error value in their exit code instead of making the operation
4
For some places, we know that they will hold the lock, but we don't have
4
look successful to scripts.
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
8
5
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230203152202.49054-13-kwolf@redhat.com>
7
Message-Id: <20230112191454.169353-5-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
10
---
14
block/qcow2.h | 2 +-
11
.../qemu-iotests/tests/qemu-img-close-errors | 95 +++++++++++++++++++
15
include/block/block-io.h | 7 ++++---
12
.../tests/qemu-img-close-errors.out | 23 +++++
16
block/io.c | 3 +--
13
2 files changed, 118 insertions(+)
17
3 files changed, 6 insertions(+), 6 deletions(-)
14
create mode 100755 tests/qemu-iotests/tests/qemu-img-close-errors
15
create mode 100644 tests/qemu-iotests/tests/qemu-img-close-errors.out
18
16
19
diff --git a/block/qcow2.h b/block/qcow2.h
17
diff --git a/tests/qemu-iotests/tests/qemu-img-close-errors b/tests/qemu-iotests/tests/qemu-img-close-errors
20
index XXXXXXX..XXXXXXX 100644
18
new file mode 100755
21
--- a/block/qcow2.h
19
index XXXXXXX..XXXXXXX
22
+++ b/block/qcow2.h
20
--- /dev/null
23
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
21
+++ b/tests/qemu-iotests/tests/qemu-img-close-errors
24
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
22
@@ -XXX,XX +XXX,XX @@
25
BlockDriverAmendStatusCB *status_cb,
23
+#!/usr/bin/env bash
26
void *cb_opaque, Error **errp);
24
+# group: rw auto quick
27
-int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
25
+#
28
+int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
26
+# Check that errors while closing the image, in particular writing back dirty
29
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
27
+# bitmaps, is correctly reported with a failing qemu-img exit code.
30
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
28
+#
31
29
+# Copyright (C) 2023 Red Hat, Inc.
32
diff --git a/include/block/block-io.h b/include/block/block-io.h
30
+#
33
index XXXXXXX..XXXXXXX 100644
31
+# This program is free software; you can redistribute it and/or modify
34
--- a/include/block/block-io.h
32
+# it under the terms of the GNU General Public License as published by
35
+++ b/include/block/block-io.h
33
+# the Free Software Foundation; either version 2 of the License, or
36
@@ -XXX,XX +XXX,XX @@ int co_wrapper_mixed_bdrv_rdlock
34
+# (at your option) any later version.
37
bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
35
+#
38
const void *buf, BdrvRequestFlags flags);
36
+# This program is distributed in the hope that it will be useful,
39
37
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
-int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
38
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
- int64_t bytes, const void *buf,
39
+# GNU General Public License for more details.
42
- BdrvRequestFlags flags);
40
+#
43
+int coroutine_fn GRAPH_RDLOCK
41
+# You should have received a copy of the GNU General Public License
44
+bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
42
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
45
+ const void *buf, BdrvRequestFlags flags);
43
+#
46
+
44
+
47
/*
45
+# creator
48
* Efficiently zero a region of the disk image. Note that this is a regular
46
+owner=kwolf@redhat.com
49
* I/O request like read or write and should have a reasonable size. This
47
+
50
diff --git a/block/io.c b/block/io.c
48
+seq="$(basename $0)"
51
index XXXXXXX..XXXXXXX 100644
49
+echo "QA output created by $seq"
52
--- a/block/io.c
50
+
53
+++ b/block/io.c
51
+status=1    # failure is the default!
54
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
52
+
55
{
53
+_cleanup()
56
int ret;
54
+{
57
IO_CODE();
55
+ _cleanup_test_img
58
-
56
+}
59
- assume_graph_lock(); /* FIXME */
57
+trap "_cleanup; exit \$status" 0 1 2 3 15
60
+ assert_bdrv_graph_readable();
58
+
61
59
+# get standard environment, filters and checks
62
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
60
+cd ..
63
if (ret < 0) {
61
+. ./common.rc
62
+. ./common.filter
63
+
64
+_supported_fmt qcow2
65
+_supported_proto generic
66
+
67
+size=1G
68
+
69
+# The error we are going to use is ENOSPC. Depending on how many bitmaps we
70
+# create in the backing file (and therefore increase the used up space), we get
71
+# failures in different places. With a low number, only merging the bitmap
72
+# fails, whereas with a higher number, already 'qemu-img commit' fails.
73
+for max_bitmap in 6 7; do
74
+ echo
75
+ echo "=== Test with $max_bitmap bitmaps ==="
76
+
77
+ TEST_IMG="$TEST_IMG.base" _make_test_img -q $size
78
+ for i in $(seq 1 $max_bitmap); do
79
+ $QEMU_IMG bitmap --add "$TEST_IMG.base" "stale-bitmap-$i"
80
+ done
81
+
82
+ # Simulate a block device of 128 MB by resizing the image file accordingly
83
+ # and then enforcing the size with the raw driver
84
+ truncate "$TEST_IMG.base" --size 128M
85
+ BASE_JSON='json:{
86
+ "driver": "qcow2",
87
+ "file": {
88
+ "driver": "raw",
89
+ "size": 134217728,
90
+ "file": {
91
+ "driver": "file",
92
+ "filename":"'"$TEST_IMG.base"'"
93
+ }
94
+ }
95
+ }'
96
+
97
+ _make_test_img -q -b "$BASE_JSON" -F $IMGFMT
98
+ $QEMU_IMG bitmap --add "$TEST_IMG" "good-bitmap"
99
+
100
+ $QEMU_IO -c 'write 0 126m' "$TEST_IMG" | _filter_qemu_io
101
+
102
+ $QEMU_IMG commit -d "$TEST_IMG" 2>&1 | _filter_generated_node_ids
103
+ echo "qemu-img commit exit code: ${PIPESTATUS[0]}"
104
+
105
+ $QEMU_IMG bitmap --add "$BASE_JSON" "good-bitmap"
106
+ echo "qemu-img bitmap --add exit code: $?"
107
+
108
+ $QEMU_IMG bitmap --merge "good-bitmap" -b "$TEST_IMG" "$BASE_JSON" \
109
+ "good-bitmap" 2>&1 | _filter_generated_node_ids
110
+ echo "qemu-img bitmap --merge exit code: ${PIPESTATUS[0]}"
111
+done
112
+
113
+# success, all done
114
+echo "*** done"
115
+rm -f $seq.full
116
+status=0
117
+
118
diff --git a/tests/qemu-iotests/tests/qemu-img-close-errors.out b/tests/qemu-iotests/tests/qemu-img-close-errors.out
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/tests/qemu-iotests/tests/qemu-img-close-errors.out
123
@@ -XXX,XX +XXX,XX @@
124
+QA output created by qemu-img-close-errors
125
+
126
+=== Test with 6 bitmaps ===
127
+wrote 132120576/132120576 bytes at offset 0
128
+126 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
129
+Image committed.
130
+qemu-img commit exit code: 0
131
+qemu-img bitmap --add exit code: 0
132
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'good-bitmap' to file: No space left on device
133
+qemu-img: Error while closing the image: Invalid argument
134
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'good-bitmap' to file: No space left on device
135
+qemu-img bitmap --merge exit code: 1
136
+
137
+=== Test with 7 bitmaps ===
138
+wrote 132120576/132120576 bytes at offset 0
139
+126 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
140
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'stale-bitmap-7' to file: No space left on device
141
+qemu-img: Lost persistent bitmaps during inactivation of node 'NODE_NAME': Failed to write bitmap 'stale-bitmap-7' to file: No space left on device
142
+qemu-img: Error while closing the image: Invalid argument
143
+qemu-img commit exit code: 1
144
+qemu-img bitmap --add exit code: 0
145
+qemu-img bitmap --merge exit code: 0
146
+*** done
64
--
147
--
65
2.39.2
148
2.38.1
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This function is called in two different places:
3
Just omit the various 'return' when the return type is void.
4
- timer callback, which does not take the graph rdlock.
5
- bdrv_qed_drain_begin(), which is .bdrv_drain_begin()
6
callback documented as function that does not take the lock.
7
8
Since it calls recursive functions that traverse the
9
graph, we need to protect them with the graph rdlock.
10
4
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230203152202.49054-7-kwolf@redhat.com>
7
Message-Id: <20230113204212.359076-2-kwolf@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
10
---
17
block/qed.c | 4 +++-
11
scripts/block-coroutine-wrapper.py | 20 +++++++++++++++-----
18
1 file changed, 3 insertions(+), 1 deletion(-)
12
1 file changed, 15 insertions(+), 5 deletions(-)
19
13
20
diff --git a/block/qed.c b/block/qed.c
14
diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qed.c
16
--- a/scripts/block-coroutine-wrapper.py
23
+++ b/block/qed.c
17
+++ b/scripts/block-coroutine-wrapper.py
24
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s)
18
@@ -XXX,XX +XXX,XX @@ def __init__(self, return_type: str, name: str, args: str,
25
qemu_co_mutex_unlock(&s->table_lock);
19
ctx = 'qemu_get_aio_context()'
26
}
20
self.ctx = ctx
27
21
28
-static void coroutine_fn qed_need_check_timer(BDRVQEDState *s)
22
+ self.get_result = 's->ret = '
29
+static void coroutine_fn GRAPH_RDLOCK qed_need_check_timer(BDRVQEDState *s)
23
+ self.ret = 'return s.ret;'
30
{
24
+ self.co_ret = 'return '
31
int ret;
25
+ self.return_field = self.return_type + " ret;"
32
26
+ if self.return_type == 'void':
33
trace_qed_need_check_timer_cb(s);
27
+ self.get_result = ''
34
+ assert_bdrv_graph_readable();
28
+ self.ret = ''
35
29
+ self.co_ret = ''
36
if (!qed_plug_allocating_write_reqs(s)) {
30
+ self.return_field = ''
37
return;
31
+
38
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_need_check_timer(BDRVQEDState *s)
32
def gen_list(self, format: str) -> str:
39
static void coroutine_fn qed_need_check_timer_entry(void *opaque)
33
return ', '.join(format.format_map(arg.__dict__) for arg in self.args)
40
{
34
41
BDRVQEDState *s = opaque;
35
@@ -XXX,XX +XXX,XX @@ def create_mixed_wrapper(func: FuncDecl) -> str:
42
+ GRAPH_RDLOCK_GUARD();
36
{{
43
37
if (qemu_in_coroutine()) {{
44
qed_need_check_timer(opaque);
38
{graph_assume_lock}
45
bdrv_dec_in_flight(s->bs);
39
- return {name}({ func.gen_list('{name}') });
40
+ {func.co_ret}{name}({ func.gen_list('{name}') });
41
}} else {{
42
{struct_name} s = {{
43
.poll_state.ctx = {func.ctx},
44
@@ -XXX,XX +XXX,XX @@ def create_mixed_wrapper(func: FuncDecl) -> str:
45
s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
46
47
bdrv_poll_co(&s.poll_state);
48
- return s.ret;
49
+ {func.ret}
50
}}
51
}}"""
52
53
@@ -XXX,XX +XXX,XX @@ def create_co_wrapper(func: FuncDecl) -> str:
54
s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
55
56
bdrv_poll_co(&s.poll_state);
57
- return s.ret;
58
+ {func.ret}
59
}}"""
60
61
62
@@ -XXX,XX +XXX,XX @@ def gen_wrapper(func: FuncDecl) -> str:
63
64
typedef struct {struct_name} {{
65
BdrvPollCo poll_state;
66
- {func.return_type} ret;
67
+ {func.return_field}
68
{ func.gen_block(' {decl};') }
69
}} {struct_name};
70
71
@@ -XXX,XX +XXX,XX @@ def gen_wrapper(func: FuncDecl) -> str:
72
{struct_name} *s = opaque;
73
74
{graph_lock}
75
- s->ret = {name}({ func.gen_list('s->{name}') });
76
+ {func.get_result}{name}({ func.gen_list('s->{name}') });
77
{graph_unlock}
78
s->poll_state.in_progress = false;
79
46
--
80
--
47
2.39.2
81
2.38.1
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This adds GRAPH_RDLOCK annotations to declare that callers of
3
BlockDriver->bdrv_io_plug is categorized as IO callback, and it
4
bdrv_co_flush() need to hold a reader lock for the graph.
4
currently doesn't run in a coroutine. We should let it take a graph
5
rdlock since the callback traverses the block nodes graph, which however
6
is only possible in a coroutine.
5
7
6
For some places, we know that they will hold the lock, but we don't have
8
The only caller of this function is blk_io_plug(), therefore make
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
9
blk_io_plug() a co_wrapper, so that we're always running in a coroutine
8
with a FIXME comment. These places will be removed once everything is
10
where the lock can be taken.
9
properly annotated.
10
11
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230203152202.49054-8-kwolf@redhat.com>
14
Message-Id: <20230113204212.359076-3-kwolf@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
---
17
block/qcow2.h | 5 +++-
18
include/block/block-io.h | 3 ++-
18
block/qed.h | 29 +++++++++++++--------
19
include/block/block_int-common.h | 2 +-
19
include/block/block-io.h | 2 +-
20
include/sysemu/block-backend-io.h | 4 +++-
20
include/block/block_int-common.h | 12 +++++----
21
block/block-backend.c | 4 ++--
21
block/blkdebug.c | 2 +-
22
block/file-posix.c | 10 +++++-----
22
block/blklogwrites.c | 21 ++++++++++-----
23
block/io.c | 8 ++++----
23
block/blkreplay.c | 2 +-
24
block/nvme.c | 4 ++--
24
block/blkverify.c | 2 +-
25
7 files changed, 19 insertions(+), 16 deletions(-)
25
block/block-backend.c | 3 ++-
26
block/copy-before-write.c | 2 +-
27
block/file-posix.c | 4 +--
28
block/io.c | 7 +++++
29
block/mirror.c | 2 +-
30
block/preallocate.c | 2 +-
31
block/qed-check.c | 3 ++-
32
block/qed-table.c | 6 ++---
33
block/qed.c | 44 +++++++++++++++++++-------------
34
block/quorum.c | 2 +-
35
block/throttle.c | 2 +-
36
block/vmdk.c | 6 +++--
37
20 files changed, 98 insertions(+), 60 deletions(-)
38
26
39
diff --git a/block/qcow2.h b/block/qcow2.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2.h
42
+++ b/block/qcow2.h
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
44
/* qcow2-cluster.c functions */
45
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
46
bool exact_size);
47
-int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
48
+
49
+int coroutine_fn GRAPH_RDLOCK
50
+qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
51
+
52
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
53
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
54
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
55
diff --git a/block/qed.h b/block/qed.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qed.h
58
+++ b/block/qed.h
59
@@ -XXX,XX +XXX,XX @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
60
* Table I/O functions
61
*/
62
int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
63
-int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index,
64
- unsigned int n);
65
-int coroutine_fn qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
66
- unsigned int n);
67
+
68
+int coroutine_fn GRAPH_RDLOCK
69
+qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
70
+
71
+int coroutine_fn GRAPH_RDLOCK
72
+qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
73
+
74
int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
75
uint64_t offset);
76
int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
77
uint64_t offset);
78
-int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
79
- unsigned int index, unsigned int n,
80
- bool flush);
81
-int coroutine_fn qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
82
- unsigned int index, unsigned int n,
83
- bool flush);
84
+
85
+int coroutine_fn GRAPH_RDLOCK
86
+qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
87
+ unsigned int n, bool flush);
88
+
89
+int coroutine_fn GRAPH_RDLOCK
90
+qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
91
+ unsigned int index, unsigned int n, bool flush);
92
93
/**
94
* Cluster functions
95
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
96
/**
97
* Consistency check
98
*/
99
-int coroutine_fn qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
100
+int coroutine_fn GRAPH_RDLOCK
101
+qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
102
+
103
104
QEDTable *qed_alloc_table(BDRVQEDState *s);
105
106
diff --git a/include/block/block-io.h b/include/block/block-io.h
27
diff --git a/include/block/block-io.h b/include/block/block-io.h
107
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
108
--- a/include/block/block-io.h
29
--- a/include/block/block-io.h
109
+++ b/include/block/block-io.h
30
+++ b/include/block/block-io.h
110
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK
31
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
111
bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
32
112
33
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
113
/* Ensure contents are flushed to disk. */
34
114
-int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
35
-void bdrv_io_plug(BlockDriverState *bs);
115
+int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
36
+void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
116
37
+
117
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
38
void bdrv_io_unplug(BlockDriverState *bs);
118
int64_t bytes);
39
40
bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
119
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
41
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
120
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
121
--- a/include/block/block_int-common.h
43
--- a/include/block/block_int-common.h
122
+++ b/include/block/block_int-common.h
44
+++ b/include/block/block_int-common.h
123
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
124
BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
46
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
125
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
47
126
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
48
/* io queue for linux-aio */
127
- BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
49
- void (*bdrv_io_plug)(BlockDriverState *bs);
128
- BlockCompletionFunc *cb, void *opaque);
50
+ void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
129
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
51
void (*bdrv_io_unplug)(BlockDriverState *bs);
130
+ BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
52
131
BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
53
/**
132
int64_t offset, int bytes,
54
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
133
BlockCompletionFunc *cb, void *opaque);
134
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
135
* layers, if needed. This function is needed for deterministic
136
* synchronization of the flush finishing callback.
137
*/
138
- int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
139
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs);
140
141
/* Delete a created file. */
142
int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
143
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
144
* Flushes all data that was already written to the OS all the way down to
145
* the disk (for example file-posix.c calls fsync()).
146
*/
147
- int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs);
148
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_disk)(
149
+ BlockDriverState *bs);
150
151
/*
152
* Flushes all internal caches to the OS. The data may still sit in a
153
* writeback cache of the host OS, but it will survive a crash of the qemu
154
* process.
155
*/
156
- int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
157
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_os)(
158
+ BlockDriverState *bs);
159
160
/*
161
* Truncate @bs to @offset bytes using the given @prealloc mode
162
diff --git a/block/blkdebug.c b/block/blkdebug.c
163
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
164
--- a/block/blkdebug.c
56
--- a/include/sysemu/block-backend-io.h
165
+++ b/block/blkdebug.c
57
+++ b/include/sysemu/block-backend-io.h
166
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
58
@@ -XXX,XX +XXX,XX @@ void blk_iostatus_set_err(BlockBackend *blk, int error);
167
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
59
int blk_get_max_iov(BlockBackend *blk);
168
}
60
int blk_get_max_hw_iov(BlockBackend *blk);
169
61
170
-static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
62
-void blk_io_plug(BlockBackend *blk);
171
+static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
63
+void coroutine_fn blk_co_io_plug(BlockBackend *blk);
172
{
64
+void co_wrapper blk_io_plug(BlockBackend *blk);
173
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
65
+
174
66
void blk_io_unplug(BlockBackend *blk);
175
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
67
AioContext *blk_get_aio_context(BlockBackend *blk);
176
index XXXXXXX..XXXXXXX 100644
68
BlockAcctStats *blk_get_stats(BlockBackend *blk);
177
--- a/block/blklogwrites.c
178
+++ b/block/blklogwrites.c
179
@@ -XXX,XX +XXX,XX @@ typedef struct BlkLogWritesFileReq {
180
uint64_t bytes;
181
int file_flags;
182
QEMUIOVector *qiov;
183
- int (*func)(struct BlkLogWritesFileReq *r);
184
+ int GRAPH_RDLOCK_PTR (*func)(struct BlkLogWritesFileReq *r);
185
int file_ret;
186
} BlkLogWritesFileReq;
187
188
@@ -XXX,XX +XXX,XX @@ typedef struct {
189
int log_ret;
190
} BlkLogWritesLogReq;
191
192
-static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
193
+static void coroutine_fn GRAPH_RDLOCK
194
+blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
195
{
196
BDRVBlkLogWritesState *s = lr->bs->opaque;
197
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
198
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
199
}
200
}
201
202
-static void coroutine_fn blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
203
+static void coroutine_fn GRAPH_RDLOCK
204
+blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
205
{
206
fr->file_ret = fr->func(fr);
207
}
208
209
-static int coroutine_fn
210
+static int coroutine_fn GRAPH_RDLOCK
211
blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
212
QEMUIOVector *qiov, int flags,
213
- int (*file_func)(BlkLogWritesFileReq *r),
214
+ int /*GRAPH_RDLOCK*/ (*file_func)(BlkLogWritesFileReq *r),
215
uint64_t entry_flags, bool is_zero_write)
216
{
217
QEMUIOVector log_qiov;
218
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
219
fr->file_flags);
220
}
221
222
-static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
223
+static int coroutine_fn GRAPH_RDLOCK
224
+blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
225
{
226
return bdrv_co_flush(fr->bs->file->bs);
227
}
228
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
229
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
230
QEMUIOVector *qiov, BdrvRequestFlags flags)
231
{
232
+ assume_graph_lock(); /* FIXME */
233
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
234
blk_log_writes_co_do_file_pwritev, 0, false);
235
}
236
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
237
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
238
int64_t bytes, BdrvRequestFlags flags)
239
{
240
+ assume_graph_lock(); /* FIXME */
241
return blk_log_writes_co_log(bs, offset, bytes, NULL, flags,
242
blk_log_writes_co_do_file_pwrite_zeroes, 0,
243
true);
244
}
245
246
-static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
247
+static int coroutine_fn GRAPH_RDLOCK
248
+blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
249
{
250
return blk_log_writes_co_log(bs, 0, 0, NULL, 0,
251
blk_log_writes_co_do_file_flush,
252
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
253
static int coroutine_fn
254
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
255
{
256
+ assume_graph_lock(); /* FIXME */
257
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,
258
blk_log_writes_co_do_file_pdiscard,
259
LOG_DISCARD_FLAG, false);
260
diff --git a/block/blkreplay.c b/block/blkreplay.c
261
index XXXXXXX..XXXXXXX 100644
262
--- a/block/blkreplay.c
263
+++ b/block/blkreplay.c
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
265
return ret;
266
}
267
268
-static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
269
+static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
270
{
271
uint64_t reqid = blkreplay_next_id();
272
int ret = bdrv_co_flush(bs->file->bs);
273
diff --git a/block/blkverify.c b/block/blkverify.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/block/blkverify.c
276
+++ b/block/blkverify.c
277
@@ -XXX,XX +XXX,XX @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
278
return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
279
}
280
281
-static int coroutine_fn blkverify_co_flush(BlockDriverState *bs)
282
+static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs)
283
{
284
BDRVBlkverifyState *s = bs->opaque;
285
286
diff --git a/block/block-backend.c b/block/block-backend.c
69
diff --git a/block/block-backend.c b/block/block-backend.c
287
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
288
--- a/block/block-backend.c
71
--- a/block/block-backend.c
289
+++ b/block/block-backend.c
72
+++ b/block/block-backend.c
290
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
73
@@ -XXX,XX +XXX,XX @@ void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
291
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
74
notifier_list_add(&blk->insert_bs_notifiers, notify);
292
static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
75
}
76
77
-void blk_io_plug(BlockBackend *blk)
78
+void coroutine_fn blk_co_io_plug(BlockBackend *blk)
293
{
79
{
294
- blk_wait_while_drained(blk);
80
BlockDriverState *bs = blk_bs(blk);
295
IO_CODE();
81
IO_CODE();
296
+ blk_wait_while_drained(blk);
82
297
+ GRAPH_RDLOCK_GUARD();
83
if (bs) {
298
84
- bdrv_io_plug(bs);
299
if (!blk_is_available(blk)) {
85
+ bdrv_co_io_plug(bs);
300
return -ENOMEDIUM;
86
}
301
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
302
index XXXXXXX..XXXXXXX 100644
303
--- a/block/copy-before-write.c
304
+++ b/block/copy-before-write.c
305
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
306
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
307
}
87
}
308
88
309
-static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
310
+static int coroutine_fn GRAPH_RDLOCK cbw_co_flush(BlockDriverState *bs)
311
{
312
if (!bs->file) {
313
return 0;
314
diff --git a/block/file-posix.c b/block/file-posix.c
89
diff --git a/block/file-posix.c b/block/file-posix.c
315
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
316
--- a/block/file-posix.c
91
--- a/block/file-posix.c
317
+++ b/block/file-posix.c
92
+++ b/block/file-posix.c
318
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
94
return raw_co_prw(bs, offset, bytes, qiov, QEMU_AIO_WRITE);
319
}
95
}
320
#endif /* __linux__ */
96
321
97
-static void raw_aio_plug(BlockDriverState *bs)
322
-static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
98
+static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
323
- Error **errp)
324
+static void coroutine_fn GRAPH_RDLOCK
325
+raw_co_invalidate_cache(BlockDriverState *bs, Error **errp)
326
{
99
{
327
BDRVRawState *s = bs->opaque;
100
BDRVRawState __attribute__((unused)) *s = bs->opaque;
328
int ret;
101
#ifdef CONFIG_LINUX_AIO
102
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
103
.bdrv_co_copy_range_from = raw_co_copy_range_from,
104
.bdrv_co_copy_range_to = raw_co_copy_range_to,
105
.bdrv_refresh_limits = raw_refresh_limits,
106
- .bdrv_io_plug = raw_aio_plug,
107
+ .bdrv_co_io_plug = raw_co_io_plug,
108
.bdrv_io_unplug = raw_aio_unplug,
109
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
110
111
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
112
.bdrv_co_copy_range_from = raw_co_copy_range_from,
113
.bdrv_co_copy_range_to = raw_co_copy_range_to,
114
.bdrv_refresh_limits = raw_refresh_limits,
115
- .bdrv_io_plug = raw_aio_plug,
116
+ .bdrv_co_io_plug = raw_co_io_plug,
117
.bdrv_io_unplug = raw_aio_unplug,
118
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
119
120
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
121
.bdrv_co_pwritev = raw_co_pwritev,
122
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
123
.bdrv_refresh_limits = raw_refresh_limits,
124
- .bdrv_io_plug = raw_aio_plug,
125
+ .bdrv_co_io_plug = raw_co_io_plug,
126
.bdrv_io_unplug = raw_aio_unplug,
127
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
128
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
130
.bdrv_co_pwritev = raw_co_pwritev,
131
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
132
.bdrv_refresh_limits = raw_refresh_limits,
133
- .bdrv_io_plug = raw_aio_plug,
134
+ .bdrv_co_io_plug = raw_co_io_plug,
135
.bdrv_io_unplug = raw_aio_unplug,
136
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
137
329
diff --git a/block/io.c b/block/io.c
138
diff --git a/block/io.c b/block/io.c
330
index XXXXXXX..XXXXXXX 100644
139
index XXXXXXX..XXXXXXX 100644
331
--- a/block/io.c
140
--- a/block/io.c
332
+++ b/block/io.c
141
+++ b/block/io.c
333
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
142
@@ -XXX,XX +XXX,XX @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
334
int ret;
143
return mem;
144
}
145
146
-void bdrv_io_plug(BlockDriverState *bs)
147
+void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
148
{
149
BdrvChild *child;
335
IO_CODE();
150
IO_CODE();
336
151
337
+ assume_graph_lock(); /* FIXME */
152
QLIST_FOREACH(child, &bs->children, next) {
338
+
153
- bdrv_io_plug(child->bs);
339
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
154
+ bdrv_co_io_plug(child->bs);
340
if (ret < 0) {
155
}
341
return ret;
156
342
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
157
if (qatomic_fetch_inc(&bs->io_plugged) == 0) {
343
QEMUIOVector local_qiov;
158
BlockDriver *drv = bs->drv;
344
int ret;
159
- if (drv && drv->bdrv_io_plug) {
345
160
- drv->bdrv_io_plug(bs);
346
+ assume_graph_lock(); /* FIXME */
161
+ if (drv && drv->bdrv_co_io_plug) {
347
+
162
+ drv->bdrv_co_io_plug(bs);
348
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
163
}
349
350
if (!drv) {
351
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
352
int head = 0;
353
int tail = 0;
354
355
+ assume_graph_lock(); /* FIXME */
356
+
357
int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
358
INT64_MAX);
359
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
360
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
361
int ret = 0;
362
IO_CODE();
363
364
+ assert_bdrv_graph_readable();
365
bdrv_inc_in_flight(bs);
366
367
if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
368
diff --git a/block/mirror.c b/block/mirror.c
369
index XXXXXXX..XXXXXXX 100644
370
--- a/block/mirror.c
371
+++ b/block/mirror.c
372
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
373
return ret;
374
}
375
376
-static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)
377
+static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
378
{
379
if (bs->backing == NULL) {
380
/* we can be here after failed bdrv_append in mirror_start_job */
381
diff --git a/block/preallocate.c b/block/preallocate.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/block/preallocate.c
384
+++ b/block/preallocate.c
385
@@ -XXX,XX +XXX,XX @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
386
return 0;
387
}
388
389
-static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
390
+static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs)
391
{
392
return bdrv_co_flush(bs->file->bs);
393
}
394
diff --git a/block/qed-check.c b/block/qed-check.c
395
index XXXXXXX..XXXXXXX 100644
396
--- a/block/qed-check.c
397
+++ b/block/qed-check.c
398
@@ -XXX,XX +XXX,XX @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
399
/**
400
* Descend tables and check each cluster is referenced once only
401
*/
402
-static int coroutine_fn qed_check_l1_table(QEDCheck *check, QEDTable *table)
403
+static int coroutine_fn GRAPH_RDLOCK
404
+qed_check_l1_table(QEDCheck *check, QEDTable *table)
405
{
406
BDRVQEDState *s = check->s;
407
unsigned int i, num_invalid_l1 = 0;
408
diff --git a/block/qed-table.c b/block/qed-table.c
409
index XXXXXXX..XXXXXXX 100644
410
--- a/block/qed-table.c
411
+++ b/block/qed-table.c
412
@@ -XXX,XX +XXX,XX @@ out:
413
*
414
* Called with table_lock held.
415
*/
416
-static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
417
- QEDTable *table, unsigned int index,
418
- unsigned int n, bool flush)
419
+static int coroutine_fn GRAPH_RDLOCK
420
+qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
421
+ unsigned int index, unsigned int n, bool flush)
422
{
423
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
424
unsigned int start, end, i;
425
diff --git a/block/qed.c b/block/qed.c
426
index XXXXXXX..XXXXXXX 100644
427
--- a/block/qed.c
428
+++ b/block/qed.c
429
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_init_state(BlockDriverState *bs)
430
}
431
432
/* Called with table_lock held. */
433
-static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
434
- int flags, Error **errp)
435
+static int coroutine_fn GRAPH_RDLOCK
436
+bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
437
{
438
BDRVQEDState *s = bs->opaque;
439
QEDHeader le_header;
440
@@ -XXX,XX +XXX,XX @@ typedef struct QEDOpenCo {
441
int ret;
442
} QEDOpenCo;
443
444
-static void coroutine_fn bdrv_qed_open_entry(void *opaque)
445
+static void coroutine_fn GRAPH_RDLOCK bdrv_qed_open_entry(void *opaque)
446
{
447
QEDOpenCo *qoc = opaque;
448
BDRVQEDState *s = qoc->bs->opaque;
449
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
450
};
451
int ret;
452
453
+ assume_graph_lock(); /* FIXME */
454
+
455
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
456
if (ret < 0) {
457
return ret;
458
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb)
459
*
460
* Called with table_lock held.
461
*/
462
-static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
463
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_l1_update(QEDAIOCB *acb)
464
{
465
BDRVQEDState *s = acb_to_s(acb);
466
CachedL2Table *l2_table = acb->request.l2_table;
467
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
468
*
469
* Called with table_lock held.
470
*/
471
-static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
472
+static int coroutine_fn GRAPH_RDLOCK
473
+qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
474
{
475
BDRVQEDState *s = acb_to_s(acb);
476
bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1;
477
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
478
*
479
* Called with table_lock held.
480
*/
481
-static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb)
482
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_cow(QEDAIOCB *acb)
483
{
484
BDRVQEDState *s = acb_to_s(acb);
485
uint64_t start, len, offset;
486
@@ -XXX,XX +XXX,XX @@ static bool qed_should_set_need_check(BDRVQEDState *s)
487
*
488
* Called with table_lock held.
489
*/
490
-static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
491
+static int coroutine_fn GRAPH_RDLOCK
492
+qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
493
{
494
BDRVQEDState *s = acb_to_s(acb);
495
int ret;
496
@@ -XXX,XX +XXX,XX @@ out:
497
*
498
* Called with table_lock held.
499
*/
500
-static int coroutine_fn qed_aio_write_data(void *opaque, int ret,
501
- uint64_t offset, size_t len)
502
+static int coroutine_fn GRAPH_RDLOCK
503
+qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
504
{
505
QEDAIOCB *acb = opaque;
506
507
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
508
/**
509
* Begin next I/O or complete the request
510
*/
511
-static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
512
+static int coroutine_fn GRAPH_RDLOCK qed_aio_next_io(QEDAIOCB *acb)
513
{
514
BDRVQEDState *s = acb_to_s(acb);
515
uint64_t offset;
516
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
517
return ret;
518
}
519
520
-static int coroutine_fn qed_co_request(BlockDriverState *bs, int64_t sector_num,
521
- QEMUIOVector *qiov, int nb_sectors,
522
- int flags)
523
+static int coroutine_fn GRAPH_RDLOCK
524
+qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
525
+ int nb_sectors, int flags)
526
{
527
QEDAIOCB acb = {
528
.bs = bs,
529
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
530
int64_t sector_num, int nb_sectors,
531
QEMUIOVector *qiov)
532
{
533
+ assume_graph_lock(); /* FIXME */
534
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
535
}
536
537
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
538
int64_t sector_num, int nb_sectors,
539
QEMUIOVector *qiov, int flags)
540
{
541
+ assume_graph_lock(); /* FIXME */
542
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
543
}
544
545
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
546
{
547
BDRVQEDState *s = bs->opaque;
548
549
+ assume_graph_lock(); /* FIXME */
550
+
551
/*
552
* Zero writes start without an I/O buffer. If a buffer becomes necessary
553
* then it will be allocated during request processing.
554
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
555
return ret;
556
}
557
558
-static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
559
- Error **errp)
560
+static void coroutine_fn GRAPH_RDLOCK
561
+bdrv_qed_co_invalidate_cache(BlockDriverState *bs, Error **errp)
562
{
563
BDRVQEDState *s = bs->opaque;
564
int ret;
565
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
566
}
164
}
567
}
165
}
568
166
diff --git a/block/nvme.c b/block/nvme.c
569
-static int coroutine_fn bdrv_qed_co_check(BlockDriverState *bs,
167
index XXXXXXX..XXXXXXX 100644
570
- BdrvCheckResult *result,
168
--- a/block/nvme.c
571
- BdrvCheckMode fix)
169
+++ b/block/nvme.c
572
+static int coroutine_fn GRAPH_RDLOCK
170
@@ -XXX,XX +XXX,XX @@ static void nvme_attach_aio_context(BlockDriverState *bs,
573
+bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
171
}
574
+ BdrvCheckMode fix)
172
}
173
174
-static void nvme_aio_plug(BlockDriverState *bs)
175
+static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs)
575
{
176
{
576
BDRVQEDState *s = bs->opaque;
177
BDRVNVMeState *s = bs->opaque;
577
int ret;
178
assert(!s->plugged);
578
diff --git a/block/quorum.c b/block/quorum.c
179
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
579
index XXXXXXX..XXXXXXX 100644
180
.bdrv_detach_aio_context = nvme_detach_aio_context,
580
--- a/block/quorum.c
181
.bdrv_attach_aio_context = nvme_attach_aio_context,
581
+++ b/block/quorum.c
182
582
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
183
- .bdrv_io_plug = nvme_aio_plug,
583
return result;
184
+ .bdrv_co_io_plug = nvme_co_io_plug,
584
}
185
.bdrv_io_unplug = nvme_aio_unplug,
585
186
586
-static coroutine_fn int quorum_co_flush(BlockDriverState *bs)
187
.bdrv_register_buf = nvme_register_buf,
587
+static coroutine_fn GRAPH_RDLOCK int quorum_co_flush(BlockDriverState *bs)
588
{
589
BDRVQuorumState *s = bs->opaque;
590
QuorumVoteVersion *winner = NULL;
591
diff --git a/block/throttle.c b/block/throttle.c
592
index XXXXXXX..XXXXXXX 100644
593
--- a/block/throttle.c
594
+++ b/block/throttle.c
595
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
596
BDRV_REQ_WRITE_COMPRESSED);
597
}
598
599
-static int coroutine_fn throttle_co_flush(BlockDriverState *bs)
600
+static int coroutine_fn GRAPH_RDLOCK throttle_co_flush(BlockDriverState *bs)
601
{
602
return bdrv_co_flush(bs->file->bs);
603
}
604
diff --git a/block/vmdk.c b/block/vmdk.c
605
index XXXXXXX..XXXXXXX 100644
606
--- a/block/vmdk.c
607
+++ b/block/vmdk.c
608
@@ -XXX,XX +XXX,XX @@ exit:
609
return ret;
610
}
611
612
-static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
613
- uint32_t offset)
614
+static int coroutine_fn GRAPH_RDLOCK
615
+vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset)
616
{
617
offset = cpu_to_le32(offset);
618
/* update L2 table */
619
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
620
uint64_t bytes_done = 0;
621
VmdkMetaData m_data;
622
623
+ assume_graph_lock(); /* FIXME */
624
+
625
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
626
error_report("Wrong offset: offset=0x%" PRIx64
627
" total_sectors=0x%" PRIx64,
628
--
188
--
629
2.39.2
189
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_io_plug() and bdrv_co_io_unplug() need to hold a reader lock for
2
3
the graph.
3
BlockDriver->bdrv_io_unplug is categorized as IO callback, and it
4
4
currently doesn't run in a coroutine. We should let it take a graph
5
rdlock since the callback traverses the block nodes graph, which however
6
is only possible in a coroutine.
7
8
The only caller of this function is blk_io_unplug(), therefore make
9
blk_io_unplug() a co_wrapper, so that we're always running in a
10
coroutine where the lock can be taken.
11
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20230203152202.49054-18-kwolf@redhat.com>
14
Message-Id: <20230113204212.359076-4-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
17
---
10
include/block/block-io.h | 4 ++--
18
include/block/block-io.h | 3 +--
11
include/block/block_int-common.h | 5 +++--
19
include/block/block_int-common.h | 2 +-
12
block/block-backend.c | 2 ++
20
include/sysemu/block-backend-io.h | 4 +++-
13
block/io.c | 2 ++
21
block/blkio.c | 4 ++--
14
4 files changed, 9 insertions(+), 4 deletions(-)
22
block/block-backend.c | 4 ++--
23
block/file-posix.c | 10 +++++-----
24
block/io.c | 8 ++++----
25
block/nvme.c | 4 ++--
26
8 files changed, 20 insertions(+), 19 deletions(-)
15
27
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
28
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-io.h
30
--- a/include/block/block-io.h
19
+++ b/include/block/block-io.h
31
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
32
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
21
22
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
33
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
23
34
24
-void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
35
void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
25
-void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs);
36
-
26
+void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
37
-void bdrv_io_unplug(BlockDriverState *bs);
27
+void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
38
+void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs);
28
39
29
bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
40
bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
30
const char *name,
41
const char *name,
31
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
42
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
32
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
33
--- a/include/block/block_int-common.h
44
--- a/include/block/block_int-common.h
34
+++ b/include/block/block_int-common.h
45
+++ b/include/block/block_int-common.h
35
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
46
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
36
BlkdebugEvent event);
37
47
38
/* io queue for linux-aio */
48
/* io queue for linux-aio */
39
- void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
49
void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
40
- void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs);
50
- void (*bdrv_io_unplug)(BlockDriverState *bs);
41
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_plug)(BlockDriverState *bs);
51
+ void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs);
42
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_unplug)(
43
+ BlockDriverState *bs);
44
52
45
/**
53
/**
46
* bdrv_drain_begin is called if implemented in the beginning of a
54
* bdrv_drain_begin is called if implemented in the beginning of a
55
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/sysemu/block-backend-io.h
58
+++ b/include/sysemu/block-backend-io.h
59
@@ -XXX,XX +XXX,XX @@ int blk_get_max_hw_iov(BlockBackend *blk);
60
void coroutine_fn blk_co_io_plug(BlockBackend *blk);
61
void co_wrapper blk_io_plug(BlockBackend *blk);
62
63
-void blk_io_unplug(BlockBackend *blk);
64
+void coroutine_fn blk_co_io_unplug(BlockBackend *blk);
65
+void co_wrapper blk_io_unplug(BlockBackend *blk);
66
+
67
AioContext *blk_get_aio_context(BlockBackend *blk);
68
BlockAcctStats *blk_get_stats(BlockBackend *blk);
69
void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
70
diff --git a/block/blkio.c b/block/blkio.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/blkio.c
73
+++ b/block/blkio.c
74
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_co_pwrite_zeroes(BlockDriverState *bs,
75
return cod.ret;
76
}
77
78
-static void blkio_io_unplug(BlockDriverState *bs)
79
+static void coroutine_fn blkio_co_io_unplug(BlockDriverState *bs)
80
{
81
BDRVBlkioState *s = bs->opaque;
82
83
@@ -XXX,XX +XXX,XX @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
84
.bdrv_co_pwritev = blkio_co_pwritev, \
85
.bdrv_co_flush_to_disk = blkio_co_flush, \
86
.bdrv_co_pwrite_zeroes = blkio_co_pwrite_zeroes, \
87
- .bdrv_io_unplug = blkio_io_unplug, \
88
+ .bdrv_co_io_unplug = blkio_co_io_unplug, \
89
.bdrv_refresh_limits = blkio_refresh_limits, \
90
.bdrv_register_buf = blkio_register_buf, \
91
.bdrv_unregister_buf = blkio_unregister_buf, \
47
diff --git a/block/block-backend.c b/block/block-backend.c
92
diff --git a/block/block-backend.c b/block/block-backend.c
48
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
49
--- a/block/block-backend.c
94
--- a/block/block-backend.c
50
+++ b/block/block-backend.c
95
+++ b/block/block-backend.c
51
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk)
96
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk)
97
}
98
}
99
100
-void blk_io_unplug(BlockBackend *blk)
101
+void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
52
{
102
{
53
BlockDriverState *bs = blk_bs(blk);
103
BlockDriverState *bs = blk_bs(blk);
54
IO_CODE();
104
IO_CODE();
55
+ GRAPH_RDLOCK_GUARD();
56
105
57
if (bs) {
106
if (bs) {
58
bdrv_co_io_plug(bs);
107
- bdrv_io_unplug(bs);
59
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
108
+ bdrv_co_io_unplug(bs);
60
{
109
}
61
BlockDriverState *bs = blk_bs(blk);
110
}
62
IO_CODE();
111
63
+ GRAPH_RDLOCK_GUARD();
112
diff --git a/block/file-posix.c b/block/file-posix.c
64
113
index XXXXXXX..XXXXXXX 100644
65
if (bs) {
114
--- a/block/file-posix.c
66
bdrv_co_io_unplug(bs);
115
+++ b/block/file-posix.c
116
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
117
#endif
118
}
119
120
-static void raw_aio_unplug(BlockDriverState *bs)
121
+static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
122
{
123
BDRVRawState __attribute__((unused)) *s = bs->opaque;
124
#ifdef CONFIG_LINUX_AIO
125
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
126
.bdrv_co_copy_range_to = raw_co_copy_range_to,
127
.bdrv_refresh_limits = raw_refresh_limits,
128
.bdrv_co_io_plug = raw_co_io_plug,
129
- .bdrv_io_unplug = raw_aio_unplug,
130
+ .bdrv_co_io_unplug = raw_co_io_unplug,
131
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
132
133
.bdrv_co_truncate = raw_co_truncate,
134
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
135
.bdrv_co_copy_range_to = raw_co_copy_range_to,
136
.bdrv_refresh_limits = raw_refresh_limits,
137
.bdrv_co_io_plug = raw_co_io_plug,
138
- .bdrv_io_unplug = raw_aio_unplug,
139
+ .bdrv_co_io_unplug = raw_co_io_unplug,
140
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
141
142
.bdrv_co_truncate = raw_co_truncate,
143
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
144
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
145
.bdrv_refresh_limits = raw_refresh_limits,
146
.bdrv_co_io_plug = raw_co_io_plug,
147
- .bdrv_io_unplug = raw_aio_unplug,
148
+ .bdrv_co_io_unplug = raw_co_io_unplug,
149
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
150
151
.bdrv_co_truncate = raw_co_truncate,
152
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
153
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
154
.bdrv_refresh_limits = raw_refresh_limits,
155
.bdrv_co_io_plug = raw_co_io_plug,
156
- .bdrv_io_unplug = raw_aio_unplug,
157
+ .bdrv_co_io_unplug = raw_co_io_unplug,
158
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
159
160
.bdrv_co_truncate = raw_co_truncate,
67
diff --git a/block/io.c b/block/io.c
161
diff --git a/block/io.c b/block/io.c
68
index XXXXXXX..XXXXXXX 100644
162
index XXXXXXX..XXXXXXX 100644
69
--- a/block/io.c
163
--- a/block/io.c
70
+++ b/block/io.c
164
+++ b/block/io.c
71
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
165
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
166
}
167
}
168
169
-void bdrv_io_unplug(BlockDriverState *bs)
170
+void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
72
{
171
{
73
BdrvChild *child;
172
BdrvChild *child;
74
IO_CODE();
173
IO_CODE();
75
+ assert_bdrv_graph_readable();
174
@@ -XXX,XX +XXX,XX @@ void bdrv_io_unplug(BlockDriverState *bs)
76
77
QLIST_FOREACH(child, &bs->children, next) {
78
bdrv_co_io_plug(child->bs);
79
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
80
{
81
BdrvChild *child;
82
IO_CODE();
83
+ assert_bdrv_graph_readable();
84
85
assert(bs->io_plugged);
175
assert(bs->io_plugged);
86
if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
176
if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
177
BlockDriver *drv = bs->drv;
178
- if (drv && drv->bdrv_io_unplug) {
179
- drv->bdrv_io_unplug(bs);
180
+ if (drv && drv->bdrv_co_io_unplug) {
181
+ drv->bdrv_co_io_unplug(bs);
182
}
183
}
184
185
QLIST_FOREACH(child, &bs->children, next) {
186
- bdrv_io_unplug(child->bs);
187
+ bdrv_co_io_unplug(child->bs);
188
}
189
}
190
191
diff --git a/block/nvme.c b/block/nvme.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/block/nvme.c
194
+++ b/block/nvme.c
195
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs)
196
s->plugged = true;
197
}
198
199
-static void nvme_aio_unplug(BlockDriverState *bs)
200
+static void coroutine_fn nvme_co_io_unplug(BlockDriverState *bs)
201
{
202
BDRVNVMeState *s = bs->opaque;
203
assert(s->plugged);
204
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
205
.bdrv_attach_aio_context = nvme_attach_aio_context,
206
207
.bdrv_co_io_plug = nvme_co_io_plug,
208
- .bdrv_io_unplug = nvme_aio_unplug,
209
+ .bdrv_co_io_unplug = nvme_co_io_unplug,
210
211
.bdrv_register_buf = nvme_register_buf,
212
.bdrv_unregister_buf = nvme_unregister_buf,
87
--
213
--
88
2.39.2
214
2.38.1
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This adds GRAPH_RDLOCK annotations to declare that callers of
3
bdrv_is_inserted() is categorized as an I/O function, and it currently
4
bdrv_co_is_inserted() need to hold a reader lock for the graph.
4
doesn't run in a coroutine. We should let it take a graph rdlock since
5
5
it traverses the block nodes graph, which however is only possible in a
6
blk_is_inserted() is done as a co_wrapper_mixed_bdrv_rdlock (unlike most
6
coroutine.
7
other blk_* functions) because it is called a lot from other blk_co_*()
7
8
functions that already hold the lock. These calls go through
8
Therefore turn it into a co_wrapper to move the actual function into a
9
blk_is_available(), which becomes a co_wrapper_mixed_bdrv_rdlock, too,
9
coroutine where the lock can be taken.
10
for the same reason.
10
11
11
At the same time, add also blk_is_inserted as co_wrapper_mixed, since it
12
Functions that run in a coroutine and can call bdrv_co_is_available()
12
is called in both coroutine and non-coroutine contexts.
13
directly are changed to do so, which results in better TSA coverage.
13
14
Because now this function creates a new coroutine and polls, we need to
15
take the AioContext lock where it is missing, for the only reason that
16
internally c_w_mixed_bdrv_rdlock calls AIO_WAIT_WHILE and it expects to
17
release the AioContext lock. Once the rwlock is ultimated and placed in
18
every place it needs to be, we will poll using AIO_WAIT_WHILE_UNLOCKED
19
and remove the AioContext lock.
14
20
15
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
21
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Message-Id: <20230203152202.49054-19-kwolf@redhat.com>
23
Message-Id: <20230113204212.359076-5-kwolf@redhat.com>
18
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
24
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
26
---
21
include/block/block-io.h | 4 ++--
27
include/block/block-io.h | 5 ++++-
22
include/block/block_int-common.h | 3 ++-
28
include/block/block_int-common.h | 2 +-
23
include/sysemu/block-backend-io.h | 7 ++++---
29
include/sysemu/block-backend-io.h | 5 ++++-
24
block.c | 1 +
30
block.c | 8 ++++----
25
block/block-backend.c | 25 ++++++++++++++-----------
31
block/block-backend.c | 4 ++--
26
5 files changed, 23 insertions(+), 17 deletions(-)
32
block/file-posix.c | 8 ++++----
33
block/io.c | 12 ++++++------
34
blockdev.c | 8 +++++++-
35
8 files changed, 32 insertions(+), 20 deletions(-)
27
36
28
diff --git a/include/block/block-io.h b/include/block/block-io.h
37
diff --git a/include/block/block-io.h b/include/block/block-io.h
29
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block-io.h
39
--- a/include/block/block-io.h
31
+++ b/include/block/block-io.h
40
+++ b/include/block/block-io.h
32
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs);
41
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs);
42
bool bdrv_is_writable(BlockDriverState *bs);
33
bool bdrv_is_sg(BlockDriverState *bs);
43
bool bdrv_is_sg(BlockDriverState *bs);
34
int bdrv_get_flags(BlockDriverState *bs);
44
int bdrv_get_flags(BlockDriverState *bs);
35
45
-bool bdrv_is_inserted(BlockDriverState *bs);
36
-bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
46
+
37
-bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
47
+bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
38
+bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
48
+bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
39
+bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
49
+
40
50
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
41
void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
51
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
42
void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
52
const char *bdrv_get_format_name(BlockDriverState *bs);
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
53
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
44
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/block_int-common.h
55
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
56
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
57
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
58
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
49
59
50
/* removable device specific */
60
/* removable device specific */
51
- bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
61
- bool (*bdrv_is_inserted)(BlockDriverState *bs);
52
+ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
62
+ bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
53
+ BlockDriverState *bs);
63
void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag);
54
void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
64
void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
55
void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
56
65
57
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
66
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
58
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
59
--- a/include/sysemu/block-backend-io.h
68
--- a/include/sysemu/block-backend-io.h
60
+++ b/include/sysemu/block-backend-io.h
69
+++ b/include/sysemu/block-backend-io.h
61
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
70
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
71
62
void blk_inc_in_flight(BlockBackend *blk);
72
void blk_inc_in_flight(BlockBackend *blk);
63
void blk_dec_in_flight(BlockBackend *blk);
73
void blk_dec_in_flight(BlockBackend *blk);
64
74
-bool blk_is_inserted(BlockBackend *blk);
65
-bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
75
+
66
-bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
76
+bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
67
+bool coroutine_fn GRAPH_RDLOCK blk_co_is_inserted(BlockBackend *blk);
77
+bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
68
+bool co_wrapper_mixed_bdrv_rdlock blk_is_inserted(BlockBackend *blk);
78
+
69
79
bool blk_is_available(BlockBackend *blk);
70
-bool blk_is_available(BlockBackend *blk);
80
void blk_lock_medium(BlockBackend *blk, bool locked);
71
+bool coroutine_fn GRAPH_RDLOCK blk_co_is_available(BlockBackend *blk);
81
void blk_eject(BlockBackend *blk, bool eject_flag);
72
+bool co_wrapper_mixed_bdrv_rdlock blk_is_available(BlockBackend *blk);
73
74
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked);
75
void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked);
76
diff --git a/block.c b/block.c
82
diff --git a/block.c b/block.c
77
index XXXXXXX..XXXXXXX 100644
83
index XXXXXXX..XXXXXXX 100644
78
--- a/block.c
84
--- a/block.c
79
+++ b/block.c
85
+++ b/block.c
80
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
86
@@ -XXX,XX +XXX,XX @@ out:
87
/**
88
* Return TRUE if the media is present
89
*/
90
-bool bdrv_is_inserted(BlockDriverState *bs)
91
+bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
92
{
81
BlockDriver *drv = bs->drv;
93
BlockDriver *drv = bs->drv;
82
BdrvChild *child;
94
BdrvChild *child;
83
IO_CODE();
95
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_inserted(BlockDriverState *bs)
84
+ assert_bdrv_graph_readable();
85
86
if (!drv) {
96
if (!drv) {
87
return false;
97
return false;
98
}
99
- if (drv->bdrv_is_inserted) {
100
- return drv->bdrv_is_inserted(bs);
101
+ if (drv->bdrv_co_is_inserted) {
102
+ return drv->bdrv_co_is_inserted(bs);
103
}
104
QLIST_FOREACH(child, &bs->children, next) {
105
- if (!bdrv_is_inserted(child->bs)) {
106
+ if (!bdrv_co_is_inserted(child->bs)) {
107
return false;
108
}
109
}
88
diff --git a/block/block-backend.c b/block/block-backend.c
110
diff --git a/block/block-backend.c b/block/block-backend.c
89
index XXXXXXX..XXXXXXX 100644
111
index XXXXXXX..XXXXXXX 100644
90
--- a/block/block-backend.c
112
--- a/block/block-backend.c
91
+++ b/block/block-backend.c
113
+++ b/block/block-backend.c
92
@@ -XXX,XX +XXX,XX @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
114
@@ -XXX,XX +XXX,XX @@ void blk_activate(BlockBackend *blk, Error **errp)
93
blk->disable_request_queuing = disable;
115
bdrv_activate(bs, errp);
94
}
116
}
95
117
96
-static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
118
-bool blk_is_inserted(BlockBackend *blk)
97
- int64_t offset, int64_t bytes)
119
+bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
98
+static int coroutine_fn GRAPH_RDLOCK
99
+blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes)
100
{
101
int64_t len;
102
103
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
104
return -EIO;
105
}
106
107
- if (!blk_is_available(blk)) {
108
+ if (!blk_co_is_available(blk)) {
109
return -ENOMEDIUM;
110
}
111
112
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
113
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
114
{
115
IO_CODE();
116
+ GRAPH_RDLOCK_GUARD();
117
118
- if (!blk_is_available(blk)) {
119
+ if (!blk_co_is_available(blk)) {
120
return -ENOMEDIUM;
121
}
122
123
@@ -XXX,XX +XXX,XX @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
124
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
125
{
126
IO_CODE();
127
+ GRAPH_RDLOCK_GUARD();
128
129
- if (!blk_is_available(blk)) {
130
+ if (!blk_co_is_available(blk)) {
131
return -ENOMEDIUM;
132
}
133
134
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
135
blk_wait_while_drained(blk);
136
GRAPH_RDLOCK_GUARD();
137
138
- if (!blk_is_available(blk)) {
139
+ if (!blk_co_is_available(blk)) {
140
return -ENOMEDIUM;
141
}
142
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
144
blk_wait_while_drained(blk);
145
GRAPH_RDLOCK_GUARD();
146
147
- if (!blk_is_available(blk)) {
148
+ if (!blk_co_is_available(blk)) {
149
return -ENOMEDIUM;
150
}
151
152
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
153
{
120
{
154
BlockDriverState *bs = blk_bs(blk);
121
BlockDriverState *bs = blk_bs(blk);
155
IO_CODE();
122
IO_CODE();
156
+ assert_bdrv_graph_readable();
123
157
124
- return bs && bdrv_is_inserted(bs);
158
return bs && bdrv_co_is_inserted(bs);
125
+ return bs && bdrv_co_is_inserted(bs);
159
}
126
}
160
127
161
-bool blk_is_available(BlockBackend *blk)
128
bool blk_is_available(BlockBackend *blk)
162
+bool coroutine_fn blk_co_is_available(BlockBackend *blk)
129
diff --git a/block/file-posix.c b/block/file-posix.c
163
{
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/file-posix.c
132
+++ b/block/file-posix.c
133
@@ -XXX,XX +XXX,XX @@ out:
134
return prio;
135
}
136
137
-static bool cdrom_is_inserted(BlockDriverState *bs)
138
+static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
139
{
140
BDRVRawState *s = bs->opaque;
141
int ret;
142
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
143
= raw_get_allocated_file_size,
144
145
/* removable device support */
146
- .bdrv_is_inserted = cdrom_is_inserted,
147
+ .bdrv_co_is_inserted = cdrom_co_is_inserted,
148
.bdrv_eject = cdrom_eject,
149
.bdrv_lock_medium = cdrom_lock_medium,
150
151
@@ -XXX,XX +XXX,XX @@ static int cdrom_reopen(BlockDriverState *bs)
152
return 0;
153
}
154
155
-static bool cdrom_is_inserted(BlockDriverState *bs)
156
+static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
157
{
158
return raw_getlength(bs) > 0;
159
}
160
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
161
= raw_get_allocated_file_size,
162
163
/* removable device support */
164
- .bdrv_is_inserted = cdrom_is_inserted,
165
+ .bdrv_co_is_inserted = cdrom_co_is_inserted,
166
.bdrv_eject = cdrom_eject,
167
.bdrv_lock_medium = cdrom_lock_medium,
168
};
169
diff --git a/block/io.c b/block/io.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/block/io.c
172
+++ b/block/io.c
173
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
174
175
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
176
177
- if (!bdrv_is_inserted(bs)) {
178
+ if (!bdrv_co_is_inserted(bs)) {
179
return -ENOMEDIUM;
180
}
181
182
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
183
184
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
185
186
- if (!bdrv_is_inserted(bs)) {
187
+ if (!bdrv_co_is_inserted(bs)) {
188
return -ENOMEDIUM;
189
}
190
191
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
192
193
bdrv_inc_in_flight(bs);
194
195
- if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
196
+ if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
197
bdrv_is_sg(bs)) {
198
goto early_exit;
199
}
200
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
201
BlockDriverState *bs = child->bs;
164
IO_CODE();
202
IO_CODE();
165
- return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
203
166
+ return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk);
204
- if (!bs || !bs->drv || !bdrv_is_inserted(bs)) {
167
}
205
+ if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
168
206
return -ENOMEDIUM;
169
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
207
}
170
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
208
171
{
209
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(
172
IO_OR_GS_CODE();
210
assert(!(read_flags & BDRV_REQ_NO_WAIT));
173
GRAPH_RDLOCK_GUARD();
211
assert(!(write_flags & BDRV_REQ_NO_WAIT));
174
- if (!blk_is_available(blk)) {
212
175
+ if (!blk_co_is_available(blk)) {
213
- if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) {
176
error_setg(errp, "No medium inserted");
214
+ if (!dst || !dst->bs || !bdrv_co_is_inserted(dst->bs)) {
177
return -ENOMEDIUM;
215
return -ENOMEDIUM;
178
}
216
}
179
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
217
ret = bdrv_check_request32(dst_offset, bytes, NULL, 0);
180
{
218
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(
181
int r;
219
return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags);
182
IO_CODE();
220
}
183
+ GRAPH_RDLOCK_GUARD();
221
184
222
- if (!src || !src->bs || !bdrv_is_inserted(src->bs)) {
185
r = blk_check_byte_request(blk_in, off_in, bytes);
223
+ if (!src || !src->bs || !bdrv_co_is_inserted(src->bs)) {
186
if (r) {
224
return -ENOMEDIUM;
187
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
225
}
188
return r;
226
ret = bdrv_check_request32(src_offset, bytes, NULL, 0);
189
}
227
diff --git a/blockdev.c b/blockdev.c
190
228
index XXXXXXX..XXXXXXX 100644
191
- GRAPH_RDLOCK_GUARD();
229
--- a/blockdev.c
192
return bdrv_co_copy_range(blk_in->root, off_in,
230
+++ b/blockdev.c
193
blk_out->root, off_out,
231
@@ -XXX,XX +XXX,XX @@ fail:
194
bytes, read_flags, write_flags);
232
static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
233
{
234
BlockDriverState *bs;
235
+ AioContext *aio_context;
236
237
bs = bdrv_lookup_bs(name, name, errp);
238
if (bs == NULL) {
239
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
240
return NULL;
241
}
242
243
+ aio_context = bdrv_get_aio_context(bs);
244
+ aio_context_acquire(aio_context);
245
+
246
if (!bdrv_is_inserted(bs)) {
247
error_setg(errp, "Device has no medium");
248
- return NULL;
249
+ bs = NULL;
250
}
251
252
+ aio_context_release(aio_context);
253
+
254
return bs;
255
}
256
195
--
257
--
196
2.39.2
258
2.38.1
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This adds GRAPH_RDLOCK annotations to declare that callers of
3
The name is not good, not the least because we are going to convert this
4
bdrv_co_copy_range() need to hold a reader lock for the graph.
4
to a generated co_wrapper, which adds a _co infix after the first part
5
of the name.
6
7
No functional change intended.
5
8
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20230203152202.49054-15-kwolf@redhat.com>
11
Message-Id: <20230113204212.359076-6-kwolf@redhat.com>
9
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
14
---
12
include/block/block-io.h | 9 +++++----
15
include/block/block_int-io.h | 2 +-
13
include/block/block_int-common.h | 24 ++++++++----------------
16
block.c | 8 ++++----
14
include/block/block_int-io.h | 20 ++++++++++----------
17
block/io.c | 8 +++++---
15
block/block-backend.c | 2 ++
18
3 files changed, 10 insertions(+), 8 deletions(-)
16
block/file-posix.c | 16 +++++++---------
17
block/io.c | 7 +++++--
18
block/iscsi.c | 28 ++++++++++++----------------
19
block/qcow2.c | 5 ++---
20
block/raw-format.c | 28 ++++++++++++----------------
21
qemu-img.c | 4 +++-
22
10 files changed, 66 insertions(+), 77 deletions(-)
23
19
24
diff --git a/include/block/block-io.h b/include/block/block-io.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block-io.h
27
+++ b/include/block/block-io.h
28
@@ -XXX,XX +XXX,XX @@ bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs,
29
*
30
* Returns: 0 if succeeded; negative error code if failed.
31
**/
32
-int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
33
- BdrvChild *dst, int64_t dst_offset,
34
- int64_t bytes, BdrvRequestFlags read_flags,
35
- BdrvRequestFlags write_flags);
36
+int coroutine_fn GRAPH_RDLOCK
37
+bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
38
+ BdrvChild *dst, int64_t dst_offset,
39
+ int64_t bytes, BdrvRequestFlags read_flags,
40
+ BdrvRequestFlags write_flags);
41
42
/*
43
* "I/O or GS" API functions. These functions can run without
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
* See the comment of bdrv_co_copy_range for the parameter and return value
50
* semantics.
51
*/
52
- int coroutine_fn (*bdrv_co_copy_range_from)(BlockDriverState *bs,
53
- BdrvChild *src,
54
- int64_t offset,
55
- BdrvChild *dst,
56
- int64_t dst_offset,
57
- int64_t bytes,
58
- BdrvRequestFlags read_flags,
59
- BdrvRequestFlags write_flags);
60
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_from)(
61
+ BlockDriverState *bs, BdrvChild *src, int64_t offset,
62
+ BdrvChild *dst, int64_t dst_offset, int64_t bytes,
63
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags);
64
65
/*
66
* Map [offset, offset + nbytes) range onto a child of bs to copy data to,
67
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
68
* See the comment of bdrv_co_copy_range for the parameter and return value
69
* semantics.
70
*/
71
- int coroutine_fn (*bdrv_co_copy_range_to)(BlockDriverState *bs,
72
- BdrvChild *src,
73
- int64_t src_offset,
74
- BdrvChild *dst,
75
- int64_t dst_offset,
76
- int64_t bytes,
77
- BdrvRequestFlags read_flags,
78
- BdrvRequestFlags write_flags);
79
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_to)(
80
+ BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
81
+ BdrvChild *dst, int64_t dst_offset, int64_t bytes,
82
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags);
83
84
/*
85
* Building block for bdrv_block_status[_above] and
86
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
20
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
87
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
88
--- a/include/block/block_int-io.h
22
--- a/include/block/block_int-io.h
89
+++ b/include/block/block_int-io.h
23
+++ b/include/block/block_int-io.h
90
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
24
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
91
void bdrv_inc_in_flight(BlockDriverState *bs);
25
BdrvRequestFlags read_flags,
92
void bdrv_dec_in_flight(BlockDriverState *bs);
26
BdrvRequestFlags write_flags);
93
27
94
-int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
28
-int refresh_total_sectors(BlockDriverState *bs, int64_t hint);
95
- BdrvChild *dst, int64_t dst_offset,
29
+int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
96
- int64_t bytes,
30
97
- BdrvRequestFlags read_flags,
31
BdrvChild *bdrv_cow_child(BlockDriverState *bs);
98
- BdrvRequestFlags write_flags);
32
BdrvChild *bdrv_filter_child(BlockDriverState *bs);
99
-int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
33
diff --git a/block.c b/block.c
100
- BdrvChild *dst, int64_t dst_offset,
101
- int64_t bytes,
102
- BdrvRequestFlags read_flags,
103
- BdrvRequestFlags write_flags);
104
+int coroutine_fn GRAPH_RDLOCK
105
+bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
106
+ BdrvChild *dst, int64_t dst_offset,
107
+ int64_t bytes, BdrvRequestFlags read_flags,
108
+ BdrvRequestFlags write_flags);
109
+int coroutine_fn GRAPH_RDLOCK
110
+bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
111
+ BdrvChild *dst, int64_t dst_offset,
112
+ int64_t bytes, BdrvRequestFlags read_flags,
113
+ BdrvRequestFlags write_flags);
114
115
int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
116
int64_t hint);
117
diff --git a/block/block-backend.c b/block/block-backend.c
118
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
119
--- a/block/block-backend.c
35
--- a/block.c
120
+++ b/block/block-backend.c
36
+++ b/block.c
121
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
37
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
122
if (r) {
38
* Set the current 'total_sectors' value
123
return r;
39
* Return 0 on success, -errno on error.
124
}
40
*/
125
+
41
-int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
126
+ GRAPH_RDLOCK_GUARD();
42
+int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint)
127
return bdrv_co_copy_range(blk_in->root, off_in,
128
blk_out->root, off_out,
129
bytes, read_flags, write_flags);
130
diff --git a/block/file-posix.c b/block/file-posix.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/file-posix.c
133
+++ b/block/file-posix.c
134
@@ -XXX,XX +XXX,XX @@ static void raw_abort_perm_update(BlockDriverState *bs)
135
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
136
}
137
138
-static int coroutine_fn raw_co_copy_range_from(
139
+static int coroutine_fn GRAPH_RDLOCK raw_co_copy_range_from(
140
BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
141
BdrvChild *dst, int64_t dst_offset, int64_t bytes,
142
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags)
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(
144
read_flags, write_flags);
145
}
146
147
-static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
148
- BdrvChild *src,
149
- int64_t src_offset,
150
- BdrvChild *dst,
151
- int64_t dst_offset,
152
- int64_t bytes,
153
- BdrvRequestFlags read_flags,
154
- BdrvRequestFlags write_flags)
155
+static int coroutine_fn GRAPH_RDLOCK
156
+raw_co_copy_range_to(BlockDriverState *bs,
157
+ BdrvChild *src, int64_t src_offset,
158
+ BdrvChild *dst, int64_t dst_offset,
159
+ int64_t bytes, BdrvRequestFlags read_flags,
160
+ BdrvRequestFlags write_flags)
161
{
43
{
162
RawPosixAIOData acb;
44
BlockDriver *drv = bs->drv;
163
BDRVRawState *s = bs->opaque;
45
IO_CODE();
46
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
47
bs->supported_read_flags |= BDRV_REQ_REGISTERED_BUF;
48
bs->supported_write_flags |= BDRV_REQ_REGISTERED_BUF;
49
50
- ret = refresh_total_sectors(bs, bs->total_sectors);
51
+ ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
52
if (ret < 0) {
53
error_setg_errno(errp, -ret, "Could not refresh total sector count");
54
return ret;
55
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
56
return -ENOMEDIUM;
57
58
if (drv->has_variable_length) {
59
- int ret = refresh_total_sectors(bs, bs->total_sectors);
60
+ int ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
61
if (ret < 0) {
62
return ret;
63
}
64
@@ -XXX,XX +XXX,XX @@ int bdrv_activate(BlockDriverState *bs, Error **errp)
65
bdrv_dirty_bitmap_skip_store(bm, false);
66
}
67
68
- ret = refresh_total_sectors(bs, bs->total_sectors);
69
+ ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
70
if (ret < 0) {
71
bs->open_flags |= BDRV_O_INACTIVE;
72
error_setg_errno(errp, -ret, "Could not refresh total sector count");
164
diff --git a/block/io.c b/block/io.c
73
diff --git a/block/io.c b/block/io.c
165
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
166
--- a/block/io.c
75
--- a/block/io.c
167
+++ b/block/io.c
76
+++ b/block/io.c
168
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
77
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
169
{
78
goto out;
170
BdrvTrackedRequest req;
79
}
171
int ret;
80
172
+ assert_bdrv_graph_readable();
81
- ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
173
82
+ ret = bdrv_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
174
/* TODO We can support BDRV_REQ_NO_FALLBACK here */
83
if (ret < 0) {
175
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
84
error_setg_errno(errp, -ret, "Could not refresh total sector count");
176
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
85
} else {
177
BdrvRequestFlags write_flags)
86
offset = bs->total_sectors * BDRV_SECTOR_SIZE;
178
{
87
}
179
IO_CODE();
88
- /* It's possible that truncation succeeded but refresh_total_sectors
180
- assume_graph_lock(); /* FIXME */
89
+ /*
181
+ assert_bdrv_graph_readable();
90
+ * It's possible that truncation succeeded but bdrv_refresh_total_sectors
182
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
91
* failed, but the latter doesn't affect how we should finish the request.
183
read_flags, write_flags);
92
- * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */
184
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
93
+ * Pass 0 as the last parameter so that dirty bitmaps etc. are handled.
185
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
94
+ */
186
BdrvRequestFlags write_flags)
95
bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0);
187
{
96
188
IO_CODE();
97
out:
189
- assume_graph_lock(); /* FIXME */
190
+ assert_bdrv_graph_readable();
191
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
192
read_flags, write_flags);
193
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
194
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
195
BdrvRequestFlags write_flags)
196
{
197
IO_CODE();
198
+ assert_bdrv_graph_readable();
199
+
200
return bdrv_co_copy_range_from(src, src_offset,
201
dst, dst_offset,
202
bytes, read_flags, write_flags);
203
diff --git a/block/iscsi.c b/block/iscsi.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/iscsi.c
206
+++ b/block/iscsi.c
207
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn iscsi_co_invalidate_cache(BlockDriverState *bs,
208
iscsi_allocmap_invalidate(iscsilun);
209
}
210
211
-static int coroutine_fn iscsi_co_copy_range_from(BlockDriverState *bs,
212
- BdrvChild *src,
213
- int64_t src_offset,
214
- BdrvChild *dst,
215
- int64_t dst_offset,
216
- int64_t bytes,
217
- BdrvRequestFlags read_flags,
218
- BdrvRequestFlags write_flags)
219
+static int coroutine_fn GRAPH_RDLOCK
220
+iscsi_co_copy_range_from(BlockDriverState *bs,
221
+ BdrvChild *src, int64_t src_offset,
222
+ BdrvChild *dst, int64_t dst_offset,
223
+ int64_t bytes, BdrvRequestFlags read_flags,
224
+ BdrvRequestFlags write_flags)
225
{
226
return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
227
read_flags, write_flags);
228
@@ -XXX,XX +XXX,XX @@ static void iscsi_xcopy_data(struct iscsi_data *data,
229
src_lba, dst_lba);
230
}
231
232
-static int coroutine_fn iscsi_co_copy_range_to(BlockDriverState *bs,
233
- BdrvChild *src,
234
- int64_t src_offset,
235
- BdrvChild *dst,
236
- int64_t dst_offset,
237
- int64_t bytes,
238
- BdrvRequestFlags read_flags,
239
- BdrvRequestFlags write_flags)
240
+static int coroutine_fn GRAPH_RDLOCK
241
+iscsi_co_copy_range_to(BlockDriverState *bs,
242
+ BdrvChild *src, int64_t src_offset,
243
+ BdrvChild *dst, int64_t dst_offset,
244
+ int64_t bytes, BdrvRequestFlags read_flags,
245
+ BdrvRequestFlags write_flags)
246
{
247
IscsiLun *dst_lun = dst->bs->opaque;
248
IscsiLun *src_lun;
249
diff --git a/block/qcow2.c b/block/qcow2.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/block/qcow2.c
252
+++ b/block/qcow2.c
253
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
254
return ret;
255
}
256
257
-static int coroutine_fn
258
+static int coroutine_fn GRAPH_RDLOCK
259
qcow2_co_copy_range_from(BlockDriverState *bs,
260
BdrvChild *src, int64_t src_offset,
261
BdrvChild *dst, int64_t dst_offset,
262
@@ -XXX,XX +XXX,XX @@ out:
263
return ret;
264
}
265
266
-static int coroutine_fn
267
+static int coroutine_fn GRAPH_RDLOCK
268
qcow2_co_copy_range_to(BlockDriverState *bs,
269
BdrvChild *src, int64_t src_offset,
270
BdrvChild *dst, int64_t dst_offset,
271
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
272
uint64_t host_offset;
273
QCowL2Meta *l2meta = NULL;
274
275
- assume_graph_lock(); /* FIXME */
276
assert(!bs->encrypted);
277
278
qemu_co_mutex_lock(&s->lock);
279
diff --git a/block/raw-format.c b/block/raw-format.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/block/raw-format.c
282
+++ b/block/raw-format.c
283
@@ -XXX,XX +XXX,XX @@ static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
284
return bdrv_probe_geometry(bs->file->bs, geo);
285
}
286
287
-static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
288
- BdrvChild *src,
289
- int64_t src_offset,
290
- BdrvChild *dst,
291
- int64_t dst_offset,
292
- int64_t bytes,
293
- BdrvRequestFlags read_flags,
294
- BdrvRequestFlags write_flags)
295
+static int coroutine_fn GRAPH_RDLOCK
296
+raw_co_copy_range_from(BlockDriverState *bs,
297
+ BdrvChild *src, int64_t src_offset,
298
+ BdrvChild *dst, int64_t dst_offset,
299
+ int64_t bytes, BdrvRequestFlags read_flags,
300
+ BdrvRequestFlags write_flags)
301
{
302
int ret;
303
304
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
305
bytes, read_flags, write_flags);
306
}
307
308
-static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
309
- BdrvChild *src,
310
- int64_t src_offset,
311
- BdrvChild *dst,
312
- int64_t dst_offset,
313
- int64_t bytes,
314
- BdrvRequestFlags read_flags,
315
- BdrvRequestFlags write_flags)
316
+static int coroutine_fn GRAPH_RDLOCK
317
+raw_co_copy_range_to(BlockDriverState *bs,
318
+ BdrvChild *src, int64_t src_offset,
319
+ BdrvChild *dst, int64_t dst_offset,
320
+ int64_t bytes, BdrvRequestFlags read_flags,
321
+ BdrvRequestFlags write_flags)
322
{
323
int ret;
324
325
diff --git a/qemu-img.c b/qemu-img.c
326
index XXXXXXX..XXXXXXX 100644
327
--- a/qemu-img.c
328
+++ b/qemu-img.c
329
@@ -XXX,XX +XXX,XX @@ retry:
330
331
if (s->ret == -EINPROGRESS) {
332
if (copy_range) {
333
- ret = convert_co_copy_range(s, sector_num, n);
334
+ WITH_GRAPH_RDLOCK_GUARD() {
335
+ ret = convert_co_copy_range(s, sector_num, n);
336
+ }
337
if (ret) {
338
s->copy_range = false;
339
goto retry;
340
--
98
--
341
2.39.2
99
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_refresh_total_sectors() need to hold a reader lock for the
3
graph.
4
2
3
BlockDriver->bdrv_getlength is categorized as IO callback, and it
4
currently doesn't run in a coroutine. We should let it take a graph
5
rdlock since the callback traverses the block nodes graph, which however
6
is only possible in a coroutine.
7
8
Therefore turn it into a co_wrapper to move the actual function into a
9
coroutine where the lock can be taken.
10
11
Because now this function creates a new coroutine and polls, we need to
12
take the AioContext lock where it is missing, for the only reason that
13
internally co_wrapper calls AIO_WAIT_WHILE and it expects to release the
14
AioContext lock.
15
16
This is especially messy when a co_wrapper creates a coroutine and polls
17
in bdrv_open_driver, because this function has so many callers in so
18
many context that it can easily lead to deadlocks. Therefore the new
19
rule for bdrv_open_driver is that the caller must always hold the
20
AioContext lock of the given bs (except if it is a coroutine), because
21
the function calls bdrv_refresh_total_sectors() which is now a
22
co_wrapper.
23
24
Once the rwlock is ultimated and placed in every place it needs to be,
25
we will poll using AIO_WAIT_WHILE_UNLOCKED and remove the AioContext
26
lock.
27
28
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20230203152202.49054-24-kwolf@redhat.com>
30
Message-Id: <20230113204212.359076-7-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
31
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
32
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
33
---
10
include/block/block-io.h | 8 ++++----
34
include/block/block-io.h | 8 ++++--
11
include/block/block_int-common.h | 4 +++-
35
include/block/block_int-common.h | 2 +-
12
include/block/block_int-io.h | 7 ++++---
36
include/block/block_int-io.h | 5 +++-
13
block.c | 3 +++
37
include/sysemu/block-backend-io.h | 10 ++++++--
14
block/blkdebug.c | 3 ++-
38
block.c | 32 +++++++++++++++++------
15
block/blklogwrites.c | 3 ++-
39
block/blkdebug.c | 6 ++---
16
block/blkreplay.c | 3 ++-
40
block/blkio.c | 6 ++---
17
block/blkverify.c | 3 ++-
41
block/blklogwrites.c | 6 ++---
18
block/copy-on-read.c | 2 +-
42
block/blkreplay.c | 6 ++---
19
block/crypto.c | 3 ++-
43
block/blkverify.c | 6 ++---
20
block/filter-compress.c | 3 ++-
44
block/block-backend.c | 10 +++++---
21
block/mirror.c | 3 +++
45
block/commit.c | 4 +--
22
block/preallocate.c | 3 ++-
46
block/copy-on-read.c | 6 ++---
23
block/quorum.c | 3 ++-
47
block/crypto.c | 6 ++---
24
block/raw-format.c | 3 ++-
48
block/curl.c | 10 ++++----
25
block/replication.c | 3 ++-
49
block/file-posix.c | 42 +++++++++++++++----------------
26
block/stream.c | 8 +++++---
50
block/file-win32.c | 8 +++---
27
block/throttle.c | 3 ++-
51
block/filter-compress.c | 6 ++---
28
18 files changed, 45 insertions(+), 23 deletions(-)
52
block/gluster.c | 12 ++++-----
53
block/iscsi.c | 10 ++++----
54
block/mirror.c | 4 +--
55
block/nbd.c | 8 +++---
56
block/null.c | 6 ++---
57
block/nvme.c | 6 ++---
58
block/preallocate.c | 10 ++++----
59
block/qed.c | 4 +--
60
block/quorum.c | 8 +++---
61
block/raw-format.c | 6 ++---
62
block/rbd.c | 4 +--
63
block/replication.c | 6 ++---
64
block/ssh.c | 4 +--
65
block/throttle.c | 6 ++---
66
hw/scsi/scsi-disk.c | 5 ++++
67
tests/unit/test-block-iothread.c | 3 +++
68
block/meson.build | 1 +
69
35 files changed, 161 insertions(+), 121 deletions(-)
29
70
30
diff --git a/include/block/block-io.h b/include/block/block-io.h
71
diff --git a/include/block/block-io.h b/include/block/block-io.h
31
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block-io.h
73
--- a/include/block/block-io.h
33
+++ b/include/block/block-io.h
74
+++ b/include/block/block-io.h
34
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK
75
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
35
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
76
PreallocMode prealloc, BdrvRequestFlags flags,
36
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
77
Error **errp);
37
78
38
-int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
79
-int64_t bdrv_nb_sectors(BlockDriverState *bs);
39
-int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
80
-int64_t bdrv_getlength(BlockDriverState *bs);
40
+int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_nb_sectors(BlockDriverState *bs);
81
+int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
41
+int64_t co_wrapper_mixed_bdrv_rdlock bdrv_nb_sectors(BlockDriverState *bs);
82
+int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
42
83
+
43
-int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
84
+int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
44
-int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
85
+int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
45
+int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_getlength(BlockDriverState *bs);
86
+
46
+int64_t co_wrapper_mixed_bdrv_rdlock bdrv_getlength(BlockDriverState *bs);
87
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
47
88
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
48
int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
89
BlockDriverState *in_bs, Error **errp);
49
int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
50
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
90
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
51
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block_int-common.h
92
--- a/include/block/block_int-common.h
53
+++ b/include/block/block_int-common.h
93
+++ b/include/block/block_int-common.h
54
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
94
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
55
BlockDriverState *bs, int64_t offset, bool exact,
95
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
56
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
96
bool exact, PreallocMode prealloc,
57
97
BdrvRequestFlags flags, Error **errp);
58
- int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
98
- int64_t (*bdrv_getlength)(BlockDriverState *bs);
59
+ int64_t coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_getlength)(
99
+ int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
60
+ BlockDriverState *bs);
100
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
61
+
101
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
62
int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
102
Error **errp);
63
BlockDriverState *bs);
64
65
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
103
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
66
index XXXXXXX..XXXXXXX 100644
104
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/block_int-io.h
105
--- a/include/block/block_int-io.h
68
+++ b/include/block/block_int-io.h
106
+++ b/include/block/block_int-io.h
69
@@ -XXX,XX +XXX,XX @@ bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
107
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
70
int64_t bytes, BdrvRequestFlags read_flags,
108
BdrvRequestFlags read_flags,
71
BdrvRequestFlags write_flags);
109
BdrvRequestFlags write_flags);
72
110
73
-int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
111
-int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
74
- int64_t hint);
112
+int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
75
-int co_wrapper_mixed
113
+ int64_t hint);
76
+int coroutine_fn GRAPH_RDLOCK
114
+int co_wrapper_mixed
77
+bdrv_co_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
115
+bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
116
117
BdrvChild *bdrv_cow_child(BlockDriverState *bs);
118
BdrvChild *bdrv_filter_child(BlockDriverState *bs);
119
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
120
index XXXXXXX..XXXXXXX 100644
121
--- a/include/sysemu/block-backend-io.h
122
+++ b/include/sysemu/block-backend-io.h
123
@@ -XXX,XX +XXX,XX @@ bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
124
bool blk_is_available(BlockBackend *blk);
125
void blk_lock_medium(BlockBackend *blk, bool locked);
126
void blk_eject(BlockBackend *blk, bool eject_flag);
127
-int64_t blk_getlength(BlockBackend *blk);
78
+
128
+
79
+int co_wrapper_mixed_bdrv_rdlock
129
+int64_t coroutine_fn blk_co_getlength(BlockBackend *blk);
80
bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
130
+int64_t co_wrapper_mixed blk_getlength(BlockBackend *blk);
81
131
+
82
BdrvChild *bdrv_cow_child(BlockDriverState *bs);
132
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr);
133
-int64_t blk_nb_sectors(BlockBackend *blk);
134
+
135
+int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk);
136
+int64_t co_wrapper_mixed blk_nb_sectors(BlockBackend *blk);
137
+
138
void *blk_try_blockalign(BlockBackend *blk, size_t size);
139
void *blk_blockalign(BlockBackend *blk, size_t size);
140
bool blk_is_writable(BlockBackend *blk);
83
diff --git a/block.c b/block.c
141
diff --git a/block.c b/block.c
84
index XXXXXXX..XXXXXXX 100644
142
index XXXXXXX..XXXXXXX 100644
85
--- a/block.c
143
--- a/block.c
86
+++ b/block.c
144
+++ b/block.c
87
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
145
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
146
* Set the current 'total_sectors' value
147
* Return 0 on success, -errno on error.
148
*/
149
-int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint)
150
+int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
151
+ int64_t hint)
88
{
152
{
89
BlockDriver *drv = bs->drv;
153
BlockDriver *drv = bs->drv;
90
IO_CODE();
154
IO_CODE();
91
+ assert_bdrv_graph_readable();
155
@@ -XXX,XX +XXX,XX @@ int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint)
92
93
if (!drv) {
94
return -ENOMEDIUM;
156
return -ENOMEDIUM;
95
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
157
}
158
159
- /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
160
+ /* Do not attempt drv->bdrv_co_getlength() on scsi-generic devices */
161
if (bdrv_is_sg(bs))
162
return 0;
163
164
/* query actual device if possible, otherwise just trust the hint */
165
- if (drv->bdrv_getlength) {
166
- int64_t length = drv->bdrv_getlength(bs);
167
+ if (drv->bdrv_co_getlength) {
168
+ int64_t length = drv->bdrv_co_getlength(bs);
169
if (length < 0) {
170
return length;
171
}
172
@@ -XXX,XX +XXX,XX @@ out:
173
g_free(gen_node_name);
174
}
175
176
+/*
177
+ * The caller must always hold @bs AioContext lock, because this function calls
178
+ * bdrv_refresh_total_sectors() which polls when called from non-coroutine
179
+ * context.
180
+ */
181
static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
182
const char *node_name, QDict *options,
183
int open_flags, Error **errp)
184
@@ -XXX,XX +XXX,XX @@ out:
185
* The reference parameter may be used to specify an existing block device which
186
* should be opened. If specified, neither options nor a filename may be given,
187
* nor can an existing BDS be reused (that is, *pbs has to be NULL).
188
+ *
189
+ * The caller must always hold @filename AioContext lock, because this
190
+ * function eventually calls bdrv_refresh_total_sectors() which polls
191
+ * when called from non-coroutine context.
192
*/
193
static BlockDriverState *bdrv_open_inherit(const char *filename,
194
const char *reference,
195
@@ -XXX,XX +XXX,XX @@ close_and_fail:
196
return NULL;
197
}
198
199
+/*
200
+ * The caller must always hold @filename AioContext lock, because this
201
+ * function eventually calls bdrv_refresh_total_sectors() which polls
202
+ * when called from non-coroutine context.
203
+ */
204
BlockDriverState *bdrv_open(const char *filename, const char *reference,
205
QDict *options, int flags, Error **errp)
206
{
207
@@ -XXX,XX +XXX,XX @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
208
/**
209
* Return number of sectors on success, -errno on error.
210
*/
211
-int64_t bdrv_nb_sectors(BlockDriverState *bs)
212
+int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
96
{
213
{
97
BlockDriver *drv = bs->drv;
214
BlockDriver *drv = bs->drv;
98
IO_CODE();
215
IO_CODE();
99
+ assert_bdrv_graph_readable();
216
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
100
101
if (!drv)
102
return -ENOMEDIUM;
217
return -ENOMEDIUM;
103
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
218
104
{
219
if (drv->has_variable_length) {
105
int64_t ret;
220
- int ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
221
+ int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
222
if (ret < 0) {
223
return ret;
224
}
225
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_nb_sectors(BlockDriverState *bs)
226
* Return length in bytes on success, -errno on error.
227
* The length is always a multiple of BDRV_SECTOR_SIZE.
228
*/
229
-int64_t bdrv_getlength(BlockDriverState *bs)
230
+int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
231
{
232
- int64_t ret = bdrv_nb_sectors(bs);
233
+ int64_t ret;
106
IO_CODE();
234
IO_CODE();
107
+ assert_bdrv_graph_readable();
235
108
236
+ ret = bdrv_co_nb_sectors(bs);
109
ret = bdrv_co_nb_sectors(bs);
110
if (ret < 0) {
237
if (ret < 0) {
238
return ret;
239
}
111
diff --git a/block/blkdebug.c b/block/blkdebug.c
240
diff --git a/block/blkdebug.c b/block/blkdebug.c
112
index XXXXXXX..XXXXXXX 100644
241
index XXXXXXX..XXXXXXX 100644
113
--- a/block/blkdebug.c
242
--- a/block/blkdebug.c
114
+++ b/block/blkdebug.c
243
+++ b/block/blkdebug.c
115
@@ -XXX,XX +XXX,XX @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
244
@@ -XXX,XX +XXX,XX @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
116
return false;
245
return false;
117
}
246
}
118
247
119
-static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
248
-static int64_t blkdebug_getlength(BlockDriverState *bs)
120
+static int64_t coroutine_fn GRAPH_RDLOCK
249
+static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
121
+blkdebug_co_getlength(BlockDriverState *bs)
250
{
122
{
251
- return bdrv_getlength(bs->file->bs);
123
return bdrv_co_getlength(bs->file->bs);
252
+ return bdrv_co_getlength(bs->file->bs);
124
}
253
}
254
255
static void blkdebug_refresh_filename(BlockDriverState *bs)
256
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
257
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
258
.bdrv_child_perm = blkdebug_child_perm,
259
260
- .bdrv_getlength = blkdebug_getlength,
261
+ .bdrv_co_getlength = blkdebug_co_getlength,
262
.bdrv_refresh_filename = blkdebug_refresh_filename,
263
.bdrv_refresh_limits = blkdebug_refresh_limits,
264
265
diff --git a/block/blkio.c b/block/blkio.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/blkio.c
268
+++ b/block/blkio.c
269
@@ -XXX,XX +XXX,XX @@ static void blkio_close(BlockDriverState *bs)
270
}
271
}
272
273
-static int64_t blkio_getlength(BlockDriverState *bs)
274
+static int64_t coroutine_fn blkio_co_getlength(BlockDriverState *bs)
275
{
276
BDRVBlkioState *s = bs->opaque;
277
uint64_t capacity;
278
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset,
279
return -ENOTSUP;
280
}
281
282
- current_length = blkio_getlength(bs);
283
+ current_length = blkio_co_getlength(bs);
284
285
if (offset > current_length) {
286
error_setg(errp, "Cannot grow device");
287
@@ -XXX,XX +XXX,XX @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
288
.instance_size = sizeof(BDRVBlkioState), \
289
.bdrv_file_open = blkio_file_open, \
290
.bdrv_close = blkio_close, \
291
- .bdrv_getlength = blkio_getlength, \
292
+ .bdrv_co_getlength = blkio_co_getlength, \
293
.bdrv_co_truncate = blkio_truncate, \
294
.bdrv_get_info = blkio_get_info, \
295
.bdrv_attach_aio_context = blkio_attach_aio_context, \
125
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
296
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
126
index XXXXXXX..XXXXXXX 100644
297
index XXXXXXX..XXXXXXX 100644
127
--- a/block/blklogwrites.c
298
--- a/block/blklogwrites.c
128
+++ b/block/blklogwrites.c
299
+++ b/block/blklogwrites.c
129
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_close(BlockDriverState *bs)
300
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_close(BlockDriverState *bs)
130
s->log_file = NULL;
301
s->log_file = NULL;
131
}
302
}
132
303
133
-static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
304
-static int64_t blk_log_writes_getlength(BlockDriverState *bs)
134
+static int64_t coroutine_fn GRAPH_RDLOCK
305
+static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
135
+blk_log_writes_co_getlength(BlockDriverState *bs)
306
{
136
{
307
- return bdrv_getlength(bs->file->bs);
137
return bdrv_co_getlength(bs->file->bs);
308
+ return bdrv_co_getlength(bs->file->bs);
138
}
309
}
310
311
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
312
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
313
314
.bdrv_open = blk_log_writes_open,
315
.bdrv_close = blk_log_writes_close,
316
- .bdrv_getlength = blk_log_writes_getlength,
317
+ .bdrv_co_getlength = blk_log_writes_co_getlength,
318
.bdrv_child_perm = blk_log_writes_child_perm,
319
.bdrv_refresh_limits = blk_log_writes_refresh_limits,
320
139
diff --git a/block/blkreplay.c b/block/blkreplay.c
321
diff --git a/block/blkreplay.c b/block/blkreplay.c
140
index XXXXXXX..XXXXXXX 100644
322
index XXXXXXX..XXXXXXX 100644
141
--- a/block/blkreplay.c
323
--- a/block/blkreplay.c
142
+++ b/block/blkreplay.c
324
+++ b/block/blkreplay.c
143
@@ -XXX,XX +XXX,XX @@ fail:
325
@@ -XXX,XX +XXX,XX @@ fail:
144
return ret;
326
return ret;
145
}
327
}
146
328
147
-static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
329
-static int64_t blkreplay_getlength(BlockDriverState *bs)
148
+static int64_t coroutine_fn GRAPH_RDLOCK
330
+static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
149
+blkreplay_co_getlength(BlockDriverState *bs)
331
{
150
{
332
- return bdrv_getlength(bs->file->bs);
151
return bdrv_co_getlength(bs->file->bs);
333
+ return bdrv_co_getlength(bs->file->bs);
152
}
334
}
335
336
/* This bh is used for synchronization of return from coroutines.
337
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkreplay = {
338
339
.bdrv_open = blkreplay_open,
340
.bdrv_child_perm = bdrv_default_perms,
341
- .bdrv_getlength = blkreplay_getlength,
342
+ .bdrv_co_getlength = blkreplay_co_getlength,
343
344
.bdrv_co_preadv = blkreplay_co_preadv,
345
.bdrv_co_pwritev = blkreplay_co_pwritev,
153
diff --git a/block/blkverify.c b/block/blkverify.c
346
diff --git a/block/blkverify.c b/block/blkverify.c
154
index XXXXXXX..XXXXXXX 100644
347
index XXXXXXX..XXXXXXX 100644
155
--- a/block/blkverify.c
348
--- a/block/blkverify.c
156
+++ b/block/blkverify.c
349
+++ b/block/blkverify.c
157
@@ -XXX,XX +XXX,XX @@ static void blkverify_close(BlockDriverState *bs)
350
@@ -XXX,XX +XXX,XX @@ static void blkverify_close(BlockDriverState *bs)
158
s->test_file = NULL;
351
s->test_file = NULL;
159
}
352
}
160
353
161
-static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
354
-static int64_t blkverify_getlength(BlockDriverState *bs)
162
+static int64_t coroutine_fn GRAPH_RDLOCK
355
+static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
163
+blkverify_co_getlength(BlockDriverState *bs)
164
{
356
{
165
BDRVBlkverifyState *s = bs->opaque;
357
BDRVBlkverifyState *s = bs->opaque;
166
358
359
- return bdrv_getlength(s->test_file->bs);
360
+ return bdrv_co_getlength(s->test_file->bs);
361
}
362
363
static void coroutine_fn blkverify_do_test_req(void *opaque)
364
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
365
.bdrv_file_open = blkverify_open,
366
.bdrv_close = blkverify_close,
367
.bdrv_child_perm = bdrv_default_perms,
368
- .bdrv_getlength = blkverify_getlength,
369
+ .bdrv_co_getlength = blkverify_co_getlength,
370
.bdrv_refresh_filename = blkverify_refresh_filename,
371
.bdrv_dirname = blkverify_dirname,
372
373
diff --git a/block/block-backend.c b/block/block-backend.c
374
index XXXXXXX..XXXXXXX 100644
375
--- a/block/block-backend.c
376
+++ b/block/block-backend.c
377
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
378
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
379
}
380
381
-int64_t blk_getlength(BlockBackend *blk)
382
+int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
383
{
384
IO_CODE();
385
+
386
if (!blk_is_available(blk)) {
387
return -ENOMEDIUM;
388
}
389
390
- return bdrv_getlength(blk_bs(blk));
391
+ return bdrv_co_getlength(blk_bs(blk));
392
}
393
394
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
395
@@ -XXX,XX +XXX,XX @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
396
}
397
}
398
399
-int64_t blk_nb_sectors(BlockBackend *blk)
400
+int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
401
{
402
IO_CODE();
403
+
404
if (!blk_is_available(blk)) {
405
return -ENOMEDIUM;
406
}
407
408
- return bdrv_nb_sectors(blk_bs(blk));
409
+ return bdrv_co_nb_sectors(blk_bs(blk));
410
}
411
412
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
413
diff --git a/block/commit.c b/block/commit.c
414
index XXXXXXX..XXXXXXX 100644
415
--- a/block/commit.c
416
+++ b/block/commit.c
417
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
418
QEMU_AUTO_VFREE void *buf = NULL;
419
int64_t len, base_len;
420
421
- len = blk_getlength(s->top);
422
+ len = blk_co_getlength(s->top);
423
if (len < 0) {
424
return len;
425
}
426
job_progress_set_remaining(&s->common.job, len);
427
428
- base_len = blk_getlength(s->base);
429
+ base_len = blk_co_getlength(s->base);
430
if (base_len < 0) {
431
return base_len;
432
}
167
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
433
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
168
index XXXXXXX..XXXXXXX 100644
434
index XXXXXXX..XXXXXXX 100644
169
--- a/block/copy-on-read.c
435
--- a/block/copy-on-read.c
170
+++ b/block/copy-on-read.c
436
+++ b/block/copy-on-read.c
171
@@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
437
@@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
172
}
438
}
173
439
174
440
175
-static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
441
-static int64_t cor_getlength(BlockDriverState *bs)
176
+static int64_t coroutine_fn GRAPH_RDLOCK cor_co_getlength(BlockDriverState *bs)
442
+static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
177
{
443
{
178
return bdrv_co_getlength(bs->file->bs);
444
- return bdrv_getlength(bs->file->bs);
179
}
445
+ return bdrv_co_getlength(bs->file->bs);
446
}
447
448
449
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = {
450
.bdrv_close = cor_close,
451
.bdrv_child_perm = cor_child_perm,
452
453
- .bdrv_getlength = cor_getlength,
454
+ .bdrv_co_getlength = cor_co_getlength,
455
456
.bdrv_co_preadv_part = cor_co_preadv_part,
457
.bdrv_co_pwritev_part = cor_co_pwritev_part,
180
diff --git a/block/crypto.c b/block/crypto.c
458
diff --git a/block/crypto.c b/block/crypto.c
181
index XXXXXXX..XXXXXXX 100644
459
index XXXXXXX..XXXXXXX 100644
182
--- a/block/crypto.c
460
--- a/block/crypto.c
183
+++ b/block/crypto.c
461
+++ b/block/crypto.c
184
@@ -XXX,XX +XXX,XX @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
462
@@ -XXX,XX +XXX,XX @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
185
}
463
}
186
464
187
465
188
-static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
466
-static int64_t block_crypto_getlength(BlockDriverState *bs)
189
+static int64_t coroutine_fn GRAPH_RDLOCK
467
+static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
190
+block_crypto_co_getlength(BlockDriverState *bs)
191
{
468
{
192
BlockCrypto *crypto = bs->opaque;
469
BlockCrypto *crypto = bs->opaque;
193
int64_t len = bdrv_co_getlength(bs->file->bs);
470
- int64_t len = bdrv_getlength(bs->file->bs);
471
+ int64_t len = bdrv_co_getlength(bs->file->bs);
472
473
uint64_t offset = qcrypto_block_get_payload_offset(crypto->block);
474
assert(offset < INT64_MAX);
475
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
476
.bdrv_refresh_limits = block_crypto_refresh_limits,
477
.bdrv_co_preadv = block_crypto_co_preadv,
478
.bdrv_co_pwritev = block_crypto_co_pwritev,
479
- .bdrv_getlength = block_crypto_getlength,
480
+ .bdrv_co_getlength = block_crypto_co_getlength,
481
.bdrv_measure = block_crypto_measure,
482
.bdrv_get_info = block_crypto_get_info_luks,
483
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
484
diff --git a/block/curl.c b/block/curl.c
485
index XXXXXXX..XXXXXXX 100644
486
--- a/block/curl.c
487
+++ b/block/curl.c
488
@@ -XXX,XX +XXX,XX @@ static void curl_close(BlockDriverState *bs)
489
g_free(s->proxypassword);
490
}
491
492
-static int64_t curl_getlength(BlockDriverState *bs)
493
+static int64_t coroutine_fn curl_co_getlength(BlockDriverState *bs)
494
{
495
BDRVCURLState *s = bs->opaque;
496
return s->len;
497
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
498
.bdrv_parse_filename = curl_parse_filename,
499
.bdrv_file_open = curl_open,
500
.bdrv_close = curl_close,
501
- .bdrv_getlength = curl_getlength,
502
+ .bdrv_co_getlength = curl_co_getlength,
503
504
.bdrv_co_preadv = curl_co_preadv,
505
506
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
507
.bdrv_parse_filename = curl_parse_filename,
508
.bdrv_file_open = curl_open,
509
.bdrv_close = curl_close,
510
- .bdrv_getlength = curl_getlength,
511
+ .bdrv_co_getlength = curl_co_getlength,
512
513
.bdrv_co_preadv = curl_co_preadv,
514
515
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
516
.bdrv_parse_filename = curl_parse_filename,
517
.bdrv_file_open = curl_open,
518
.bdrv_close = curl_close,
519
- .bdrv_getlength = curl_getlength,
520
+ .bdrv_co_getlength = curl_co_getlength,
521
522
.bdrv_co_preadv = curl_co_preadv,
523
524
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
525
.bdrv_parse_filename = curl_parse_filename,
526
.bdrv_file_open = curl_open,
527
.bdrv_close = curl_close,
528
- .bdrv_getlength = curl_getlength,
529
+ .bdrv_co_getlength = curl_co_getlength,
530
531
.bdrv_co_preadv = curl_co_preadv,
532
533
diff --git a/block/file-posix.c b/block/file-posix.c
534
index XXXXXXX..XXXXXXX 100644
535
--- a/block/file-posix.c
536
+++ b/block/file-posix.c
537
@@ -XXX,XX +XXX,XX @@ static int fd_open(BlockDriverState *bs)
538
return -EIO;
539
}
540
541
-static int64_t raw_getlength(BlockDriverState *bs);
542
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs);
543
544
typedef struct RawPosixAIOData {
545
BlockDriverState *bs;
546
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
547
}
548
549
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
550
- int64_t cur_length = raw_getlength(bs);
551
+ int64_t cur_length = raw_co_getlength(bs);
552
553
if (offset != cur_length && exact) {
554
error_setg(errp, "Cannot resize device files");
555
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
556
}
557
558
#ifdef __OpenBSD__
559
-static int64_t raw_getlength(BlockDriverState *bs)
560
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
561
{
562
BDRVRawState *s = bs->opaque;
563
int fd = s->fd;
564
@@ -XXX,XX +XXX,XX @@ static int64_t raw_getlength(BlockDriverState *bs)
565
return st.st_size;
566
}
567
#elif defined(__NetBSD__)
568
-static int64_t raw_getlength(BlockDriverState *bs)
569
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
570
{
571
BDRVRawState *s = bs->opaque;
572
int fd = s->fd;
573
@@ -XXX,XX +XXX,XX @@ static int64_t raw_getlength(BlockDriverState *bs)
574
return st.st_size;
575
}
576
#elif defined(__sun__)
577
-static int64_t raw_getlength(BlockDriverState *bs)
578
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
579
{
580
BDRVRawState *s = bs->opaque;
581
struct dk_minfo minfo;
582
@@ -XXX,XX +XXX,XX @@ static int64_t raw_getlength(BlockDriverState *bs)
583
return size;
584
}
585
#elif defined(CONFIG_BSD)
586
-static int64_t raw_getlength(BlockDriverState *bs)
587
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
588
{
589
BDRVRawState *s = bs->opaque;
590
int fd = s->fd;
591
@@ -XXX,XX +XXX,XX @@ again:
592
return size;
593
}
594
#else
595
-static int64_t raw_getlength(BlockDriverState *bs)
596
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
597
{
598
BDRVRawState *s = bs->opaque;
599
int ret;
600
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
601
* round up if necessary.
602
*/
603
if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
604
- int64_t file_length = raw_getlength(bs);
605
+ int64_t file_length = raw_co_getlength(bs);
606
if (file_length > 0) {
607
/* Ignore errors, this is just a safeguard */
608
assert(hole == file_length);
609
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
610
611
#if defined(__linux__)
612
/* Verify that the file is not in the page cache */
613
-static void check_cache_dropped(BlockDriverState *bs, Error **errp)
614
+static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
615
{
616
const size_t window_size = 128 * 1024 * 1024;
617
BDRVRawState *s = bs->opaque;
618
@@ -XXX,XX +XXX,XX @@ static void check_cache_dropped(BlockDriverState *bs, Error **errp)
619
page_size = sysconf(_SC_PAGESIZE);
620
vec = g_malloc(DIV_ROUND_UP(window_size, page_size));
621
622
- end = raw_getlength(bs);
623
+ end = raw_co_getlength(bs);
624
625
for (offset = 0; offset < end; offset += window_size) {
626
void *new_window;
627
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
628
.bdrv_co_io_unplug = raw_co_io_unplug,
629
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
630
631
- .bdrv_co_truncate = raw_co_truncate,
632
- .bdrv_getlength = raw_getlength,
633
+ .bdrv_co_truncate = raw_co_truncate,
634
+ .bdrv_co_getlength = raw_co_getlength,
635
.bdrv_get_info = raw_get_info,
636
.bdrv_get_allocated_file_size
637
= raw_get_allocated_file_size,
638
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
639
.bdrv_co_io_unplug = raw_co_io_unplug,
640
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
641
642
- .bdrv_co_truncate = raw_co_truncate,
643
- .bdrv_getlength    = raw_getlength,
644
+ .bdrv_co_truncate = raw_co_truncate,
645
+ .bdrv_co_getlength = raw_co_getlength,
646
.bdrv_get_info = raw_get_info,
647
.bdrv_get_allocated_file_size
648
= raw_get_allocated_file_size,
649
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
650
.bdrv_co_io_unplug = raw_co_io_unplug,
651
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
652
653
- .bdrv_co_truncate = raw_co_truncate,
654
- .bdrv_getlength = raw_getlength,
655
- .has_variable_length = true,
656
+ .bdrv_co_truncate = raw_co_truncate,
657
+ .bdrv_co_getlength = raw_co_getlength,
658
+ .has_variable_length = true,
659
.bdrv_get_allocated_file_size
660
= raw_get_allocated_file_size,
661
662
@@ -XXX,XX +XXX,XX @@ static int cdrom_reopen(BlockDriverState *bs)
663
664
static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
665
{
666
- return raw_getlength(bs) > 0;
667
+ return raw_co_getlength(bs) > 0;
668
}
669
670
static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
671
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
672
.bdrv_co_io_unplug = raw_co_io_unplug,
673
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
674
675
- .bdrv_co_truncate = raw_co_truncate,
676
- .bdrv_getlength = raw_getlength,
677
- .has_variable_length = true,
678
+ .bdrv_co_truncate = raw_co_truncate,
679
+ .bdrv_co_getlength = raw_co_getlength,
680
+ .has_variable_length = true,
681
.bdrv_get_allocated_file_size
682
= raw_get_allocated_file_size,
683
684
diff --git a/block/file-win32.c b/block/file-win32.c
685
index XXXXXXX..XXXXXXX 100644
686
--- a/block/file-win32.c
687
+++ b/block/file-win32.c
688
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
689
return 0;
690
}
691
692
-static int64_t raw_getlength(BlockDriverState *bs)
693
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
694
{
695
BDRVRawState *s = bs->opaque;
696
LARGE_INTEGER l;
697
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
698
.bdrv_aio_flush = raw_aio_flush,
699
700
.bdrv_co_truncate = raw_co_truncate,
701
- .bdrv_getlength    = raw_getlength,
702
+ .bdrv_co_getlength = raw_co_getlength,
703
.bdrv_get_allocated_file_size
704
= raw_get_allocated_file_size,
705
706
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
707
.bdrv_detach_aio_context = raw_detach_aio_context,
708
.bdrv_attach_aio_context = raw_attach_aio_context,
709
710
- .bdrv_getlength = raw_getlength,
711
- .has_variable_length = true,
712
+ .bdrv_co_getlength = raw_co_getlength,
713
+ .has_variable_length = true,
714
715
.bdrv_get_allocated_file_size
716
= raw_get_allocated_file_size,
194
diff --git a/block/filter-compress.c b/block/filter-compress.c
717
diff --git a/block/filter-compress.c b/block/filter-compress.c
195
index XXXXXXX..XXXXXXX 100644
718
index XXXXXXX..XXXXXXX 100644
196
--- a/block/filter-compress.c
719
--- a/block/filter-compress.c
197
+++ b/block/filter-compress.c
720
+++ b/block/filter-compress.c
198
@@ -XXX,XX +XXX,XX @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
721
@@ -XXX,XX +XXX,XX @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
199
}
722
}
200
723
201
724
202
-static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
725
-static int64_t compress_getlength(BlockDriverState *bs)
203
+static int64_t coroutine_fn GRAPH_RDLOCK
726
+static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
204
+compress_co_getlength(BlockDriverState *bs)
727
{
205
{
728
- return bdrv_getlength(bs->file->bs);
206
return bdrv_co_getlength(bs->file->bs);
729
+ return bdrv_co_getlength(bs->file->bs);
207
}
730
}
731
732
733
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = {
734
.bdrv_open = compress_open,
735
.bdrv_child_perm = bdrv_default_perms,
736
737
- .bdrv_getlength = compress_getlength,
738
+ .bdrv_co_getlength = compress_co_getlength,
739
740
.bdrv_co_preadv_part = compress_co_preadv_part,
741
.bdrv_co_pwritev_part = compress_co_pwritev_part,
742
diff --git a/block/gluster.c b/block/gluster.c
743
index XXXXXXX..XXXXXXX 100644
744
--- a/block/gluster.c
745
+++ b/block/gluster.c
746
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_pdiscard(BlockDriverState *bs,
747
}
748
#endif
749
750
-static int64_t qemu_gluster_getlength(BlockDriverState *bs)
751
+static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
752
{
753
BDRVGlusterState *s = bs->opaque;
754
int64_t ret;
755
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
756
* round up if necessary.
757
*/
758
if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
759
- int64_t file_length = qemu_gluster_getlength(bs);
760
+ int64_t file_length = qemu_gluster_co_getlength(bs);
761
if (file_length > 0) {
762
/* Ignore errors, this is just a safeguard */
763
assert(hole == file_length);
764
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
765
.bdrv_close = qemu_gluster_close,
766
.bdrv_co_create = qemu_gluster_co_create,
767
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
768
- .bdrv_getlength = qemu_gluster_getlength,
769
+ .bdrv_co_getlength = qemu_gluster_co_getlength,
770
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
771
.bdrv_co_truncate = qemu_gluster_co_truncate,
772
.bdrv_co_readv = qemu_gluster_co_readv,
773
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
774
.bdrv_close = qemu_gluster_close,
775
.bdrv_co_create = qemu_gluster_co_create,
776
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
777
- .bdrv_getlength = qemu_gluster_getlength,
778
+ .bdrv_co_getlength = qemu_gluster_co_getlength,
779
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
780
.bdrv_co_truncate = qemu_gluster_co_truncate,
781
.bdrv_co_readv = qemu_gluster_co_readv,
782
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
783
.bdrv_close = qemu_gluster_close,
784
.bdrv_co_create = qemu_gluster_co_create,
785
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
786
- .bdrv_getlength = qemu_gluster_getlength,
787
+ .bdrv_co_getlength = qemu_gluster_co_getlength,
788
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
789
.bdrv_co_truncate = qemu_gluster_co_truncate,
790
.bdrv_co_readv = qemu_gluster_co_readv,
791
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
792
.bdrv_close = qemu_gluster_close,
793
.bdrv_co_create = qemu_gluster_co_create,
794
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
795
- .bdrv_getlength = qemu_gluster_getlength,
796
+ .bdrv_co_getlength = qemu_gluster_co_getlength,
797
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
798
.bdrv_co_truncate = qemu_gluster_co_truncate,
799
.bdrv_co_readv = qemu_gluster_co_readv,
800
diff --git a/block/iscsi.c b/block/iscsi.c
801
index XXXXXXX..XXXXXXX 100644
802
--- a/block/iscsi.c
803
+++ b/block/iscsi.c
804
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
805
806
#endif
807
808
-static int64_t
809
-iscsi_getlength(BlockDriverState *bs)
810
+static int64_t coroutine_fn
811
+iscsi_co_getlength(BlockDriverState *bs)
812
{
813
IscsiLun *iscsilun = bs->opaque;
814
int64_t len;
815
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
816
return -EIO;
817
}
818
819
- cur_length = iscsi_getlength(bs);
820
+ cur_length = iscsi_co_getlength(bs);
821
if (offset != cur_length && exact) {
822
error_setg(errp, "Cannot resize iSCSI devices");
823
return -ENOTSUP;
824
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
825
.bdrv_reopen_commit = iscsi_reopen_commit,
826
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
827
828
- .bdrv_getlength = iscsi_getlength,
829
+ .bdrv_co_getlength = iscsi_co_getlength,
830
.bdrv_get_info = iscsi_get_info,
831
.bdrv_co_truncate = iscsi_co_truncate,
832
.bdrv_refresh_limits = iscsi_refresh_limits,
833
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
834
.bdrv_reopen_commit = iscsi_reopen_commit,
835
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
836
837
- .bdrv_getlength = iscsi_getlength,
838
+ .bdrv_co_getlength = iscsi_co_getlength,
839
.bdrv_get_info = iscsi_get_info,
840
.bdrv_co_truncate = iscsi_co_truncate,
841
.bdrv_refresh_limits = iscsi_refresh_limits,
208
diff --git a/block/mirror.c b/block/mirror.c
842
diff --git a/block/mirror.c b/block/mirror.c
209
index XXXXXXX..XXXXXXX 100644
843
index XXXXXXX..XXXXXXX 100644
210
--- a/block/mirror.c
844
--- a/block/mirror.c
211
+++ b/block/mirror.c
845
+++ b/block/mirror.c
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
846
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
213
goto immediate_exit;
847
goto immediate_exit;
214
}
848
}
215
849
216
+ bdrv_graph_co_rdlock();
850
- s->bdev_length = bdrv_getlength(bs);
217
s->bdev_length = bdrv_co_getlength(bs);
851
+ s->bdev_length = bdrv_co_getlength(bs);
218
+ bdrv_graph_co_rdunlock();
219
+
220
if (s->bdev_length < 0) {
852
if (s->bdev_length < 0) {
221
ret = s->bdev_length;
853
ret = s->bdev_length;
222
goto immediate_exit;
854
goto immediate_exit;
855
}
856
857
- target_length = blk_getlength(s->target);
858
+ target_length = blk_co_getlength(s->target);
859
if (target_length < 0) {
860
ret = target_length;
861
goto immediate_exit;
862
diff --git a/block/nbd.c b/block/nbd.c
863
index XXXXXXX..XXXXXXX 100644
864
--- a/block/nbd.c
865
+++ b/block/nbd.c
866
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_co_truncate(BlockDriverState *bs, int64_t offset,
867
return 0;
868
}
869
870
-static int64_t nbd_getlength(BlockDriverState *bs)
871
+static int64_t coroutine_fn nbd_co_getlength(BlockDriverState *bs)
872
{
873
BDRVNBDState *s = bs->opaque;
874
875
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
876
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
877
.bdrv_refresh_limits = nbd_refresh_limits,
878
.bdrv_co_truncate = nbd_co_truncate,
879
- .bdrv_getlength = nbd_getlength,
880
+ .bdrv_co_getlength = nbd_co_getlength,
881
.bdrv_refresh_filename = nbd_refresh_filename,
882
.bdrv_co_block_status = nbd_client_co_block_status,
883
.bdrv_dirname = nbd_dirname,
884
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
885
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
886
.bdrv_refresh_limits = nbd_refresh_limits,
887
.bdrv_co_truncate = nbd_co_truncate,
888
- .bdrv_getlength = nbd_getlength,
889
+ .bdrv_co_getlength = nbd_co_getlength,
890
.bdrv_refresh_filename = nbd_refresh_filename,
891
.bdrv_co_block_status = nbd_client_co_block_status,
892
.bdrv_dirname = nbd_dirname,
893
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
894
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
895
.bdrv_refresh_limits = nbd_refresh_limits,
896
.bdrv_co_truncate = nbd_co_truncate,
897
- .bdrv_getlength = nbd_getlength,
898
+ .bdrv_co_getlength = nbd_co_getlength,
899
.bdrv_refresh_filename = nbd_refresh_filename,
900
.bdrv_co_block_status = nbd_client_co_block_status,
901
.bdrv_dirname = nbd_dirname,
902
diff --git a/block/null.c b/block/null.c
903
index XXXXXXX..XXXXXXX 100644
904
--- a/block/null.c
905
+++ b/block/null.c
906
@@ -XXX,XX +XXX,XX @@ static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
907
return ret;
908
}
909
910
-static int64_t null_getlength(BlockDriverState *bs)
911
+static int64_t coroutine_fn null_co_getlength(BlockDriverState *bs)
912
{
913
BDRVNullState *s = bs->opaque;
914
return s->length;
915
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
916
917
.bdrv_file_open = null_file_open,
918
.bdrv_parse_filename = null_co_parse_filename,
919
- .bdrv_getlength = null_getlength,
920
+ .bdrv_co_getlength = null_co_getlength,
921
.bdrv_get_allocated_file_size = null_allocated_file_size,
922
923
.bdrv_co_preadv = null_co_preadv,
924
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
925
926
.bdrv_file_open = null_file_open,
927
.bdrv_parse_filename = null_aio_parse_filename,
928
- .bdrv_getlength = null_getlength,
929
+ .bdrv_co_getlength = null_co_getlength,
930
.bdrv_get_allocated_file_size = null_allocated_file_size,
931
932
.bdrv_aio_preadv = null_aio_preadv,
933
diff --git a/block/nvme.c b/block/nvme.c
934
index XXXXXXX..XXXXXXX 100644
935
--- a/block/nvme.c
936
+++ b/block/nvme.c
937
@@ -XXX,XX +XXX,XX @@ fail:
938
return ret;
939
}
940
941
-static int64_t nvme_getlength(BlockDriverState *bs)
942
+static int64_t coroutine_fn nvme_co_getlength(BlockDriverState *bs)
943
{
944
BDRVNVMeState *s = bs->opaque;
945
return s->nsze << s->blkshift;
946
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nvme_co_truncate(BlockDriverState *bs, int64_t offset,
947
return -ENOTSUP;
948
}
949
950
- cur_length = nvme_getlength(bs);
951
+ cur_length = nvme_co_getlength(bs);
952
if (offset != cur_length && exact) {
953
error_setg(errp, "Cannot resize NVMe devices");
954
return -ENOTSUP;
955
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
956
.bdrv_parse_filename = nvme_parse_filename,
957
.bdrv_file_open = nvme_file_open,
958
.bdrv_close = nvme_close,
959
- .bdrv_getlength = nvme_getlength,
960
+ .bdrv_co_getlength = nvme_co_getlength,
961
.bdrv_probe_blocksizes = nvme_probe_blocksizes,
962
.bdrv_co_truncate = nvme_co_truncate,
963
223
diff --git a/block/preallocate.c b/block/preallocate.c
964
diff --git a/block/preallocate.c b/block/preallocate.c
224
index XXXXXXX..XXXXXXX 100644
965
index XXXXXXX..XXXXXXX 100644
225
--- a/block/preallocate.c
966
--- a/block/preallocate.c
226
+++ b/block/preallocate.c
967
+++ b/block/preallocate.c
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs)
968
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
228
return bdrv_co_flush(bs->file->bs);
969
return bdrv_co_flush(bs->file->bs);
229
}
970
}
230
971
231
-static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs)
972
-static int64_t preallocate_getlength(BlockDriverState *bs)
232
+static int64_t coroutine_fn GRAPH_RDLOCK
973
+static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs)
233
+preallocate_co_getlength(BlockDriverState *bs)
234
{
974
{
235
int64_t ret;
975
int64_t ret;
236
BDRVPreallocateState *s = bs->opaque;
976
BDRVPreallocateState *s = bs->opaque;
977
@@ -XXX,XX +XXX,XX @@ static int64_t preallocate_getlength(BlockDriverState *bs)
978
return s->data_end;
979
}
980
981
- ret = bdrv_getlength(bs->file->bs);
982
+ ret = bdrv_co_getlength(bs->file->bs);
983
984
if (has_prealloc_perms(bs)) {
985
s->file_end = s->zero_start = s->data_end = ret;
986
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_preallocate_filter = {
987
.format_name = "preallocate",
988
.instance_size = sizeof(BDRVPreallocateState),
989
990
- .bdrv_getlength = preallocate_getlength,
991
- .bdrv_open = preallocate_open,
992
- .bdrv_close = preallocate_close,
993
+ .bdrv_co_getlength = preallocate_co_getlength,
994
+ .bdrv_open = preallocate_open,
995
+ .bdrv_close = preallocate_close,
996
997
.bdrv_reopen_prepare = preallocate_reopen_prepare,
998
.bdrv_reopen_commit = preallocate_reopen_commit,
999
diff --git a/block/qed.c b/block/qed.c
1000
index XXXXXXX..XXXXXXX 100644
1001
--- a/block/qed.c
1002
+++ b/block/qed.c
1003
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
1004
return ret;
1005
}
1006
1007
-static int64_t bdrv_qed_getlength(BlockDriverState *bs)
1008
+static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs)
1009
{
1010
BDRVQEDState *s = bs->opaque;
1011
return s->header.image_size;
1012
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
1013
.bdrv_co_writev = bdrv_qed_co_writev,
1014
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
1015
.bdrv_co_truncate = bdrv_qed_co_truncate,
1016
- .bdrv_getlength = bdrv_qed_getlength,
1017
+ .bdrv_co_getlength = bdrv_qed_co_getlength,
1018
.bdrv_get_info = bdrv_qed_get_info,
1019
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
1020
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
237
diff --git a/block/quorum.c b/block/quorum.c
1021
diff --git a/block/quorum.c b/block/quorum.c
238
index XXXXXXX..XXXXXXX 100644
1022
index XXXXXXX..XXXXXXX 100644
239
--- a/block/quorum.c
1023
--- a/block/quorum.c
240
+++ b/block/quorum.c
1024
+++ b/block/quorum.c
241
@@ -XXX,XX +XXX,XX @@ quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
1025
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
242
flags | BDRV_REQ_ZERO_WRITE);
1026
flags | BDRV_REQ_ZERO_WRITE);
243
}
1027
}
244
1028
245
-static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
1029
-static int64_t quorum_getlength(BlockDriverState *bs)
246
+static int64_t coroutine_fn GRAPH_RDLOCK
1030
+static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
247
+quorum_co_getlength(BlockDriverState *bs)
248
{
1031
{
249
BDRVQuorumState *s = bs->opaque;
1032
BDRVQuorumState *s = bs->opaque;
250
int64_t result;
1033
int64_t result;
1034
int i;
1035
1036
/* check that all file have the same length */
1037
- result = bdrv_getlength(s->children[0]->bs);
1038
+ result = bdrv_co_getlength(s->children[0]->bs);
1039
if (result < 0) {
1040
return result;
1041
}
1042
for (i = 1; i < s->num_children; i++) {
1043
- int64_t value = bdrv_getlength(s->children[i]->bs);
1044
+ int64_t value = bdrv_co_getlength(s->children[i]->bs);
1045
if (value < 0) {
1046
return value;
1047
}
1048
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
1049
1050
.bdrv_co_flush = quorum_co_flush,
1051
1052
- .bdrv_getlength = quorum_getlength,
1053
+ .bdrv_co_getlength = quorum_co_getlength,
1054
1055
.bdrv_co_preadv = quorum_co_preadv,
1056
.bdrv_co_pwritev = quorum_co_pwritev,
251
diff --git a/block/raw-format.c b/block/raw-format.c
1057
diff --git a/block/raw-format.c b/block/raw-format.c
252
index XXXXXXX..XXXXXXX 100644
1058
index XXXXXXX..XXXXXXX 100644
253
--- a/block/raw-format.c
1059
--- a/block/raw-format.c
254
+++ b/block/raw-format.c
1060
+++ b/block/raw-format.c
255
@@ -XXX,XX +XXX,XX @@ raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
1061
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
256
return bdrv_co_pdiscard(bs->file, offset, bytes);
1062
return bdrv_co_pdiscard(bs->file, offset, bytes);
257
}
1063
}
258
1064
259
-static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
1065
-static int64_t raw_getlength(BlockDriverState *bs)
260
+static int64_t coroutine_fn GRAPH_RDLOCK
1066
+static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
261
+raw_co_getlength(BlockDriverState *bs)
262
{
1067
{
263
int64_t len;
1068
int64_t len;
264
BDRVRawState *s = bs->opaque;
1069
BDRVRawState *s = bs->opaque;
1070
1071
/* Update size. It should not change unless the file was externally
1072
* modified. */
1073
- len = bdrv_getlength(bs->file->bs);
1074
+ len = bdrv_co_getlength(bs->file->bs);
1075
if (len < 0) {
1076
return len;
1077
}
1078
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
1079
.bdrv_co_copy_range_from = &raw_co_copy_range_from,
1080
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
1081
.bdrv_co_truncate = &raw_co_truncate,
1082
- .bdrv_getlength = &raw_getlength,
1083
+ .bdrv_co_getlength = &raw_co_getlength,
1084
.is_format = true,
1085
.has_variable_length = true,
1086
.bdrv_measure = &raw_measure,
1087
diff --git a/block/rbd.c b/block/rbd.c
1088
index XXXXXXX..XXXXXXX 100644
1089
--- a/block/rbd.c
1090
+++ b/block/rbd.c
1091
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
1092
return status;
1093
}
1094
1095
-static int64_t qemu_rbd_getlength(BlockDriverState *bs)
1096
+static int64_t coroutine_fn qemu_rbd_co_getlength(BlockDriverState *bs)
1097
{
1098
BDRVRBDState *s = bs->opaque;
1099
int r;
1100
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
1101
.bdrv_get_info = qemu_rbd_getinfo,
1102
.bdrv_get_specific_info = qemu_rbd_get_specific_info,
1103
.create_opts = &qemu_rbd_create_opts,
1104
- .bdrv_getlength = qemu_rbd_getlength,
1105
+ .bdrv_co_getlength = qemu_rbd_co_getlength,
1106
.bdrv_co_truncate = qemu_rbd_co_truncate,
1107
.protocol_name = "rbd",
1108
265
diff --git a/block/replication.c b/block/replication.c
1109
diff --git a/block/replication.c b/block/replication.c
266
index XXXXXXX..XXXXXXX 100644
1110
index XXXXXXX..XXXXXXX 100644
267
--- a/block/replication.c
1111
--- a/block/replication.c
268
+++ b/block/replication.c
1112
+++ b/block/replication.c
269
@@ -XXX,XX +XXX,XX @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
1113
@@ -XXX,XX +XXX,XX @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
270
return;
1114
return;
271
}
1115
}
272
1116
273
-static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs)
1117
-static int64_t replication_getlength(BlockDriverState *bs)
274
+static int64_t coroutine_fn GRAPH_RDLOCK
1118
+static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs)
275
+replication_co_getlength(BlockDriverState *bs)
1119
{
276
{
1120
- return bdrv_getlength(bs->file->bs);
277
return bdrv_co_getlength(bs->file->bs);
1121
+ return bdrv_co_getlength(bs->file->bs);
278
}
1122
}
279
diff --git a/block/stream.c b/block/stream.c
1123
280
index XXXXXXX..XXXXXXX 100644
1124
static int replication_get_io_status(BDRVReplicationState *s)
281
--- a/block/stream.c
1125
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_replication = {
282
+++ b/block/stream.c
1126
.bdrv_close = replication_close,
283
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
1127
.bdrv_child_perm = replication_child_perm,
284
return 0;
1128
285
}
1129
- .bdrv_getlength = replication_getlength,
286
1130
+ .bdrv_co_getlength = replication_co_getlength,
287
- len = bdrv_getlength(s->target_bs);
1131
.bdrv_co_readv = replication_co_readv,
288
- if (len < 0) {
1132
.bdrv_co_writev = replication_co_writev,
289
- return len;
1133
290
+ WITH_GRAPH_RDLOCK_GUARD() {
1134
diff --git a/block/ssh.c b/block/ssh.c
291
+ len = bdrv_co_getlength(s->target_bs);
1135
index XXXXXXX..XXXXXXX 100644
292
+ if (len < 0) {
1136
--- a/block/ssh.c
293
+ return len;
1137
+++ b/block/ssh.c
294
+ }
1138
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
295
}
1139
return ret;
296
job_progress_set_remaining(&s->common.job, len);
1140
}
297
1141
1142
-static int64_t ssh_getlength(BlockDriverState *bs)
1143
+static int64_t coroutine_fn ssh_co_getlength(BlockDriverState *bs)
1144
{
1145
BDRVSSHState *s = bs->opaque;
1146
int64_t length;
1147
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
1148
.bdrv_has_zero_init = ssh_has_zero_init,
1149
.bdrv_co_readv = ssh_co_readv,
1150
.bdrv_co_writev = ssh_co_writev,
1151
- .bdrv_getlength = ssh_getlength,
1152
+ .bdrv_co_getlength = ssh_co_getlength,
1153
.bdrv_co_truncate = ssh_co_truncate,
1154
.bdrv_co_flush_to_disk = ssh_co_flush,
1155
.bdrv_refresh_filename = ssh_refresh_filename,
298
diff --git a/block/throttle.c b/block/throttle.c
1156
diff --git a/block/throttle.c b/block/throttle.c
299
index XXXXXXX..XXXXXXX 100644
1157
index XXXXXXX..XXXXXXX 100644
300
--- a/block/throttle.c
1158
--- a/block/throttle.c
301
+++ b/block/throttle.c
1159
+++ b/block/throttle.c
302
@@ -XXX,XX +XXX,XX @@ static void throttle_close(BlockDriverState *bs)
1160
@@ -XXX,XX +XXX,XX @@ static void throttle_close(BlockDriverState *bs)
303
}
1161
}
304
1162
305
1163
306
-static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
1164
-static int64_t throttle_getlength(BlockDriverState *bs)
307
+static int64_t coroutine_fn GRAPH_RDLOCK
1165
+static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
308
+throttle_co_getlength(BlockDriverState *bs)
1166
{
309
{
1167
- return bdrv_getlength(bs->file->bs);
310
return bdrv_co_getlength(bs->file->bs);
1168
+ return bdrv_co_getlength(bs->file->bs);
311
}
1169
}
1170
1171
static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1172
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
1173
1174
.bdrv_child_perm = bdrv_default_perms,
1175
1176
- .bdrv_getlength = throttle_getlength,
1177
+ .bdrv_co_getlength = throttle_co_getlength,
1178
1179
.bdrv_co_preadv = throttle_co_preadv,
1180
.bdrv_co_pwritev = throttle_co_pwritev,
1181
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
1182
index XXXXXXX..XXXXXXX 100644
1183
--- a/hw/scsi/scsi-disk.c
1184
+++ b/hw/scsi/scsi-disk.c
1185
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_reset(DeviceState *dev)
1186
{
1187
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
1188
uint64_t nb_sectors;
1189
+ AioContext *ctx;
1190
1191
scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
1192
1193
+ ctx = blk_get_aio_context(s->qdev.conf.blk);
1194
+ aio_context_acquire(ctx);
1195
blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
1196
+ aio_context_release(ctx);
1197
+
1198
nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE;
1199
if (nb_sectors) {
1200
nb_sectors--;
1201
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
1202
index XXXXXXX..XXXXXXX 100644
1203
--- a/tests/unit/test-block-iothread.c
1204
+++ b/tests/unit/test-block-iothread.c
1205
@@ -XXX,XX +XXX,XX @@ static void test_attach_second_node(void)
1206
qdict_put_str(options, "driver", "raw");
1207
qdict_put_str(options, "file", "base");
1208
1209
+ aio_context_acquire(ctx);
1210
filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
1211
+ aio_context_release(ctx);
1212
+
1213
g_assert(blk_get_aio_context(blk) == ctx);
1214
g_assert(bdrv_get_aio_context(bs) == ctx);
1215
g_assert(bdrv_get_aio_context(filter) == ctx);
1216
diff --git a/block/meson.build b/block/meson.build
1217
index XXXXXXX..XXXXXXX 100644
1218
--- a/block/meson.build
1219
+++ b/block/meson.build
1220
@@ -XXX,XX +XXX,XX @@ block_gen_c = custom_target('block-gen.c',
1221
input: files(
1222
'../include/block/block-io.h',
1223
'../include/block/dirty-bitmap.h',
1224
+ '../include/block/block_int-io.h',
1225
'../include/block/block-global-state.h',
1226
'../include/sysemu/block-backend-io.h',
1227
'coroutines.h'
312
--
1228
--
313
2.39.2
1229
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_block_status() need to hold a reader lock for the graph.
3
2
4
For some places, we know that they will hold the lock, but we don't have
3
The only difference is that blk_ checks if the block is available,
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
4
but this check is already performed above in blk_check_byte_request().
6
with a FIXME comment. These places will be removed once everything is
5
7
properly annotated.
6
This is in preparation for the graph rdlock, which will be taken
7
by both the callers of blk_check_byte_request() and blk_getlength().
8
8
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20230203152202.49054-5-kwolf@redhat.com>
11
Message-Id: <20230113204212.359076-8-kwolf@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
14
---
15
block/coroutines.h | 2 +-
15
block/block-backend.c | 2 +-
16
include/block/block-copy.h | 6 +++---
16
1 file changed, 1 insertion(+), 1 deletion(-)
17
include/block/block-io.h | 22 +++++++++++-----------
18
include/block/block_int-common.h | 3 ++-
19
block/backup.c | 3 +++
20
block/block-backend.c | 2 ++
21
block/block-copy.c | 19 +++++++++++--------
22
block/io.c | 13 ++++++++-----
23
block/mirror.c | 14 +++++++++-----
24
block/qcow.c | 11 ++++-------
25
block/quorum.c | 9 ++++-----
26
block/stream.c | 32 ++++++++++++++++++--------------
27
qemu-img.c | 4 +++-
28
tests/unit/test-block-iothread.c | 3 ++-
29
14 files changed, 81 insertions(+), 62 deletions(-)
30
17
31
diff --git a/block/coroutines.h b/block/coroutines.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/coroutines.h
34
+++ b/block/coroutines.h
35
@@ -XXX,XX +XXX,XX @@ bdrv_co_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
36
int coroutine_fn GRAPH_RDLOCK
37
bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp);
38
39
-int coroutine_fn
40
+int coroutine_fn GRAPH_RDLOCK
41
bdrv_co_common_block_status_above(BlockDriverState *bs,
42
BlockDriverState *base,
43
bool include_base,
44
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block-copy.h
47
+++ b/include/block/block-copy.h
48
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
49
void block_copy_state_free(BlockCopyState *s);
50
51
void block_copy_reset(BlockCopyState *s, int64_t offset, int64_t bytes);
52
-int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
53
- int64_t offset,
54
- int64_t *count);
55
+
56
+int64_t coroutine_fn GRAPH_RDLOCK
57
+block_copy_reset_unallocated(BlockCopyState *s, int64_t offset, int64_t *count);
58
59
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
60
bool ignore_ratelimit, uint64_t timeout_ns,
61
diff --git a/include/block/block-io.h b/include/block/block-io.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/block/block-io.h
64
+++ b/include/block/block-io.h
65
@@ -XXX,XX +XXX,XX @@ int bdrv_block_status(BlockDriverState *bs, int64_t offset,
66
int64_t bytes, int64_t *pnum, int64_t *map,
67
BlockDriverState **file);
68
69
-int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
70
- BlockDriverState *base,
71
- int64_t offset, int64_t bytes,
72
- int64_t *pnum, int64_t *map,
73
- BlockDriverState **file);
74
+int coroutine_fn GRAPH_RDLOCK
75
+bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base,
76
+ int64_t offset, int64_t bytes, int64_t *pnum,
77
+ int64_t *map, BlockDriverState **file);
78
int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
79
int64_t offset, int64_t bytes, int64_t *pnum,
80
int64_t *map, BlockDriverState **file);
81
82
-int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset,
83
- int64_t bytes, int64_t *pnum);
84
+int coroutine_fn GRAPH_RDLOCK
85
+bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
86
+ int64_t *pnum);
87
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
88
int64_t *pnum);
89
90
-int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
91
- BlockDriverState *base,
92
- bool include_base, int64_t offset,
93
- int64_t bytes, int64_t *pnum);
94
+int coroutine_fn GRAPH_RDLOCK
95
+bdrv_co_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
96
+ bool include_base, int64_t offset, int64_t bytes,
97
+ int64_t *pnum);
98
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
99
bool include_base, int64_t offset, int64_t bytes,
100
int64_t *pnum);
101
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
102
index XXXXXXX..XXXXXXX 100644
103
--- a/include/block/block_int-common.h
104
+++ b/include/block/block_int-common.h
105
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
106
* *pnum value for the block-status cache on protocol nodes, prior
107
* to clamping *pnum for return to its caller.
108
*/
109
- int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
110
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)(
111
+ BlockDriverState *bs,
112
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
113
int64_t *map, BlockDriverState **file);
114
115
diff --git a/block/backup.c b/block/backup.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/block/backup.c
118
+++ b/block/backup.c
119
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
120
return -ECANCELED;
121
}
122
123
+ /* rdlock protects the subsequent call to bdrv_is_allocated() */
124
+ bdrv_graph_co_rdlock();
125
ret = block_copy_reset_unallocated(s->bcs, offset, &count);
126
+ bdrv_graph_co_rdunlock();
127
if (ret < 0) {
128
return ret;
129
}
130
diff --git a/block/block-backend.c b/block/block-backend.c
18
diff --git a/block/block-backend.c b/block/block-backend.c
131
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
132
--- a/block/block-backend.c
20
--- a/block/block-backend.c
133
+++ b/block/block-backend.c
21
+++ b/block/block-backend.c
134
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_block_status_above(BlockBackend *blk,
22
@@ -XXX,XX +XXX,XX @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
135
BlockDriverState **file)
136
{
137
IO_CODE();
138
+ GRAPH_RDLOCK_GUARD();
139
return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum,
140
map, file);
141
}
142
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk,
143
int64_t bytes, int64_t *pnum)
144
{
145
IO_CODE();
146
+ GRAPH_RDLOCK_GUARD();
147
return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset,
148
bytes, pnum);
149
}
150
diff --git a/block/block-copy.c b/block/block-copy.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/block/block-copy.c
153
+++ b/block/block-copy.c
154
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
155
return ret;
156
}
157
158
-static coroutine_fn int block_copy_block_status(BlockCopyState *s,
159
- int64_t offset,
160
- int64_t bytes, int64_t *pnum)
161
+static coroutine_fn GRAPH_RDLOCK
162
+int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes,
163
+ int64_t *pnum)
164
{
165
int64_t num;
166
BlockDriverState *base;
167
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_block_status(BlockCopyState *s,
168
* Check if the cluster starting at offset is allocated or not.
169
* return via pnum the number of contiguous clusters sharing this allocation.
170
*/
171
-static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
172
- int64_t offset,
173
- int64_t *pnum)
174
+static int coroutine_fn GRAPH_RDLOCK
175
+block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
176
+ int64_t *pnum)
177
{
178
BlockDriverState *bs = s->source->bs;
179
int64_t count, total_count = 0;
180
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
181
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
182
183
while (true) {
184
+ /* protected in backup_run() */
185
ret = bdrv_co_is_allocated(bs, offset, bytes, &count);
186
if (ret < 0) {
187
return ret;
188
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
189
* Returns 1 if dirty clusters found and successfully copied, 0 if no dirty
190
* clusters found and -errno on failure.
191
*/
192
-static int coroutine_fn
193
+static int coroutine_fn GRAPH_RDLOCK
194
block_copy_dirty_clusters(BlockCopyCallState *call_state)
195
{
196
BlockCopyState *s = call_state->s;
197
@@ -XXX,XX +XXX,XX @@ void block_copy_kick(BlockCopyCallState *call_state)
198
* it means that some I/O operation failed in context of _this_ block_copy call,
199
* not some parallel operation.
200
*/
201
-static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
202
+static int coroutine_fn GRAPH_RDLOCK
203
+block_copy_common(BlockCopyCallState *call_state)
204
{
205
int ret;
206
BlockCopyState *s = call_state->s;
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
208
209
static void coroutine_fn block_copy_async_co_entry(void *opaque)
210
{
211
+ GRAPH_RDLOCK_GUARD();
212
block_copy_common(opaque);
213
}
214
215
diff --git a/block/io.c b/block/io.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/io.c
218
+++ b/block/io.c
219
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
220
* BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are
221
* set to the host mapping and BDS corresponding to the guest offset.
222
*/
223
-static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
224
- bool want_zero,
225
- int64_t offset, int64_t bytes,
226
- int64_t *pnum, int64_t *map,
227
- BlockDriverState **file)
228
+static int coroutine_fn GRAPH_RDLOCK
229
+bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
230
+ int64_t offset, int64_t bytes,
231
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
232
{
233
int64_t total_size;
234
int64_t n; /* bytes */
235
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
236
bool has_filtered_child;
237
238
assert(pnum);
239
+ assert_bdrv_graph_readable();
240
*pnum = 0;
241
total_size = bdrv_getlength(bs);
242
if (total_size < 0) {
243
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
244
IO_CODE();
245
246
assert(!include_base || base); /* Can't include NULL base */
247
+ assert_bdrv_graph_readable();
248
249
if (!depth) {
250
depth = &dummy;
251
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
252
int64_t pnum = bytes;
253
IO_CODE();
254
255
+ assume_graph_lock(); /* FIXME */
256
+
257
if (!bytes) {
258
return 1;
259
}
23
}
260
diff --git a/block/mirror.c b/block/mirror.c
24
261
index XXXXXXX..XXXXXXX 100644
25
if (!blk->allow_write_beyond_eof) {
262
--- a/block/mirror.c
26
- len = blk_getlength(blk);
263
+++ b/block/mirror.c
27
+ len = bdrv_getlength(blk_bs(blk));
264
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
28
if (len < 0) {
265
MirrorMethod mirror_method = MIRROR_METHOD_COPY;
29
return len;
266
267
assert(!(offset % s->granularity));
268
- ret = bdrv_block_status_above(source, NULL, offset,
269
- nb_chunks * s->granularity,
270
- &io_bytes, NULL, NULL);
271
+ WITH_GRAPH_RDLOCK_GUARD() {
272
+ ret = bdrv_block_status_above(source, NULL, offset,
273
+ nb_chunks * s->granularity,
274
+ &io_bytes, NULL, NULL);
275
+ }
276
if (ret < 0) {
277
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
278
} else if (ret & BDRV_BLOCK_DATA) {
279
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
280
return 0;
281
}
30
}
282
283
- ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes,
284
- &count);
285
+ WITH_GRAPH_RDLOCK_GUARD() {
286
+ ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset,
287
+ bytes, &count);
288
+ }
289
if (ret < 0) {
290
return ret;
291
}
292
diff --git a/block/qcow.c b/block/qcow.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/block/qcow.c
295
+++ b/block/qcow.c
296
@@ -XXX,XX +XXX,XX @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
297
return 1;
298
}
299
300
-static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
301
- bool want_zero,
302
- int64_t offset, int64_t bytes,
303
- int64_t *pnum, int64_t *map,
304
- BlockDriverState **file)
305
+static int coroutine_fn GRAPH_RDLOCK
306
+qcow_co_block_status(BlockDriverState *bs, bool want_zero,
307
+ int64_t offset, int64_t bytes, int64_t *pnum,
308
+ int64_t *map, BlockDriverState **file)
309
{
310
BDRVQcowState *s = bs->opaque;
311
int index_in_cluster, ret;
312
int64_t n;
313
uint64_t cluster_offset;
314
315
- assume_graph_lock(); /* FIXME */
316
-
317
qemu_co_mutex_lock(&s->lock);
318
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
319
qemu_co_mutex_unlock(&s->lock);
320
diff --git a/block/quorum.c b/block/quorum.c
321
index XXXXXXX..XXXXXXX 100644
322
--- a/block/quorum.c
323
+++ b/block/quorum.c
324
@@ -XXX,XX +XXX,XX @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
325
* return BDRV_BLOCK_ZERO if *all* children agree that a certain
326
* region contains zeroes, and BDRV_BLOCK_DATA otherwise.
327
*/
328
-static int coroutine_fn quorum_co_block_status(BlockDriverState *bs,
329
- bool want_zero,
330
- int64_t offset, int64_t count,
331
- int64_t *pnum, int64_t *map,
332
- BlockDriverState **file)
333
+static int coroutine_fn GRAPH_RDLOCK
334
+quorum_co_block_status(BlockDriverState *bs, bool want_zero,
335
+ int64_t offset, int64_t count,
336
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
337
{
338
BDRVQuorumState *s = bs->opaque;
339
int i, ret;
340
diff --git a/block/stream.c b/block/stream.c
341
index XXXXXXX..XXXXXXX 100644
342
--- a/block/stream.c
343
+++ b/block/stream.c
344
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
345
346
copy = false;
347
348
- ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
349
- if (ret == 1) {
350
- /* Allocated in the top, no need to copy. */
351
- } else if (ret >= 0) {
352
- /* Copy if allocated in the intermediate images. Limit to the
353
- * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */
354
- ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
355
- s->base_overlay, true,
356
- offset, n, &n);
357
- /* Finish early if end of backing file has been reached */
358
- if (ret == 0 && n == 0) {
359
- n = len - offset;
360
+ WITH_GRAPH_RDLOCK_GUARD() {
361
+ ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
362
+ if (ret == 1) {
363
+ /* Allocated in the top, no need to copy. */
364
+ } else if (ret >= 0) {
365
+ /*
366
+ * Copy if allocated in the intermediate images. Limit to the
367
+ * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE).
368
+ */
369
+ ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
370
+ s->base_overlay, true,
371
+ offset, n, &n);
372
+ /* Finish early if end of backing file has been reached */
373
+ if (ret == 0 && n == 0) {
374
+ n = len - offset;
375
+ }
376
+
377
+ copy = (ret > 0);
378
}
379
-
380
- copy = (ret > 0);
381
}
382
trace_stream_one_iteration(s, offset, n, ret);
383
if (copy) {
384
diff --git a/qemu-img.c b/qemu-img.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/qemu-img.c
387
+++ b/qemu-img.c
388
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
389
qemu_co_mutex_unlock(&s->lock);
390
break;
391
}
392
- n = convert_iteration_sectors(s, s->sector_num);
393
+ WITH_GRAPH_RDLOCK_GUARD() {
394
+ n = convert_iteration_sectors(s, s->sector_num);
395
+ }
396
if (n < 0) {
397
qemu_co_mutex_unlock(&s->lock);
398
s->ret = n;
399
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/tests/unit/test-block-iothread.c
402
+++ b/tests/unit/test-block-iothread.c
403
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_truncate(BlockBackend *blk)
404
g_assert_cmpint(ret, ==, -EINVAL);
405
}
406
407
-static void test_sync_op_block_status(BdrvChild *c)
408
+/* Disable TSA to make bdrv_test.bdrv_co_block_status writable */
409
+static void TSA_NO_TSA test_sync_op_block_status(BdrvChild *c)
410
{
411
int ret;
412
int64_t n;
413
--
31
--
414
2.39.2
32
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_pread*/pwrite*() need to hold a reader lock for the graph.
3
2
4
For some places, we know that they will hold the lock, but we don't have
3
In some places we are sure we are always running in a
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
4
coroutine, therefore it's useless to call the generated_co_wrapper,
6
with a FIXME comment. These places will be removed once everything is
5
instead call directly the _co_ function.
7
properly annotated.
8
6
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230203152202.49054-12-kwolf@redhat.com>
9
Message-Id: <20230113204212.359076-9-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
block/qcow2.h | 9 ++---
13
block/block-backend.c | 6 +++---
15
block/qed.h | 18 +++++-----
14
block/io.c | 4 ++--
16
include/block/block_int-io.h | 14 ++++----
15
block/preallocate.c | 6 +++---
17
block/blkdebug.c | 4 +--
16
block/qed.c | 2 +-
18
block/blklogwrites.c | 7 ++--
17
4 files changed, 9 insertions(+), 9 deletions(-)
19
block/blkreplay.c | 10 +++---
20
block/block-backend.c | 2 ++
21
block/bochs.c | 2 +-
22
block/commit.c | 5 +--
23
block/copy-before-write.c | 16 ++++-----
24
block/copy-on-read.c | 26 ++++++---------
25
block/crypto.c | 4 +--
26
block/filter-compress.c | 19 +++++------
27
block/io.c | 7 ++--
28
block/mirror.c | 18 +++++-----
29
block/parallels.c | 8 +++--
30
block/preallocate.c | 18 +++++-----
31
block/qcow.c | 8 ++---
32
block/qcow2-cluster.c | 7 ++--
33
block/qcow2.c | 53 +++++++++++++++--------------
34
block/qed-table.c | 4 +--
35
block/qed.c | 31 +++++++++--------
36
block/quorum.c | 29 ++++++++++------
37
block/raw-format.c | 12 +++----
38
block/replication.c | 15 ++++-----
39
block/throttle.c | 21 +++++-------
40
block/vdi.c | 4 +--
41
block/vhdx.c | 11 +++---
42
block/vmdk.c | 65 +++++++++++++++---------------------
43
block/vpc.c | 4 +--
44
tests/unit/test-bdrv-drain.c | 20 ++++++-----
45
31 files changed, 233 insertions(+), 238 deletions(-)
46
18
47
diff --git a/block/qcow2.h b/block/qcow2.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/qcow2.h
50
+++ b/block/qcow2.h
51
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
52
Error **errp);
53
54
/* qcow2-refcount.c functions */
55
-int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
56
+int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs);
57
void qcow2_refcount_close(BlockDriverState *bs);
58
59
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
60
@@ -XXX,XX +XXX,XX @@ void qcow2_free_snapshots(BlockDriverState *bs);
61
int qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
62
int qcow2_write_snapshots(BlockDriverState *bs);
63
64
-int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
65
- BdrvCheckResult *result,
66
- BdrvCheckMode fix);
67
+int coroutine_fn GRAPH_RDLOCK
68
+qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
69
+ BdrvCheckMode fix);
70
+
71
int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
72
BdrvCheckResult *result,
73
BdrvCheckMode fix);
74
diff --git a/block/qed.h b/block/qed.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/qed.h
77
+++ b/block/qed.h
78
@@ -XXX,XX +XXX,XX @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
79
/**
80
* Table I/O functions
81
*/
82
-int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
83
+int coroutine_fn GRAPH_RDLOCK qed_read_l1_table_sync(BDRVQEDState *s);
84
85
int coroutine_fn GRAPH_RDLOCK
86
qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
87
@@ -XXX,XX +XXX,XX @@ qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
88
int coroutine_fn GRAPH_RDLOCK
89
qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
90
91
-int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
92
- uint64_t offset);
93
-int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
94
- uint64_t offset);
95
+int coroutine_fn GRAPH_RDLOCK
96
+qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
97
+
98
+int coroutine_fn GRAPH_RDLOCK
99
+qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
100
101
int coroutine_fn GRAPH_RDLOCK
102
qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
103
@@ -XXX,XX +XXX,XX @@ qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
104
/**
105
* Cluster functions
106
*/
107
-int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
108
- uint64_t pos, size_t *len,
109
- uint64_t *img_offset);
110
+int coroutine_fn GRAPH_RDLOCK
111
+qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
112
+ size_t *len, uint64_t *img_offset);
113
114
/**
115
* Consistency check
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
117
int coroutine_fn GRAPH_RDLOCK
118
qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
119
120
-
121
QEDTable *qed_alloc_table(BDRVQEDState *s);
122
123
/**
124
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
125
index XXXXXXX..XXXXXXX 100644
126
--- a/include/block/block_int-io.h
127
+++ b/include/block/block_int-io.h
128
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
129
int64_t offset, int64_t bytes);
130
131
132
-int coroutine_fn bdrv_co_preadv(BdrvChild *child,
133
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv(BdrvChild *child,
134
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
135
BdrvRequestFlags flags);
136
-int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
137
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_part(BdrvChild *child,
138
int64_t offset, int64_t bytes,
139
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
140
-int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
141
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev(BdrvChild *child,
142
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
143
BdrvRequestFlags flags);
144
-int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
145
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev_part(BdrvChild *child,
146
int64_t offset, int64_t bytes,
147
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
148
149
-static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
150
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pread(BdrvChild *child,
151
int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags)
152
{
153
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
154
IO_CODE();
155
+ assert_bdrv_graph_readable();
156
157
return bdrv_co_preadv(child, offset, bytes, &qiov, flags);
158
}
159
160
-static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
161
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pwrite(BdrvChild *child,
162
int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags)
163
{
164
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
165
IO_CODE();
166
+ assert_bdrv_graph_readable();
167
168
return bdrv_co_pwritev(child, offset, bytes, &qiov, flags);
169
}
170
diff --git a/block/blkdebug.c b/block/blkdebug.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/blkdebug.c
173
+++ b/block/blkdebug.c
174
@@ -XXX,XX +XXX,XX @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
175
return -error;
176
}
177
178
-static int coroutine_fn
179
+static int coroutine_fn GRAPH_RDLOCK
180
blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
181
QEMUIOVector *qiov, BdrvRequestFlags flags)
182
{
183
@@ -XXX,XX +XXX,XX @@ blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
184
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
185
}
186
187
-static int coroutine_fn
188
+static int coroutine_fn GRAPH_RDLOCK
189
blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
190
QEMUIOVector *qiov, BdrvRequestFlags flags)
191
{
192
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/blklogwrites.c
195
+++ b/block/blklogwrites.c
196
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
197
bs->bl.request_alignment = s->sectorsize;
198
}
199
200
-static int coroutine_fn
201
+static int coroutine_fn GRAPH_RDLOCK
202
blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
203
QEMUIOVector *qiov, BdrvRequestFlags flags)
204
{
205
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
206
return fr.file_ret;
207
}
208
209
-static int coroutine_fn
210
+static int coroutine_fn GRAPH_RDLOCK
211
blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
212
{
213
return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes,
214
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
215
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
216
}
217
218
-static int coroutine_fn
219
+static int coroutine_fn GRAPH_RDLOCK
220
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
221
QEMUIOVector *qiov, BdrvRequestFlags flags)
222
{
223
- assume_graph_lock(); /* FIXME */
224
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
225
blk_log_writes_co_do_file_pwritev, 0, false);
226
}
227
diff --git a/block/blkreplay.c b/block/blkreplay.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/block/blkreplay.c
230
+++ b/block/blkreplay.c
231
@@ -XXX,XX +XXX,XX @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs,
232
replay_block_event(req->bh, reqid);
233
}
234
235
-static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
236
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
237
+static int coroutine_fn GRAPH_RDLOCK
238
+blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
239
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
240
{
241
uint64_t reqid = blkreplay_next_id();
242
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
243
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
244
return ret;
245
}
246
247
-static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
248
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
249
+static int coroutine_fn GRAPH_RDLOCK
250
+blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
251
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
252
{
253
uint64_t reqid = blkreplay_next_id();
254
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
255
diff --git a/block/block-backend.c b/block/block-backend.c
19
diff --git a/block/block-backend.c b/block/block-backend.c
256
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
257
--- a/block/block-backend.c
21
--- a/block/block-backend.c
258
+++ b/block/block-backend.c
22
+++ b/block/block-backend.c
259
@@ -XXX,XX +XXX,XX @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
23
@@ -XXX,XX +XXX,XX @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
260
IO_CODE();
24
blk->disable_request_queuing = disable;
261
262
blk_wait_while_drained(blk);
263
+ GRAPH_RDLOCK_GUARD();
264
265
/* Call blk_bs() only after waiting, the graph may have changed */
266
bs = blk_bs(blk);
267
@@ -XXX,XX +XXX,XX @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
268
IO_CODE();
269
270
blk_wait_while_drained(blk);
271
+ GRAPH_RDLOCK_GUARD();
272
273
/* Call blk_bs() only after waiting, the graph may have changed */
274
bs = blk_bs(blk);
275
diff --git a/block/bochs.c b/block/bochs.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/block/bochs.c
278
+++ b/block/bochs.c
279
@@ -XXX,XX +XXX,XX @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
280
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
281
}
25
}
282
26
283
-static int coroutine_fn
27
-static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
284
+static int coroutine_fn GRAPH_RDLOCK
28
- int64_t bytes)
285
bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
29
+static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
286
QEMUIOVector *qiov, BdrvRequestFlags flags)
30
+ int64_t offset, int64_t bytes)
287
{
31
{
288
diff --git a/block/commit.c b/block/commit.c
32
int64_t len;
289
index XXXXXXX..XXXXXXX 100644
33
290
--- a/block/commit.c
34
@@ -XXX,XX +XXX,XX @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
291
+++ b/block/commit.c
35
}
292
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver commit_job_driver = {
36
293
},
37
if (!blk->allow_write_beyond_eof) {
294
};
38
- len = bdrv_getlength(blk_bs(blk));
295
39
+ len = bdrv_co_getlength(blk_bs(blk));
296
-static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
40
if (len < 0) {
297
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
41
return len;
298
+static int coroutine_fn GRAPH_RDLOCK
42
}
299
+bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
300
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
301
{
302
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
303
}
304
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
305
index XXXXXXX..XXXXXXX 100644
306
--- a/block/copy-before-write.c
307
+++ b/block/copy-before-write.c
308
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVCopyBeforeWriteState {
309
int snapshot_error;
310
} BDRVCopyBeforeWriteState;
311
312
-static coroutine_fn int cbw_co_preadv(
313
- BlockDriverState *bs, int64_t offset, int64_t bytes,
314
- QEMUIOVector *qiov, BdrvRequestFlags flags)
315
+static int coroutine_fn GRAPH_RDLOCK
316
+cbw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
317
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
318
{
319
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
320
}
321
@@ -XXX,XX +XXX,XX @@ cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
322
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
323
}
324
325
-static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
326
- int64_t offset,
327
- int64_t bytes,
328
- QEMUIOVector *qiov,
329
- BdrvRequestFlags flags)
330
+static coroutine_fn GRAPH_RDLOCK
331
+int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
332
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
333
{
334
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
335
if (ret < 0) {
336
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
337
BdrvChild *file;
338
int ret;
339
340
+ assume_graph_lock(); /* FIXME */
341
+
342
/* TODO: upgrade to async loop using AioTask */
343
while (bytes) {
344
int64_t cur_bytes;
345
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/block/copy-on-read.c
348
+++ b/block/copy-on-read.c
349
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
350
}
351
352
353
-static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
354
- int64_t offset, int64_t bytes,
355
- QEMUIOVector *qiov,
356
- size_t qiov_offset,
357
- BdrvRequestFlags flags)
358
+static int coroutine_fn GRAPH_RDLOCK
359
+cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
360
+ QEMUIOVector *qiov, size_t qiov_offset,
361
+ BdrvRequestFlags flags)
362
{
363
int64_t n;
364
int local_flags;
365
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
366
}
367
368
369
-static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
370
- int64_t offset,
371
- int64_t bytes,
372
- QEMUIOVector *qiov,
373
- size_t qiov_offset,
374
- BdrvRequestFlags flags)
375
+static int coroutine_fn GRAPH_RDLOCK
376
+cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
377
+ QEMUIOVector *qiov, size_t qiov_offset,
378
+ BdrvRequestFlags flags)
379
{
380
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
381
flags);
382
@@ -XXX,XX +XXX,XX @@ cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
383
}
384
385
386
-static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
387
- int64_t offset,
388
- int64_t bytes,
389
- QEMUIOVector *qiov)
390
+static int coroutine_fn GRAPH_RDLOCK
391
+cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
392
+ QEMUIOVector *qiov)
393
{
394
return bdrv_co_pwritev(bs->file, offset, bytes, qiov,
395
BDRV_REQ_WRITE_COMPRESSED);
396
diff --git a/block/crypto.c b/block/crypto.c
397
index XXXXXXX..XXXXXXX 100644
398
--- a/block/crypto.c
399
+++ b/block/crypto.c
400
@@ -XXX,XX +XXX,XX @@ static int block_crypto_reopen_prepare(BDRVReopenState *state,
401
*/
402
#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
403
404
-static coroutine_fn int
405
+static int coroutine_fn GRAPH_RDLOCK
406
block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
407
QEMUIOVector *qiov, BdrvRequestFlags flags)
408
{
409
@@ -XXX,XX +XXX,XX @@ block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
410
}
411
412
413
-static coroutine_fn int
414
+static int coroutine_fn GRAPH_RDLOCK
415
block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
416
QEMUIOVector *qiov, BdrvRequestFlags flags)
417
{
418
diff --git a/block/filter-compress.c b/block/filter-compress.c
419
index XXXXXXX..XXXXXXX 100644
420
--- a/block/filter-compress.c
421
+++ b/block/filter-compress.c
422
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
423
}
424
425
426
-static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
427
- int64_t offset, int64_t bytes,
428
- QEMUIOVector *qiov,
429
- size_t qiov_offset,
430
- BdrvRequestFlags flags)
431
+static int coroutine_fn GRAPH_RDLOCK
432
+compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
433
+ QEMUIOVector *qiov, size_t qiov_offset,
434
+ BdrvRequestFlags flags)
435
{
436
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
437
flags);
438
}
439
440
441
-static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
442
- int64_t offset,
443
- int64_t bytes,
444
- QEMUIOVector *qiov,
445
- size_t qiov_offset,
446
- BdrvRequestFlags flags)
447
+static int coroutine_fn GRAPH_RDLOCK
448
+compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
449
+ QEMUIOVector *qiov, size_t qiov_offset,
450
+ BdrvRequestFlags flags)
451
{
452
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
453
flags | BDRV_REQ_WRITE_COMPRESSED);
454
diff --git a/block/io.c b/block/io.c
43
diff --git a/block/io.c b/block/io.c
455
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
456
--- a/block/io.c
45
--- a/block/io.c
457
+++ b/block/io.c
46
+++ b/block/io.c
458
@@ -XXX,XX +XXX,XX @@ bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
47
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
459
unsigned int nb_sectors;
48
if (new_bytes && backing) {
460
QEMUIOVector local_qiov;
49
int64_t backing_len;
461
int ret;
50
462
+ assert_bdrv_graph_readable();
51
- backing_len = bdrv_getlength(backing->bs);
463
52
+ backing_len = bdrv_co_getlength(backing->bs);
464
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
53
if (backing_len < 0) {
465
assert(!(flags & ~bs->supported_read_flags));
54
ret = backing_len;
466
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
55
error_setg_errno(errp, -ret, "Could not get backing file size");
467
unsigned int nb_sectors;
56
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
468
QEMUIOVector local_qiov;
57
goto out;
469
int ret;
58
}
470
+ assert_bdrv_graph_readable();
59
471
60
- ret = bdrv_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
472
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
61
+ ret = bdrv_co_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
473
62
if (ret < 0) {
474
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
63
error_setg_errno(errp, -ret, "Could not refresh total sector count");
475
BlockDriver *drv = bs->drv;
64
} else {
476
QEMUIOVector local_qiov;
477
int ret;
478
+ assert_bdrv_graph_readable();
479
480
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
481
482
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
483
int ret;
484
IO_CODE();
485
486
- assume_graph_lock(); /* FIXME */
487
-
488
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
489
490
if (!bdrv_co_is_inserted(bs)) {
491
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
492
bool padded = false;
493
IO_CODE();
494
495
- assume_graph_lock(); /* FIXME */
496
-
497
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
498
499
if (!bdrv_co_is_inserted(bs)) {
500
diff --git a/block/mirror.c b/block/mirror.c
501
index XXXXXXX..XXXXXXX 100644
502
--- a/block/mirror.c
503
+++ b/block/mirror.c
504
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_co_read(void *opaque)
505
op->is_in_flight = true;
506
trace_mirror_one_iteration(s, op->offset, op->bytes);
507
508
- ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
509
- &op->qiov, 0);
510
+ WITH_GRAPH_RDLOCK_GUARD() {
511
+ ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
512
+ &op->qiov, 0);
513
+ }
514
mirror_read_complete(op, ret);
515
}
516
517
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn active_write_settle(MirrorOp *op)
518
g_free(op);
519
}
520
521
-static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
522
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
523
+static int coroutine_fn GRAPH_RDLOCK
524
+bdrv_mirror_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
525
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
526
{
527
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
528
}
529
@@ -XXX,XX +XXX,XX @@ out:
530
return ret;
531
}
532
533
-static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
534
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
535
+static int coroutine_fn GRAPH_RDLOCK
536
+bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
537
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
538
{
539
MirrorBDSOpaque *s = bs->opaque;
540
QEMUIOVector bounce_qiov;
541
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
542
int ret = 0;
543
bool copy_to_target = false;
544
545
- assume_graph_lock(); /* FIXME */
546
-
547
if (s->job) {
548
copy_to_target = s->job->ret >= 0 &&
549
!job_is_cancelled(&s->job->common.job) &&
550
diff --git a/block/parallels.c b/block/parallels.c
551
index XXXXXXX..XXXXXXX 100644
552
--- a/block/parallels.c
553
+++ b/block/parallels.c
554
@@ -XXX,XX +XXX,XX @@ allocate_clusters(BlockDriverState *bs, int64_t sector_num,
555
}
556
557
558
-static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
559
+static int coroutine_fn GRAPH_RDLOCK
560
+parallels_co_flush_to_os(BlockDriverState *bs)
561
{
562
BDRVParallelsState *s = bs->opaque;
563
unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
564
@@ -XXX,XX +XXX,XX @@ parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
565
return ret;
566
}
567
568
-static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
569
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
570
+static int coroutine_fn GRAPH_RDLOCK
571
+parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
572
+ QEMUIOVector *qiov)
573
{
574
BDRVParallelsState *s = bs->opaque;
575
uint64_t bytes_done = 0;
576
diff --git a/block/preallocate.c b/block/preallocate.c
65
diff --git a/block/preallocate.c b/block/preallocate.c
577
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
578
--- a/block/preallocate.c
67
--- a/block/preallocate.c
579
+++ b/block/preallocate.c
68
+++ b/block/preallocate.c
580
@@ -XXX,XX +XXX,XX @@ static void preallocate_reopen_abort(BDRVReopenState *state)
69
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
581
state->opaque = NULL;
582
}
583
584
-static coroutine_fn int preallocate_co_preadv_part(
585
- BlockDriverState *bs, int64_t offset, int64_t bytes,
586
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
587
+static int coroutine_fn GRAPH_RDLOCK
588
+preallocate_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
589
+ QEMUIOVector *qiov, size_t qiov_offset,
590
+ BdrvRequestFlags flags)
591
{
592
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
593
flags);
594
@@ -XXX,XX +XXX,XX @@ preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
595
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
596
}
597
598
-static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
599
- int64_t offset,
600
- int64_t bytes,
601
- QEMUIOVector *qiov,
602
- size_t qiov_offset,
603
- BdrvRequestFlags flags)
604
+static int coroutine_fn GRAPH_RDLOCK
605
+preallocate_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
606
+ QEMUIOVector *qiov, size_t qiov_offset,
607
+ BdrvRequestFlags flags)
608
{
609
- assume_graph_lock(); /* FIXME */
610
handle_write(bs, offset, bytes, false);
611
612
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
613
diff --git a/block/qcow.c b/block/qcow.c
614
index XXXXXXX..XXXXXXX 100644
615
--- a/block/qcow.c
616
+++ b/block/qcow.c
617
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
618
619
static QemuOptsList qcow_create_opts;
620
621
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
622
- uint64_t cluster_offset);
623
+static int coroutine_fn GRAPH_RDLOCK
624
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
625
626
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
627
{
628
@@ -XXX,XX +XXX,XX @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
629
return 0;
630
}
631
632
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
633
- uint64_t cluster_offset)
634
+static int coroutine_fn GRAPH_RDLOCK
635
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
636
{
637
BDRVQcowState *s = bs->opaque;
638
int ret, csize;
639
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
640
index XXXXXXX..XXXXXXX 100644
641
--- a/block/qcow2-cluster.c
642
+++ b/block/qcow2-cluster.c
643
@@ -XXX,XX +XXX,XX @@ do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset,
644
return 0;
645
}
646
647
-static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
648
- uint64_t cluster_offset,
649
- unsigned offset_in_cluster,
650
- QEMUIOVector *qiov)
651
+static int coroutine_fn GRAPH_RDLOCK
652
+do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset,
653
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
654
{
655
BDRVQcow2State *s = bs->opaque;
656
int ret;
657
diff --git a/block/qcow2.c b/block/qcow2.c
658
index XXXXXXX..XXXXXXX 100644
659
--- a/block/qcow2.c
660
+++ b/block/qcow2.c
661
@@ -XXX,XX +XXX,XX @@ static void qcow2_add_check_result(BdrvCheckResult *out,
662
}
70
}
663
}
71
664
72
if (s->data_end < 0) {
665
-static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
73
- s->data_end = bdrv_getlength(bs->file->bs);
666
- BdrvCheckResult *result,
74
+ s->data_end = bdrv_co_getlength(bs->file->bs);
667
- BdrvCheckMode fix)
75
if (s->data_end < 0) {
668
+static int coroutine_fn GRAPH_RDLOCK
76
return false;
669
+qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckResult *result,
77
}
670
+ BdrvCheckMode fix)
78
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
671
{
79
}
672
BdrvCheckResult snapshot_res = {};
80
673
BdrvCheckResult refcount_res = {};
81
if (s->file_end < 0) {
674
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
82
- s->file_end = bdrv_getlength(bs->file->bs);
675
return ret;
83
+ s->file_end = bdrv_co_getlength(bs->file->bs);
676
}
84
if (s->file_end < 0) {
677
85
return false;
678
-static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
86
}
679
- BdrvCheckResult *result,
87
@@ -XXX,XX +XXX,XX @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
680
- BdrvCheckMode fix)
88
681
+static int coroutine_fn GRAPH_RDLOCK
89
if (s->data_end >= 0 && offset > s->data_end) {
682
+qcow2_co_check(BlockDriverState *bs, BdrvCheckResult *result,
90
if (s->file_end < 0) {
683
+ BdrvCheckMode fix)
91
- s->file_end = bdrv_getlength(bs->file->bs);
684
{
92
+ s->file_end = bdrv_co_getlength(bs->file->bs);
685
BDRVQcow2State *s = bs->opaque;
93
if (s->file_end < 0) {
686
int ret;
94
error_setg(errp, "failed to get file length");
687
@@ -XXX,XX +XXX,XX @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp)
95
return s->file_end;
688
}
689
690
/* Called with s->lock held. */
691
-static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
692
- int flags, bool open_data_file,
693
- Error **errp)
694
+static int coroutine_fn GRAPH_RDLOCK
695
+qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
696
+ bool open_data_file, Error **errp)
697
{
698
ERRP_GUARD();
699
BDRVQcow2State *s = bs->opaque;
700
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qcow2_open_entry(void *opaque)
701
QCow2OpenCo *qoc = opaque;
702
BDRVQcow2State *s = qoc->bs->opaque;
703
704
+ assume_graph_lock(); /* FIXME */
705
+
706
qemu_co_mutex_lock(&s->lock);
707
qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
708
qoc->errp);
709
@@ -XXX,XX +XXX,XX @@ out:
710
return ret;
711
}
712
713
-static coroutine_fn int
714
+static int coroutine_fn GRAPH_RDLOCK
715
qcow2_co_preadv_encrypted(BlockDriverState *bs,
716
uint64_t host_offset,
717
uint64_t offset,
718
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
719
return 0;
720
}
721
722
-static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
723
- QCow2SubclusterType subc_type,
724
- uint64_t host_offset,
725
- uint64_t offset, uint64_t bytes,
726
- QEMUIOVector *qiov,
727
- size_t qiov_offset)
728
+static int coroutine_fn GRAPH_RDLOCK
729
+qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type,
730
+ uint64_t host_offset, uint64_t offset, uint64_t bytes,
731
+ QEMUIOVector *qiov, size_t qiov_offset)
732
{
733
BDRVQcow2State *s = bs->opaque;
734
735
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
736
g_assert_not_reached();
737
}
738
739
-static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
740
+/*
741
+ * This function can count as GRAPH_RDLOCK because qcow2_co_preadv_part() holds
742
+ * the graph lock and keeps it until this coroutine has terminated.
743
+ */
744
+static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_task_entry(AioTask *task)
745
{
746
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
747
748
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
749
t->qiov, t->qiov_offset);
750
}
751
752
-static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
753
- int64_t offset, int64_t bytes,
754
- QEMUIOVector *qiov,
755
- size_t qiov_offset,
756
- BdrvRequestFlags flags)
757
+static int coroutine_fn GRAPH_RDLOCK
758
+qcow2_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
759
+ QEMUIOVector *qiov, size_t qiov_offset,
760
+ BdrvRequestFlags flags)
761
{
762
BDRVQcow2State *s = bs->opaque;
763
int ret = 0;
764
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
765
qcow2_do_close(bs, true);
766
}
767
768
-static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
769
- Error **errp)
770
+static void coroutine_fn GRAPH_RDLOCK
771
+qcow2_co_invalidate_cache(BlockDriverState *bs, Error **errp)
772
{
773
ERRP_GUARD();
774
BDRVQcow2State *s = bs->opaque;
775
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
776
return ret;
777
}
778
779
-static int coroutine_fn
780
+static int coroutine_fn GRAPH_RDLOCK
781
qcow2_co_preadv_compressed(BlockDriverState *bs,
782
uint64_t l2_entry,
783
uint64_t offset,
784
diff --git a/block/qed-table.c b/block/qed-table.c
785
index XXXXXXX..XXXXXXX 100644
786
--- a/block/qed-table.c
787
+++ b/block/qed-table.c
788
@@ -XXX,XX +XXX,XX @@
789
#include "qemu/memalign.h"
790
791
/* Called with table_lock held. */
792
-static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset,
793
- QEDTable *table)
794
+static int coroutine_fn GRAPH_RDLOCK
795
+qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
796
{
797
unsigned int bytes = s->header.cluster_size * s->header.table_size;
798
799
diff --git a/block/qed.c b/block/qed.c
96
diff --git a/block/qed.c b/block/qed.c
800
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
801
--- a/block/qed.c
98
--- a/block/qed.c
802
+++ b/block/qed.c
99
+++ b/block/qed.c
803
@@ -XXX,XX +XXX,XX @@ int qed_write_header_sync(BDRVQEDState *s)
100
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
804
*
805
* No new allocating reqs can start while this function runs.
806
*/
807
-static int coroutine_fn qed_write_header(BDRVQEDState *s)
808
+static int coroutine_fn GRAPH_RDLOCK qed_write_header(BDRVQEDState *s)
809
{
810
/* We must write full sectors for O_DIRECT but cannot necessarily generate
811
* the data following the header if an unrecognized compat feature is
812
@@ -XXX,XX +XXX,XX @@ fail:
813
return ret;
814
}
815
816
-static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs,
817
- bool want_zero,
818
- int64_t pos, int64_t bytes,
819
- int64_t *pnum, int64_t *map,
820
- BlockDriverState **file)
821
+static int coroutine_fn GRAPH_RDLOCK
822
+bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos,
823
+ int64_t bytes, int64_t *pnum, int64_t *map,
824
+ BlockDriverState **file)
825
{
826
BDRVQEDState *s = bs->opaque;
827
size_t len = MIN(bytes, SIZE_MAX);
828
@@ -XXX,XX +XXX,XX @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
829
* This function reads qiov->size bytes starting at pos from the backing file.
830
* If there is no backing file then zeroes are read.
831
*/
832
-static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
833
- QEMUIOVector *qiov)
834
+static int coroutine_fn GRAPH_RDLOCK
835
+qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov)
836
{
837
if (s->bs->backing) {
838
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
839
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
840
* @len: Number of bytes
841
* @offset: Byte offset in image file
842
*/
843
-static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
844
- uint64_t pos, uint64_t len,
845
- uint64_t offset)
846
+static int coroutine_fn GRAPH_RDLOCK
847
+qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len,
848
+ uint64_t offset)
849
{
850
QEMUIOVector qiov;
851
int ret;
852
@@ -XXX,XX +XXX,XX @@ qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
853
*
854
* Called with table_lock *not* held.
855
*/
856
-static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
857
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_main(QEDAIOCB *acb)
858
{
859
BDRVQEDState *s = acb_to_s(acb);
860
uint64_t offset = acb->cur_cluster +
861
@@ -XXX,XX +XXX,XX @@ qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
862
*
863
* Called with table_lock held.
864
*/
865
-static int coroutine_fn qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset,
866
- size_t len)
867
+static int coroutine_fn GRAPH_RDLOCK
868
+qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len)
869
{
870
BDRVQEDState *s = acb_to_s(acb);
871
int r;
872
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
873
*
874
* Called with table_lock held.
875
*/
876
-static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
877
- uint64_t offset, size_t len)
878
+static int coroutine_fn GRAPH_RDLOCK
879
+qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len)
880
{
881
QEDAIOCB *acb = opaque;
882
BDRVQEDState *s = acb_to_s(acb);
883
diff --git a/block/quorum.c b/block/quorum.c
884
index XXXXXXX..XXXXXXX 100644
885
--- a/block/quorum.c
886
+++ b/block/quorum.c
887
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad_versions(BDRVQuorumState *s,
888
}
101
}
889
}
102
890
103
/* Round down file size to the last cluster */
891
-static void coroutine_fn quorum_rewrite_entry(void *opaque)
104
- file_size = bdrv_getlength(bs->file->bs);
892
+/*
105
+ file_size = bdrv_co_getlength(bs->file->bs);
893
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
106
if (file_size < 0) {
894
+ * the graph lock and keeps it until this coroutine has terminated.
107
error_setg(errp, "Failed to get file length");
895
+ */
108
return file_size;
896
+static void coroutine_fn GRAPH_RDLOCK quorum_rewrite_entry(void *opaque)
897
{
898
QuorumCo *co = opaque;
899
QuorumAIOCB *acb = co->acb;
900
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn quorum_rewrite_entry(void *opaque)
901
}
902
}
903
904
-static bool quorum_rewrite_bad_versions(QuorumAIOCB *acb,
905
- QuorumVoteValue *value)
906
+static bool coroutine_fn GRAPH_RDLOCK
907
+quorum_rewrite_bad_versions(QuorumAIOCB *acb, QuorumVoteValue *value)
908
{
909
QuorumVoteVersion *version;
910
QuorumVoteItem *item;
911
@@ -XXX,XX +XXX,XX @@ static int quorum_vote_error(QuorumAIOCB *acb)
912
return ret;
913
}
914
915
-static void quorum_vote(QuorumAIOCB *acb)
916
+static void coroutine_fn GRAPH_RDLOCK quorum_vote(QuorumAIOCB *acb)
917
{
918
bool quorum = true;
919
int i, j, ret;
920
@@ -XXX,XX +XXX,XX @@ free_exit:
921
quorum_free_vote_list(&acb->votes);
922
}
923
924
-static void coroutine_fn read_quorum_children_entry(void *opaque)
925
+/*
926
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
927
+ * the graph lock and keeps it until this coroutine has terminated.
928
+ */
929
+static void coroutine_fn GRAPH_RDLOCK read_quorum_children_entry(void *opaque)
930
{
931
QuorumCo *co = opaque;
932
QuorumAIOCB *acb = co->acb;
933
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn read_quorum_children_entry(void *opaque)
934
}
935
}
936
937
-static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
938
+static int coroutine_fn GRAPH_RDLOCK read_quorum_children(QuorumAIOCB *acb)
939
{
940
BDRVQuorumState *s = acb->bs->opaque;
941
int i;
942
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
943
return acb->vote_ret;
944
}
945
946
-static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
947
+static int coroutine_fn GRAPH_RDLOCK read_fifo_child(QuorumAIOCB *acb)
948
{
949
BDRVQuorumState *s = acb->bs->opaque;
950
int n, ret;
951
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
952
return ret;
953
}
954
955
-static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
956
- int64_t offset, int64_t bytes,
957
- QEMUIOVector *qiov,
958
- BdrvRequestFlags flags)
959
+static int coroutine_fn GRAPH_RDLOCK
960
+quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
961
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
962
{
963
BDRVQuorumState *s = bs->opaque;
964
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
965
diff --git a/block/raw-format.c b/block/raw-format.c
966
index XXXXXXX..XXXXXXX 100644
967
--- a/block/raw-format.c
968
+++ b/block/raw-format.c
969
@@ -XXX,XX +XXX,XX @@ static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset,
970
return 0;
971
}
972
973
-static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
974
- int64_t bytes, QEMUIOVector *qiov,
975
- BdrvRequestFlags flags)
976
+static int coroutine_fn GRAPH_RDLOCK
977
+raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
978
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
979
{
980
int ret;
981
982
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
983
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
984
}
985
986
-static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
987
- int64_t bytes, QEMUIOVector *qiov,
988
- BdrvRequestFlags flags)
989
+static int coroutine_fn GRAPH_RDLOCK
990
+raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
991
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
992
{
993
void *buf = NULL;
994
BlockDriver *drv;
995
diff --git a/block/replication.c b/block/replication.c
996
index XXXXXXX..XXXXXXX 100644
997
--- a/block/replication.c
998
+++ b/block/replication.c
999
@@ -XXX,XX +XXX,XX @@ static int replication_return_value(BDRVReplicationState *s, int ret)
1000
return ret;
1001
}
1002
1003
-static coroutine_fn int replication_co_readv(BlockDriverState *bs,
1004
- int64_t sector_num,
1005
- int remaining_sectors,
1006
- QEMUIOVector *qiov)
1007
+static int coroutine_fn GRAPH_RDLOCK
1008
+replication_co_readv(BlockDriverState *bs, int64_t sector_num,
1009
+ int remaining_sectors, QEMUIOVector *qiov)
1010
{
1011
BDRVReplicationState *s = bs->opaque;
1012
int ret;
1013
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
1014
return replication_return_value(s, ret);
1015
}
1016
1017
-static coroutine_fn int replication_co_writev(BlockDriverState *bs,
1018
- int64_t sector_num,
1019
- int remaining_sectors,
1020
- QEMUIOVector *qiov,
1021
- int flags)
1022
+static int coroutine_fn GRAPH_RDLOCK
1023
+replication_co_writev(BlockDriverState *bs, int64_t sector_num,
1024
+ int remaining_sectors, QEMUIOVector *qiov, int flags)
1025
{
1026
BDRVReplicationState *s = bs->opaque;
1027
QEMUIOVector hd_qiov;
1028
diff --git a/block/throttle.c b/block/throttle.c
1029
index XXXXXXX..XXXXXXX 100644
1030
--- a/block/throttle.c
1031
+++ b/block/throttle.c
1032
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
1033
return bdrv_co_getlength(bs->file->bs);
1034
}
1035
1036
-static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1037
- int64_t offset, int64_t bytes,
1038
- QEMUIOVector *qiov,
1039
- BdrvRequestFlags flags)
1040
+static int coroutine_fn GRAPH_RDLOCK
1041
+throttle_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1042
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1043
{
1044
1045
ThrottleGroupMember *tgm = bs->opaque;
1046
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1047
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
1048
}
1049
1050
-static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
1051
- int64_t offset, int64_t bytes,
1052
- QEMUIOVector *qiov,
1053
- BdrvRequestFlags flags)
1054
+static int coroutine_fn GRAPH_RDLOCK
1055
+throttle_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1056
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1057
{
1058
ThrottleGroupMember *tgm = bs->opaque;
1059
throttle_group_co_io_limits_intercept(tgm, bytes, true);
1060
@@ -XXX,XX +XXX,XX @@ throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
1061
return bdrv_co_pdiscard(bs->file, offset, bytes);
1062
}
1063
1064
-static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
1065
- int64_t offset,
1066
- int64_t bytes,
1067
- QEMUIOVector *qiov)
1068
+static int coroutine_fn GRAPH_RDLOCK
1069
+throttle_co_pwritev_compressed(BlockDriverState *bs, int64_t offset,
1070
+ int64_t bytes, QEMUIOVector *qiov)
1071
{
1072
return throttle_co_pwritev(bs, offset, bytes, qiov,
1073
BDRV_REQ_WRITE_COMPRESSED);
1074
diff --git a/block/vdi.c b/block/vdi.c
1075
index XXXXXXX..XXXXXXX 100644
1076
--- a/block/vdi.c
1077
+++ b/block/vdi.c
1078
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
1079
(s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
1080
}
1081
1082
-static int coroutine_fn
1083
+static int coroutine_fn GRAPH_RDLOCK
1084
vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1085
QEMUIOVector *qiov, BdrvRequestFlags flags)
1086
{
1087
@@ -XXX,XX +XXX,XX @@ vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1088
return ret;
1089
}
1090
1091
-static int coroutine_fn
1092
+static int coroutine_fn GRAPH_RDLOCK
1093
vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1094
QEMUIOVector *qiov, BdrvRequestFlags flags)
1095
{
1096
diff --git a/block/vhdx.c b/block/vhdx.c
1097
index XXXXXXX..XXXXXXX 100644
1098
--- a/block/vhdx.c
1099
+++ b/block/vhdx.c
1100
@@ -XXX,XX +XXX,XX @@ vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1101
}
1102
1103
1104
-static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
1105
- int nb_sectors, QEMUIOVector *qiov)
1106
+static int coroutine_fn GRAPH_RDLOCK
1107
+vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1108
+ QEMUIOVector *qiov)
1109
{
1110
BDRVVHDXState *s = bs->opaque;
1111
int ret = 0;
1112
@@ -XXX,XX +XXX,XX @@ int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s)
1113
return ret;
1114
}
1115
1116
-static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
1117
- int nb_sectors, QEMUIOVector *qiov,
1118
- int flags)
1119
+static int coroutine_fn GRAPH_RDLOCK
1120
+vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1121
+ QEMUIOVector *qiov, int flags)
1122
{
1123
int ret = -ENOTSUP;
1124
BDRVVHDXState *s = bs->opaque;
1125
diff --git a/block/vmdk.c b/block/vmdk.c
1126
index XXXXXXX..XXXXXXX 100644
1127
--- a/block/vmdk.c
1128
+++ b/block/vmdk.c
1129
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
1130
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
1131
* it for call to write user data in the request.
1132
*/
1133
-static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
1134
- VmdkExtent *extent,
1135
- uint64_t cluster_offset,
1136
- uint64_t offset,
1137
- uint64_t skip_start_bytes,
1138
- uint64_t skip_end_bytes,
1139
- bool zeroed)
1140
+static int coroutine_fn GRAPH_RDLOCK
1141
+get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent,
1142
+ uint64_t cluster_offset, uint64_t offset,
1143
+ uint64_t skip_start_bytes, uint64_t skip_end_bytes,
1144
+ bool zeroed)
1145
{
1146
int ret = VMDK_OK;
1147
int64_t cluster_bytes;
1148
@@ -XXX,XX +XXX,XX @@ vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset)
1149
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
1150
* VMDK_ERROR if failed.
1151
*/
1152
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
1153
- VmdkExtent *extent,
1154
- VmdkMetaData *m_data,
1155
- uint64_t offset,
1156
- bool allocate,
1157
- uint64_t *cluster_offset,
1158
- uint64_t skip_start_bytes,
1159
- uint64_t skip_end_bytes)
1160
+static int coroutine_fn GRAPH_RDLOCK
1161
+get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent,
1162
+ VmdkMetaData *m_data, uint64_t offset, bool allocate,
1163
+ uint64_t *cluster_offset, uint64_t skip_start_bytes,
1164
+ uint64_t skip_end_bytes)
1165
{
1166
unsigned int l1_index, l2_offset, l2_index;
1167
int min_index, i, j;
1168
@@ -XXX,XX +XXX,XX @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent,
1169
return extent_relative_offset % cluster_size;
1170
}
1171
1172
-static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
1173
- bool want_zero,
1174
- int64_t offset, int64_t bytes,
1175
- int64_t *pnum, int64_t *map,
1176
- BlockDriverState **file)
1177
+static int coroutine_fn GRAPH_RDLOCK
1178
+vmdk_co_block_status(BlockDriverState *bs, bool want_zero,
1179
+ int64_t offset, int64_t bytes, int64_t *pnum,
1180
+ int64_t *map, BlockDriverState **file)
1181
{
1182
BDRVVmdkState *s = bs->opaque;
1183
int64_t index_in_cluster, n, ret;
1184
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
1185
return ret;
1186
}
1187
1188
-static int coroutine_fn
1189
+static int coroutine_fn GRAPH_RDLOCK
1190
vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
1191
int64_t offset_in_cluster, QEMUIOVector *qiov,
1192
uint64_t qiov_offset, uint64_t n_bytes,
1193
@@ -XXX,XX +XXX,XX @@ vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
1194
return ret;
1195
}
1196
1197
-static int coroutine_fn
1198
+static int coroutine_fn GRAPH_RDLOCK
1199
vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1200
- int64_t offset_in_cluster, QEMUIOVector *qiov,
1201
- int bytes)
1202
+ int64_t offset_in_cluster, QEMUIOVector *qiov, int bytes)
1203
{
1204
int ret;
1205
int cluster_bytes, buf_bytes;
1206
@@ -XXX,XX +XXX,XX @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1207
return ret;
1208
}
1209
1210
-static int coroutine_fn
1211
+static int coroutine_fn GRAPH_RDLOCK
1212
vmdk_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1213
QEMUIOVector *qiov, BdrvRequestFlags flags)
1214
{
1215
@@ -XXX,XX +XXX,XX @@ fail:
1216
*
1217
* Returns: error code with 0 for success.
1218
*/
1219
-static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1220
- uint64_t bytes, QEMUIOVector *qiov,
1221
- bool zeroed, bool zero_dry_run)
1222
+static int coroutine_fn GRAPH_RDLOCK
1223
+vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1224
+ QEMUIOVector *qiov, bool zeroed, bool zero_dry_run)
1225
{
1226
BDRVVmdkState *s = bs->opaque;
1227
VmdkExtent *extent = NULL;
1228
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1229
uint64_t bytes_done = 0;
1230
VmdkMetaData m_data;
1231
1232
- assume_graph_lock(); /* FIXME */
1233
-
1234
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
1235
error_report("Wrong offset: offset=0x%" PRIx64
1236
" total_sectors=0x%" PRIx64,
1237
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1238
return 0;
1239
}
1240
1241
-static int coroutine_fn
1242
+static int coroutine_fn GRAPH_RDLOCK
1243
vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1244
QEMUIOVector *qiov, BdrvRequestFlags flags)
1245
{
1246
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
1247
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
1248
}
1249
1250
-static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
1251
- int64_t offset,
1252
- int64_t bytes,
1253
- BdrvRequestFlags flags)
1254
+static int coroutine_fn GRAPH_RDLOCK
1255
+vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
1256
+ BdrvRequestFlags flags)
1257
{
1258
int ret;
1259
BDRVVmdkState *s = bs->opaque;
1260
@@ -XXX,XX +XXX,XX @@ static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
1261
return info;
1262
}
1263
1264
-static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
1265
- BdrvCheckResult *result,
1266
- BdrvCheckMode fix)
1267
+static int coroutine_fn GRAPH_RDLOCK
1268
+vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix)
1269
{
1270
BDRVVmdkState *s = bs->opaque;
1271
VmdkExtent *extent = NULL;
1272
diff --git a/block/vpc.c b/block/vpc.c
1273
index XXXXXXX..XXXXXXX 100644
1274
--- a/block/vpc.c
1275
+++ b/block/vpc.c
1276
@@ -XXX,XX +XXX,XX @@ vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1277
return 0;
1278
}
1279
1280
-static int coroutine_fn
1281
+static int coroutine_fn GRAPH_RDLOCK
1282
vpc_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1283
QEMUIOVector *qiov, BdrvRequestFlags flags)
1284
{
1285
@@ -XXX,XX +XXX,XX @@ fail:
1286
return ret;
1287
}
1288
1289
-static int coroutine_fn
1290
+static int coroutine_fn GRAPH_RDLOCK
1291
vpc_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1292
QEMUIOVector *qiov, BdrvRequestFlags flags)
1293
{
1294
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
1295
index XXXXXXX..XXXXXXX 100644
1296
--- a/tests/unit/test-bdrv-drain.c
1297
+++ b/tests/unit/test-bdrv-drain.c
1298
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_top_close(BlockDriverState *bs)
1299
}
1300
}
1301
1302
-static int coroutine_fn bdrv_test_top_co_preadv(BlockDriverState *bs,
1303
- int64_t offset, int64_t bytes,
1304
- QEMUIOVector *qiov,
1305
- BdrvRequestFlags flags)
1306
+static int coroutine_fn GRAPH_RDLOCK
1307
+bdrv_test_top_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1308
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1309
{
1310
BDRVTestTopState *tts = bs->opaque;
1311
return bdrv_co_preadv(tts->wait_child, offset, bytes, qiov, flags);
1312
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
1313
void *buffer = g_malloc(65536);
1314
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
1315
1316
+ GRAPH_RDLOCK_GUARD();
1317
+
1318
/* Pretend some internal write operation from parent to child.
1319
* Important: We have to read from the child, not from the parent!
1320
* Draining works by first propagating it all up the tree to the
1321
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_test_close(BlockDriverState *bs)
1322
* Otherwise:
1323
* Set .has_read to true and return success.
1324
*/
1325
-static int coroutine_fn bdrv_replace_test_co_preadv(BlockDriverState *bs,
1326
- int64_t offset,
1327
- int64_t bytes,
1328
- QEMUIOVector *qiov,
1329
- BdrvRequestFlags flags)
1330
+static int coroutine_fn GRAPH_RDLOCK
1331
+bdrv_replace_test_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1332
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1333
{
1334
BDRVReplaceTestState *s = bs->opaque;
1335
1336
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_replace_test_read_entry(void *opaque)
1337
int ret;
1338
1339
/* Queue a read request post-drain */
1340
+ bdrv_graph_co_rdlock();
1341
ret = bdrv_replace_test_co_preadv(bs, 0, 1, &qiov, 0);
1342
+ bdrv_graph_co_rdunlock();
1343
+
1344
g_assert(ret >= 0);
1345
bdrv_dec_in_flight(bs);
1346
}
1347
--
109
--
1348
2.39.2
110
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_delete_file() need to hold a reader lock for the graph.
3
2
3
bdrv_get_allocated_file_size() is categorized as an I/O function, and it
4
currently doesn't run in a coroutine. We should let it take a graph
5
rdlock since it traverses the block nodes graph, which however is only
6
possible in a coroutine.
7
8
Therefore turn it into a co_wrapper to move the actual function into a
9
coroutine where the lock can be taken.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20230203152202.49054-22-kwolf@redhat.com>
13
Message-Id: <20230113204212.359076-10-kwolf@redhat.com>
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
16
---
9
include/block/block-io.h | 8 ++++++--
17
include/block/block-io.h | 4 +++-
10
include/block/block_int-common.h | 4 ++--
18
include/block/block_int-common.h | 4 +++-
11
block.c | 1 +
19
block.c | 12 ++++++------
12
3 files changed, 9 insertions(+), 4 deletions(-)
20
block/file-posix.c | 14 +++++---------
21
block/file-win32.c | 10 ++++------
22
block/gluster.c | 11 ++++++-----
23
block/nfs.c | 4 ++--
24
block/null.c | 7 ++++---
25
block/qcow2-refcount.c | 2 +-
26
block/vmdk.c | 9 +++++----
27
10 files changed, 39 insertions(+), 38 deletions(-)
13
28
14
diff --git a/include/block/block-io.h b/include/block/block-io.h
29
diff --git a/include/block/block-io.h b/include/block/block-io.h
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block-io.h
31
--- a/include/block/block-io.h
17
+++ b/include/block/block-io.h
32
+++ b/include/block/block-io.h
18
@@ -XXX,XX +XXX,XX @@ int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
33
@@ -XXX,XX +XXX,XX @@ int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
34
int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
35
int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
36
37
-int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
38
+int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
39
+int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
40
+
19
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
41
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
20
BlockDriverState *in_bs, Error **errp);
42
BlockDriverState *in_bs, Error **errp);
21
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
43
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
22
-int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
23
-void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs);
24
+
25
+int coroutine_fn GRAPH_RDLOCK
26
+bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
27
+
28
+void coroutine_fn GRAPH_RDLOCK
29
+bdrv_co_delete_file_noerr(BlockDriverState *bs);
30
31
32
/* async block I/O */
33
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
34
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
35
--- a/include/block/block_int-common.h
46
--- a/include/block/block_int-common.h
36
+++ b/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
37
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs);
49
bool exact, PreallocMode prealloc,
39
50
BdrvRequestFlags flags, Error **errp);
40
/* Delete a created file. */
51
int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
41
- int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
52
- int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
42
- Error **errp);
53
+ int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
43
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_delete_file)(
54
+ BlockDriverState *bs);
44
+ BlockDriverState *bs, Error **errp);
55
+
45
56
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
46
/*
57
Error **errp);
47
* Flushes all data that was already written to the OS all the way down to
58
48
diff --git a/block.c b/block.c
59
diff --git a/block.c b/block.c
49
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
50
--- a/block.c
61
--- a/block.c
51
+++ b/block.c
62
+++ b/block.c
52
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
63
@@ -XXX,XX +XXX,XX @@ exit:
53
64
}
65
66
/**
67
- * Implementation of BlockDriver.bdrv_get_allocated_file_size() that
68
+ * Implementation of BlockDriver.bdrv_co_get_allocated_file_size() that
69
* sums the size of all data-bearing children. (This excludes backing
70
* children.)
71
*/
72
@@ -XXX,XX +XXX,XX @@ static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
73
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
74
BDRV_CHILD_FILTERED))
75
{
76
- child_size = bdrv_get_allocated_file_size(child->bs);
77
+ child_size = bdrv_co_get_allocated_file_size(child->bs);
78
if (child_size < 0) {
79
return child_size;
80
}
81
@@ -XXX,XX +XXX,XX @@ static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
82
* Length of a allocated file in bytes. Sparse files are counted by actual
83
* allocated space. Return < 0 if error or unknown.
84
*/
85
-int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
86
+int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
87
{
88
BlockDriver *drv = bs->drv;
54
IO_CODE();
89
IO_CODE();
55
assert(bs != NULL);
90
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
56
+ assert_bdrv_graph_readable();
91
if (!drv) {
57
92
return -ENOMEDIUM;
58
if (!bs->drv) {
93
}
59
error_setg(errp, "Block node '%s' is not opened", bs->filename);
94
- if (drv->bdrv_get_allocated_file_size) {
95
- return drv->bdrv_get_allocated_file_size(bs);
96
+ if (drv->bdrv_co_get_allocated_file_size) {
97
+ return drv->bdrv_co_get_allocated_file_size(bs);
98
}
99
100
if (drv->bdrv_file_open) {
101
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
102
return -ENOTSUP;
103
} else if (drv->is_filter) {
104
/* Filter drivers default to the size of their filtered child */
105
- return bdrv_get_allocated_file_size(bdrv_filter_bs(bs));
106
+ return bdrv_co_get_allocated_file_size(bdrv_filter_bs(bs));
107
} else {
108
/* Other drivers default to summing their children's sizes */
109
return bdrv_sum_allocated_file_size(bs);
110
diff --git a/block/file-posix.c b/block/file-posix.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/file-posix.c
113
+++ b/block/file-posix.c
114
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
115
}
116
#endif
117
118
-static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
119
+static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
120
{
121
struct stat st;
122
BDRVRawState *s = bs->opaque;
123
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
124
.bdrv_co_truncate = raw_co_truncate,
125
.bdrv_co_getlength = raw_co_getlength,
126
.bdrv_get_info = raw_get_info,
127
- .bdrv_get_allocated_file_size
128
- = raw_get_allocated_file_size,
129
+ .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
130
.bdrv_get_specific_stats = raw_get_specific_stats,
131
.bdrv_check_perm = raw_check_perm,
132
.bdrv_set_perm = raw_set_perm,
133
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
134
.bdrv_co_truncate = raw_co_truncate,
135
.bdrv_co_getlength = raw_co_getlength,
136
.bdrv_get_info = raw_get_info,
137
- .bdrv_get_allocated_file_size
138
- = raw_get_allocated_file_size,
139
+ .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
140
.bdrv_get_specific_stats = hdev_get_specific_stats,
141
.bdrv_check_perm = raw_check_perm,
142
.bdrv_set_perm = raw_set_perm,
143
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
144
.bdrv_co_truncate = raw_co_truncate,
145
.bdrv_co_getlength = raw_co_getlength,
146
.has_variable_length = true,
147
- .bdrv_get_allocated_file_size
148
- = raw_get_allocated_file_size,
149
+ .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
150
151
/* removable device support */
152
.bdrv_co_is_inserted = cdrom_co_is_inserted,
153
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
154
.bdrv_co_truncate = raw_co_truncate,
155
.bdrv_co_getlength = raw_co_getlength,
156
.has_variable_length = true,
157
- .bdrv_get_allocated_file_size
158
- = raw_get_allocated_file_size,
159
+ .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
160
161
/* removable device support */
162
.bdrv_co_is_inserted = cdrom_co_is_inserted,
163
diff --git a/block/file-win32.c b/block/file-win32.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/block/file-win32.c
166
+++ b/block/file-win32.c
167
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
168
return l.QuadPart;
169
}
170
171
-static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
172
+static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
173
{
174
typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
175
DWORD * high);
176
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
177
178
.bdrv_co_truncate = raw_co_truncate,
179
.bdrv_co_getlength = raw_co_getlength,
180
- .bdrv_get_allocated_file_size
181
- = raw_get_allocated_file_size,
182
+ .bdrv_co_get_allocated_file_size
183
+ = raw_co_get_allocated_file_size,
184
185
.create_opts = &raw_create_opts,
186
};
187
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
188
189
.bdrv_co_getlength = raw_co_getlength,
190
.has_variable_length = true,
191
-
192
- .bdrv_get_allocated_file_size
193
- = raw_get_allocated_file_size,
194
+ .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
195
};
196
197
static void bdrv_file_init(void)
198
diff --git a/block/gluster.c b/block/gluster.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/block/gluster.c
201
+++ b/block/gluster.c
202
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
203
}
204
}
205
206
-static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs)
207
+static int64_t coroutine_fn
208
+qemu_gluster_co_get_allocated_file_size(BlockDriverState *bs)
209
{
210
BDRVGlusterState *s = bs->opaque;
211
struct stat st;
212
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
213
.bdrv_co_create = qemu_gluster_co_create,
214
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
215
.bdrv_co_getlength = qemu_gluster_co_getlength,
216
- .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
217
+ .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
218
.bdrv_co_truncate = qemu_gluster_co_truncate,
219
.bdrv_co_readv = qemu_gluster_co_readv,
220
.bdrv_co_writev = qemu_gluster_co_writev,
221
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
222
.bdrv_co_create = qemu_gluster_co_create,
223
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
224
.bdrv_co_getlength = qemu_gluster_co_getlength,
225
- .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
226
+ .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
227
.bdrv_co_truncate = qemu_gluster_co_truncate,
228
.bdrv_co_readv = qemu_gluster_co_readv,
229
.bdrv_co_writev = qemu_gluster_co_writev,
230
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
231
.bdrv_co_create = qemu_gluster_co_create,
232
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
233
.bdrv_co_getlength = qemu_gluster_co_getlength,
234
- .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
235
+ .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
236
.bdrv_co_truncate = qemu_gluster_co_truncate,
237
.bdrv_co_readv = qemu_gluster_co_readv,
238
.bdrv_co_writev = qemu_gluster_co_writev,
239
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
240
.bdrv_co_create = qemu_gluster_co_create,
241
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
242
.bdrv_co_getlength = qemu_gluster_co_getlength,
243
- .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
244
+ .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
245
.bdrv_co_truncate = qemu_gluster_co_truncate,
246
.bdrv_co_readv = qemu_gluster_co_readv,
247
.bdrv_co_writev = qemu_gluster_co_writev,
248
diff --git a/block/nfs.c b/block/nfs.c
249
index XXXXXXX..XXXXXXX 100644
250
--- a/block/nfs.c
251
+++ b/block/nfs.c
252
@@ -XXX,XX +XXX,XX @@ nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data,
253
bdrv_wakeup(task->bs);
254
}
255
256
-static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
257
+static int64_t coroutine_fn nfs_co_get_allocated_file_size(BlockDriverState *bs)
258
{
259
NFSClient *client = bs->opaque;
260
NFSRPC task = {0};
261
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
262
.bdrv_has_zero_init = nfs_has_zero_init,
263
/* libnfs does not provide the allocated filesize of a file on win32. */
264
#if !defined(_WIN32)
265
- .bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
266
+ .bdrv_co_get_allocated_file_size = nfs_co_get_allocated_file_size,
267
#endif
268
.bdrv_co_truncate = nfs_file_co_truncate,
269
270
diff --git a/block/null.c b/block/null.c
271
index XXXXXXX..XXXXXXX 100644
272
--- a/block/null.c
273
+++ b/block/null.c
274
@@ -XXX,XX +XXX,XX @@ static void null_refresh_filename(BlockDriverState *bs)
275
bs->drv->format_name);
276
}
277
278
-static int64_t null_allocated_file_size(BlockDriverState *bs)
279
+static int64_t coroutine_fn
280
+null_co_get_allocated_file_size(BlockDriverState *bs)
281
{
282
return 0;
283
}
284
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
285
.bdrv_file_open = null_file_open,
286
.bdrv_parse_filename = null_co_parse_filename,
287
.bdrv_co_getlength = null_co_getlength,
288
- .bdrv_get_allocated_file_size = null_allocated_file_size,
289
+ .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
290
291
.bdrv_co_preadv = null_co_preadv,
292
.bdrv_co_pwritev = null_co_pwritev,
293
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
294
.bdrv_file_open = null_file_open,
295
.bdrv_parse_filename = null_aio_parse_filename,
296
.bdrv_co_getlength = null_co_getlength,
297
- .bdrv_get_allocated_file_size = null_allocated_file_size,
298
+ .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
299
300
.bdrv_aio_preadv = null_aio_preadv,
301
.bdrv_aio_pwritev = null_aio_pwritev,
302
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/block/qcow2-refcount.c
305
+++ b/block/qcow2-refcount.c
306
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs)
307
return file_length;
308
}
309
310
- real_allocation = bdrv_get_allocated_file_size(bs->file->bs);
311
+ real_allocation = bdrv_co_get_allocated_file_size(bs->file->bs);
312
if (real_allocation < 0) {
313
return real_allocation;
314
}
315
diff --git a/block/vmdk.c b/block/vmdk.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/block/vmdk.c
318
+++ b/block/vmdk.c
319
@@ -XXX,XX +XXX,XX @@ static void vmdk_close(BlockDriverState *bs)
320
error_free(s->migration_blocker);
321
}
322
323
-static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
324
+static int64_t coroutine_fn
325
+vmdk_co_get_allocated_file_size(BlockDriverState *bs)
326
{
327
int i;
328
int64_t ret = 0;
329
int64_t r;
330
BDRVVmdkState *s = bs->opaque;
331
332
- ret = bdrv_get_allocated_file_size(bs->file->bs);
333
+ ret = bdrv_co_get_allocated_file_size(bs->file->bs);
334
if (ret < 0) {
335
return ret;
336
}
337
@@ -XXX,XX +XXX,XX @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
338
if (s->extents[i].file == bs->file) {
339
continue;
340
}
341
- r = bdrv_get_allocated_file_size(s->extents[i].file->bs);
342
+ r = bdrv_co_get_allocated_file_size(s->extents[i].file->bs);
343
if (r < 0) {
344
return r;
345
}
346
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
347
.bdrv_co_create_opts = vmdk_co_create_opts,
348
.bdrv_co_create = vmdk_co_create,
349
.bdrv_co_block_status = vmdk_co_block_status,
350
- .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
351
+ .bdrv_co_get_allocated_file_size = vmdk_co_get_allocated_file_size,
352
.bdrv_has_zero_init = vmdk_has_zero_init,
353
.bdrv_get_specific_info = vmdk_get_specific_info,
354
.bdrv_refresh_limits = vmdk_refresh_limits,
60
--
355
--
61
2.39.2
356
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_create() need to hold a reader lock for the graph.
2
3
bdrv_get_info() is categorized as an I/O function, and it currently
4
doesn't run in a coroutine. We should let it take a graph rdlock since
5
it traverses the block nodes graph, which however is only possible in a
6
coroutine.
7
8
Therefore turn it into a co_wrapper to move the actual function into a
9
coroutine where the lock can be taken.
3
10
4
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20230203152202.49054-17-kwolf@redhat.com>
13
Message-Id: <20230113204212.359076-11-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
16
---
10
include/block/block-global-state.h | 14 ++++---
17
include/block/block-io.h | 5 ++++-
11
include/block/block_int-common.h | 11 +++---
18
include/block/block_int-common.h | 3 ++-
12
block.c | 1 +
19
block.c | 8 ++++----
13
block/create.c | 9 ++++-
20
block/blkio.c | 5 +++--
14
block/crypto.c | 7 ++--
21
block/crypto.c | 8 ++++----
15
block/file-posix.c | 7 ++--
22
block/file-posix.c | 7 ++++---
16
block/file-win32.c | 7 ++--
23
block/io.c | 8 ++++----
17
block/parallels.c | 7 ++--
24
block/iscsi.c | 7 ++++---
18
block/qcow.c | 6 +--
25
block/mirror.c | 2 +-
19
block/qcow2.c | 7 ++--
26
block/qcow.c | 5 +++--
20
block/qed.c | 7 ++--
27
block/qcow2.c | 5 +++--
21
block/raw-format.c | 7 ++--
28
block/qed.c | 5 +++--
22
block/vdi.c | 7 ++--
29
block/raw-format.c | 7 ++++---
23
block/vhdx.c | 7 ++--
30
block/rbd.c | 5 +++--
24
block/vmdk.c | 63 ++++++++++++++----------------
31
block/vdi.c | 7 ++++---
25
block/vpc.c | 7 ++--
32
block/vhdx.c | 5 +++--
26
16 files changed, 84 insertions(+), 90 deletions(-)
33
block/vmdk.c | 5 +++--
34
block/vpc.c | 5 +++--
35
18 files changed, 59 insertions(+), 43 deletions(-)
27
36
28
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
37
diff --git a/include/block/block-io.h b/include/block/block-io.h
29
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block-global-state.h
39
--- a/include/block/block-io.h
31
+++ b/include/block/block-global-state.h
40
+++ b/include/block/block-io.h
32
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_find_protocol(const char *filename,
41
@@ -XXX,XX +XXX,XX @@ bool bdrv_supports_compressed_writes(BlockDriverState *bs);
33
Error **errp);
42
const char *bdrv_get_node_name(const BlockDriverState *bs);
34
BlockDriver *bdrv_find_format(const char *format_name);
43
const char *bdrv_get_device_name(const BlockDriverState *bs);
35
44
const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
36
-int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
45
-int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
37
- QemuOpts *opts, Error **errp);
38
-int co_wrapper bdrv_create(BlockDriver *drv, const char *filename,
39
- QemuOpts *opts, Error **errp);
40
+int coroutine_fn GRAPH_RDLOCK
41
+bdrv_co_create(BlockDriver *drv, const char *filename, QemuOpts *opts,
42
+ Error **errp);
43
44
-int coroutine_fn bdrv_co_create_file(const char *filename, QemuOpts *opts,
45
- Error **errp);
46
+int co_wrapper_bdrv_rdlock bdrv_create(BlockDriver *drv, const char *filename,
47
+ QemuOpts *opts, Error **errp);
48
+
46
+
49
+int coroutine_fn GRAPH_RDLOCK
47
+int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
50
+bdrv_co_create_file(const char *filename, QemuOpts *opts, Error **errp);
48
+int co_wrapper_mixed bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
51
49
+
52
BlockDriverState *bdrv_new(void);
50
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
53
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
51
Error **errp);
52
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
54
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
53
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
55
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
56
--- a/include/block/block_int-common.h
55
--- a/include/block/block_int-common.h
57
+++ b/include/block/block_int-common.h
56
+++ b/include/block/block_int-common.h
58
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
57
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
59
Error **errp);
58
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
60
void (*bdrv_close)(BlockDriverState *bs);
59
size_t qiov_offset);
61
60
62
- int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
61
- int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
63
- Error **errp);
62
+ int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
64
- int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv,
63
+ BlockDriverInfo *bdi);
65
- const char *filename,
64
66
- QemuOpts *opts,
65
ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
67
- Error **errp);
66
Error **errp);
68
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)(
69
+ BlockdevCreateOptions *opts, Error **errp);
70
+
71
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create_opts)(
72
+ BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp);
73
74
int (*bdrv_amend_options)(BlockDriverState *bs,
75
QemuOpts *opts,
76
diff --git a/block.c b/block.c
67
diff --git a/block.c b/block.c
77
index XXXXXXX..XXXXXXX 100644
68
index XXXXXXX..XXXXXXX 100644
78
--- a/block.c
69
--- a/block.c
79
+++ b/block.c
70
+++ b/block.c
80
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
71
@@ -XXX,XX +XXX,XX @@ void bdrv_get_backing_filename(BlockDriverState *bs,
72
pstrcpy(filename, filename_size, bs->backing_file);
73
}
74
75
-int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
76
+int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
77
{
81
int ret;
78
int ret;
82
GLOBAL_STATE_CODE();
79
BlockDriver *drv = bs->drv;
83
ERRP_GUARD();
80
@@ -XXX,XX +XXX,XX @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
84
+ assert_bdrv_graph_readable();
81
if (!drv) {
85
82
return -ENOMEDIUM;
86
if (!drv->bdrv_co_create_opts) {
87
error_setg(errp, "Driver '%s' does not support image creation",
88
diff --git a/block/create.c b/block/create.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/create.c
91
+++ b/block/create.c
92
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
93
int ret;
94
95
GLOBAL_STATE_CODE();
96
+ GRAPH_RDLOCK_GUARD();
97
98
job_progress_set_remaining(&s->common, 1);
99
ret = s->drv->bdrv_co_create(s->opts, errp);
100
@@ -XXX,XX +XXX,XX @@ static const JobDriver blockdev_create_job_driver = {
101
.run = blockdev_create_run,
102
};
103
104
+/* Checking whether the function is present doesn't require the graph lock */
105
+static inline bool TSA_NO_TSA has_bdrv_co_create(BlockDriver *drv)
106
+{
107
+ return drv->bdrv_co_create;
108
+}
109
+
110
void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
111
Error **errp)
112
{
113
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
114
}
83
}
115
84
- if (!drv->bdrv_get_info) {
116
/* Error out if the driver doesn't support .bdrv_co_create */
85
+ if (!drv->bdrv_co_get_info) {
117
- if (!drv->bdrv_co_create) {
86
BlockDriverState *filtered = bdrv_filter_bs(bs);
118
+ if (!has_bdrv_co_create(drv)) {
87
if (filtered) {
119
error_setg(errp, "Driver does not support blockdev-create");
88
- return bdrv_get_info(filtered, bdi);
120
return;
89
+ return bdrv_co_get_info(filtered, bdi);
90
}
91
return -ENOTSUP;
121
}
92
}
93
memset(bdi, 0, sizeof(*bdi));
94
- ret = drv->bdrv_get_info(bs, bdi);
95
+ ret = drv->bdrv_co_get_info(bs, bdi);
96
if (ret < 0) {
97
return ret;
98
}
99
diff --git a/block/blkio.c b/block/blkio.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/blkio.c
102
+++ b/block/blkio.c
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset,
104
return 0;
105
}
106
107
-static int blkio_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
108
+static int coroutine_fn
109
+blkio_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
110
{
111
return 0;
112
}
113
@@ -XXX,XX +XXX,XX @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
114
.bdrv_close = blkio_close, \
115
.bdrv_co_getlength = blkio_co_getlength, \
116
.bdrv_co_truncate = blkio_truncate, \
117
- .bdrv_get_info = blkio_get_info, \
118
+ .bdrv_co_get_info = blkio_co_get_info, \
119
.bdrv_attach_aio_context = blkio_attach_aio_context, \
120
.bdrv_detach_aio_context = blkio_detach_aio_context, \
121
.bdrv_co_pdiscard = blkio_co_pdiscard, \
122
diff --git a/block/crypto.c b/block/crypto.c
122
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
124
--- a/block/crypto.c
125
+++ b/block/crypto.c
125
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ fail:
126
@@ -XXX,XX +XXX,XX @@ fail:
127
return ret;
127
return ret;
128
}
128
}
129
129
130
-static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv,
130
-static int block_crypto_get_info_luks(BlockDriverState *bs,
131
- const char *filename,
131
- BlockDriverInfo *bdi)
132
- QemuOpts *opts,
132
+static int coroutine_fn
133
- Error **errp)
133
+block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi)
134
+static int coroutine_fn GRAPH_RDLOCK
134
{
135
+block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
135
BlockDriverInfo subbdi;
136
+ QemuOpts *opts, Error **errp)
136
int ret;
137
{
137
138
QCryptoBlockCreateOptions *create_opts = NULL;
138
- ret = bdrv_get_info(bs->file->bs, &subbdi);
139
BlockDriverState *bs = NULL;
139
+ ret = bdrv_co_get_info(bs->file->bs, &subbdi);
140
if (ret != 0) {
141
return ret;
142
}
143
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
144
.bdrv_co_pwritev = block_crypto_co_pwritev,
145
.bdrv_co_getlength = block_crypto_co_getlength,
146
.bdrv_measure = block_crypto_measure,
147
- .bdrv_get_info = block_crypto_get_info_luks,
148
+ .bdrv_co_get_info = block_crypto_co_get_info_luks,
149
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
150
.bdrv_amend_options = block_crypto_amend_options_luks,
151
.bdrv_co_amend = block_crypto_co_amend_luks,
140
diff --git a/block/file-posix.c b/block/file-posix.c
152
diff --git a/block/file-posix.c b/block/file-posix.c
141
index XXXXXXX..XXXXXXX 100644
153
index XXXXXXX..XXXXXXX 100644
142
--- a/block/file-posix.c
154
--- a/block/file-posix.c
143
+++ b/block/file-posix.c
155
+++ b/block/file-posix.c
144
@@ -XXX,XX +XXX,XX @@ out:
156
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwrite_zeroes(
145
return result;
157
return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false);
146
}
158
}
147
159
148
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
160
-static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
149
- const char *filename,
161
+static int coroutine_fn
150
- QemuOpts *opts,
162
+raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
151
- Error **errp)
163
{
152
+static int coroutine_fn GRAPH_RDLOCK
153
+raw_co_create_opts(BlockDriver *drv, const char *filename,
154
+ QemuOpts *opts, Error **errp)
155
{
156
BlockdevCreateOptions options;
157
int64_t total_size = 0;
158
diff --git a/block/file-win32.c b/block/file-win32.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/file-win32.c
161
+++ b/block/file-win32.c
162
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
163
return 0;
164
return 0;
164
}
165
}
165
166
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
166
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
167
167
- const char *filename,
168
.bdrv_co_truncate = raw_co_truncate,
168
- QemuOpts *opts,
169
.bdrv_co_getlength = raw_co_getlength,
169
- Error **errp)
170
- .bdrv_get_info = raw_get_info,
170
+static int coroutine_fn GRAPH_RDLOCK
171
+ .bdrv_co_get_info = raw_co_get_info,
171
+raw_co_create_opts(BlockDriver *drv, const char *filename,
172
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
172
+ QemuOpts *opts, Error **errp)
173
.bdrv_get_specific_stats = raw_get_specific_stats,
173
{
174
.bdrv_check_perm = raw_check_perm,
174
BlockdevCreateOptions options;
175
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
175
int64_t total_size = 0;
176
176
diff --git a/block/parallels.c b/block/parallels.c
177
.bdrv_co_truncate = raw_co_truncate,
177
index XXXXXXX..XXXXXXX 100644
178
.bdrv_co_getlength = raw_co_getlength,
178
--- a/block/parallels.c
179
- .bdrv_get_info = raw_get_info,
179
+++ b/block/parallels.c
180
+ .bdrv_co_get_info = raw_co_get_info,
180
@@ -XXX,XX +XXX,XX @@ exit:
181
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
181
goto out;
182
.bdrv_get_specific_stats = hdev_get_specific_stats,
182
}
183
.bdrv_check_perm = raw_check_perm,
183
184
diff --git a/block/io.c b/block/io.c
184
-static int coroutine_fn parallels_co_create_opts(BlockDriver *drv,
185
index XXXXXXX..XXXXXXX 100644
185
- const char *filename,
186
--- a/block/io.c
186
- QemuOpts *opts,
187
+++ b/block/io.c
187
- Error **errp)
188
@@ -XXX,XX +XXX,XX @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
188
+static int coroutine_fn GRAPH_RDLOCK
189
/**
189
+parallels_co_create_opts(BlockDriver *drv, const char *filename,
190
* Round a region to cluster boundaries
190
+ QemuOpts *opts, Error **errp)
191
*/
191
{
192
-void bdrv_round_to_clusters(BlockDriverState *bs,
192
BlockdevCreateOptions *create_options = NULL;
193
+void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
193
BlockDriverState *bs = NULL;
194
int64_t offset, int64_t bytes,
195
int64_t *cluster_offset,
196
int64_t *cluster_bytes)
197
{
198
BlockDriverInfo bdi;
199
IO_CODE();
200
- if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
201
+ if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
202
*cluster_offset = offset;
203
*cluster_bytes = bytes;
204
} else {
205
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
206
}
207
}
208
209
-static int bdrv_get_cluster_size(BlockDriverState *bs)
210
+static coroutine_fn int bdrv_get_cluster_size(BlockDriverState *bs)
211
{
212
BlockDriverInfo bdi;
213
int ret;
214
215
- ret = bdrv_get_info(bs, &bdi);
216
+ ret = bdrv_co_get_info(bs, &bdi);
217
if (ret < 0 || bdi.cluster_size == 0) {
218
return bs->bl.request_alignment;
219
} else {
220
diff --git a/block/iscsi.c b/block/iscsi.c
221
index XXXXXXX..XXXXXXX 100644
222
--- a/block/iscsi.c
223
+++ b/block/iscsi.c
224
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
225
return 0;
226
}
227
228
-static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
229
+static int coroutine_fn
230
+iscsi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
231
{
232
IscsiLun *iscsilun = bs->opaque;
233
bdi->cluster_size = iscsilun->cluster_size;
234
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
235
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
236
237
.bdrv_co_getlength = iscsi_co_getlength,
238
- .bdrv_get_info = iscsi_get_info,
239
+ .bdrv_co_get_info = iscsi_co_get_info,
240
.bdrv_co_truncate = iscsi_co_truncate,
241
.bdrv_refresh_limits = iscsi_refresh_limits,
242
243
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
244
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
245
246
.bdrv_co_getlength = iscsi_co_getlength,
247
- .bdrv_get_info = iscsi_get_info,
248
+ .bdrv_co_get_info = iscsi_co_get_info,
249
.bdrv_co_truncate = iscsi_co_truncate,
250
.bdrv_refresh_limits = iscsi_refresh_limits,
251
252
diff --git a/block/mirror.c b/block/mirror.c
253
index XXXXXXX..XXXXXXX 100644
254
--- a/block/mirror.c
255
+++ b/block/mirror.c
256
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
257
*/
258
bdrv_get_backing_filename(target_bs, backing_filename,
259
sizeof(backing_filename));
260
- if (!bdrv_get_info(target_bs, &bdi) && bdi.cluster_size) {
261
+ if (!bdrv_co_get_info(target_bs, &bdi) && bdi.cluster_size) {
262
s->target_cluster_size = bdi.cluster_size;
263
} else {
264
s->target_cluster_size = BDRV_SECTOR_SIZE;
194
diff --git a/block/qcow.c b/block/qcow.c
265
diff --git a/block/qcow.c b/block/qcow.c
195
index XXXXXXX..XXXXXXX 100644
266
index XXXXXXX..XXXXXXX 100644
196
--- a/block/qcow.c
267
--- a/block/qcow.c
197
+++ b/block/qcow.c
268
+++ b/block/qcow.c
198
@@ -XXX,XX +XXX,XX @@ exit:
269
@@ -XXX,XX +XXX,XX @@ fail:
199
return ret;
270
return ret;
200
}
271
}
201
272
202
-static int coroutine_fn qcow_co_create_opts(BlockDriver *drv,
273
-static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
203
- const char *filename,
274
+static int coroutine_fn
204
- QemuOpts *opts, Error **errp)
275
+qcow_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
205
+static int coroutine_fn GRAPH_RDLOCK
276
{
206
+qcow_co_create_opts(BlockDriver *drv, const char *filename,
277
BDRVQcowState *s = bs->opaque;
207
+ QemuOpts *opts, Error **errp)
278
bdi->cluster_size = s->cluster_size;
208
{
279
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
209
BlockdevCreateOptions *create_options = NULL;
280
210
BlockDriverState *bs = NULL;
281
.bdrv_make_empty = qcow_make_empty,
282
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
283
- .bdrv_get_info = qcow_get_info,
284
+ .bdrv_co_get_info = qcow_co_get_info,
285
286
.create_opts = &qcow_create_opts,
287
.strong_runtime_opts = qcow_strong_runtime_opts,
211
diff --git a/block/qcow2.c b/block/qcow2.c
288
diff --git a/block/qcow2.c b/block/qcow2.c
212
index XXXXXXX..XXXXXXX 100644
289
index XXXXXXX..XXXXXXX 100644
213
--- a/block/qcow2.c
290
--- a/block/qcow2.c
214
+++ b/block/qcow2.c
291
+++ b/block/qcow2.c
215
@@ -XXX,XX +XXX,XX @@ out:
292
@@ -XXX,XX +XXX,XX @@ err:
216
return ret;
293
return NULL;
217
}
294
}
218
295
219
-static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
296
-static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
220
- const char *filename,
297
+static int coroutine_fn
221
- QemuOpts *opts,
298
+qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
222
- Error **errp)
299
{
223
+static int coroutine_fn GRAPH_RDLOCK
300
BDRVQcow2State *s = bs->opaque;
224
+qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
301
bdi->cluster_size = s->cluster_size;
225
+ Error **errp)
302
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
226
{
303
.bdrv_snapshot_list = qcow2_snapshot_list,
227
BlockdevCreateOptions *create_options = NULL;
304
.bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
228
QDict *qdict;
305
.bdrv_measure = qcow2_measure,
306
- .bdrv_get_info = qcow2_get_info,
307
+ .bdrv_co_get_info = qcow2_co_get_info,
308
.bdrv_get_specific_info = qcow2_get_specific_info,
309
310
.bdrv_save_vmstate = qcow2_save_vmstate,
229
diff --git a/block/qed.c b/block/qed.c
311
diff --git a/block/qed.c b/block/qed.c
230
index XXXXXXX..XXXXXXX 100644
312
index XXXXXXX..XXXXXXX 100644
231
--- a/block/qed.c
313
--- a/block/qed.c
232
+++ b/block/qed.c
314
+++ b/block/qed.c
233
@@ -XXX,XX +XXX,XX @@ out:
315
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs)
234
return ret;
316
return s->header.image_size;
235
}
317
}
236
318
237
-static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
319
-static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
238
- const char *filename,
320
+static int coroutine_fn
239
- QemuOpts *opts,
321
+bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
240
- Error **errp)
322
{
241
+static int coroutine_fn GRAPH_RDLOCK
323
BDRVQEDState *s = bs->opaque;
242
+bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
324
243
+ QemuOpts *opts, Error **errp)
325
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
244
{
326
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
245
BlockdevCreateOptions *create_options = NULL;
327
.bdrv_co_truncate = bdrv_qed_co_truncate,
246
QDict *qdict;
328
.bdrv_co_getlength = bdrv_qed_co_getlength,
329
- .bdrv_get_info = bdrv_qed_get_info,
330
+ .bdrv_co_get_info = bdrv_qed_co_get_info,
331
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
332
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
333
.bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
247
diff --git a/block/raw-format.c b/block/raw-format.c
334
diff --git a/block/raw-format.c b/block/raw-format.c
248
index XXXXXXX..XXXXXXX 100644
335
index XXXXXXX..XXXXXXX 100644
249
--- a/block/raw-format.c
336
--- a/block/raw-format.c
250
+++ b/block/raw-format.c
337
+++ b/block/raw-format.c
251
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
338
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
252
return bdrv_has_zero_init(bs->file->bs);
339
return info;
253
}
340
}
254
341
255
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
342
-static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
256
- const char *filename,
343
+static int coroutine_fn
257
- QemuOpts *opts,
344
+raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
258
- Error **errp)
345
{
259
+static int coroutine_fn GRAPH_RDLOCK
346
- return bdrv_get_info(bs->file->bs, bdi);
260
+raw_co_create_opts(BlockDriver *drv, const char *filename,
347
+ return bdrv_co_get_info(bs->file->bs, bdi);
261
+ QemuOpts *opts, Error **errp)
348
}
262
{
349
263
return bdrv_co_create_file(filename, opts, errp);
350
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
264
}
351
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
352
.is_format = true,
353
.has_variable_length = true,
354
.bdrv_measure = &raw_measure,
355
- .bdrv_get_info = &raw_get_info,
356
+ .bdrv_co_get_info = &raw_co_get_info,
357
.bdrv_refresh_limits = &raw_refresh_limits,
358
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
359
.bdrv_probe_geometry = &raw_probe_geometry,
360
diff --git a/block/rbd.c b/block/rbd.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/rbd.c
363
+++ b/block/rbd.c
364
@@ -XXX,XX +XXX,XX @@ coroutine_fn qemu_rbd_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
365
}
366
#endif
367
368
-static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi)
369
+static int coroutine_fn
370
+qemu_rbd_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
371
{
372
BDRVRBDState *s = bs->opaque;
373
bdi->cluster_size = s->object_size;
374
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
375
.bdrv_co_create = qemu_rbd_co_create,
376
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
377
.bdrv_has_zero_init = bdrv_has_zero_init_1,
378
- .bdrv_get_info = qemu_rbd_getinfo,
379
+ .bdrv_co_get_info = qemu_rbd_co_get_info,
380
.bdrv_get_specific_info = qemu_rbd_get_specific_info,
381
.create_opts = &qemu_rbd_create_opts,
382
.bdrv_co_getlength = qemu_rbd_co_getlength,
265
diff --git a/block/vdi.c b/block/vdi.c
383
diff --git a/block/vdi.c b/block/vdi.c
266
index XXXXXXX..XXXXXXX 100644
384
index XXXXXXX..XXXXXXX 100644
267
--- a/block/vdi.c
385
--- a/block/vdi.c
268
+++ b/block/vdi.c
386
+++ b/block/vdi.c
269
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options,
387
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
270
return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp);
388
return 0;
271
}
389
}
272
390
273
-static int coroutine_fn vdi_co_create_opts(BlockDriver *drv,
391
-static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
274
- const char *filename,
392
+static int coroutine_fn
275
- QemuOpts *opts,
393
+vdi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
276
- Error **errp)
394
{
277
+static int coroutine_fn GRAPH_RDLOCK
395
- /* TODO: vdi_get_info would be needed for machine snapshots.
278
+vdi_co_create_opts(BlockDriver *drv, const char *filename,
396
+ /* TODO: vdi_co_get_info would be needed for machine snapshots.
279
+ QemuOpts *opts, Error **errp)
397
vm_state_offset is still missing. */
280
{
398
BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
281
QDict *qdict = NULL;
399
logout("\n");
282
BlockdevCreateOptions *create_options = NULL;
400
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
401
.bdrv_co_pwritev = vdi_co_pwritev,
402
#endif
403
404
- .bdrv_get_info = vdi_get_info,
405
+ .bdrv_co_get_info = vdi_co_get_info,
406
407
.is_format = true,
408
.create_opts = &vdi_create_opts,
283
diff --git a/block/vhdx.c b/block/vhdx.c
409
diff --git a/block/vhdx.c b/block/vhdx.c
284
index XXXXXXX..XXXXXXX 100644
410
index XXXXXXX..XXXXXXX 100644
285
--- a/block/vhdx.c
411
--- a/block/vhdx.c
286
+++ b/block/vhdx.c
412
+++ b/block/vhdx.c
287
@@ -XXX,XX +XXX,XX @@ delete_and_exit:
413
@@ -XXX,XX +XXX,XX @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num,
288
return ret;
414
}
289
}
415
290
416
291
-static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv,
417
-static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
292
- const char *filename,
418
+static int coroutine_fn
293
- QemuOpts *opts,
419
+vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
294
- Error **errp)
420
{
295
+static int coroutine_fn GRAPH_RDLOCK
421
BDRVVHDXState *s = bs->opaque;
296
+vhdx_co_create_opts(BlockDriver *drv, const char *filename,
422
297
+ QemuOpts *opts, Error **errp)
423
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
298
{
424
.bdrv_co_writev = vhdx_co_writev,
299
BlockdevCreateOptions *create_options = NULL;
425
.bdrv_co_create = vhdx_co_create,
300
QDict *qdict;
426
.bdrv_co_create_opts = vhdx_co_create_opts,
427
- .bdrv_get_info = vhdx_get_info,
428
+ .bdrv_co_get_info = vhdx_co_get_info,
429
.bdrv_co_check = vhdx_co_check,
430
.bdrv_has_zero_init = vhdx_has_zero_init,
431
301
diff --git a/block/vmdk.c b/block/vmdk.c
432
diff --git a/block/vmdk.c b/block/vmdk.c
302
index XXXXXXX..XXXXXXX 100644
433
index XXXXXXX..XXXXXXX 100644
303
--- a/block/vmdk.c
434
--- a/block/vmdk.c
304
+++ b/block/vmdk.c
435
+++ b/block/vmdk.c
305
@@ -XXX,XX +XXX,XX @@ exit:
436
@@ -XXX,XX +XXX,XX @@ static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b)
306
return ret;
437
(a->flat || a->cluster_sectors == b->cluster_sectors);
307
}
438
}
308
439
309
-static int coroutine_fn vmdk_create_extent(const char *filename,
440
-static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
310
- int64_t filesize, bool flat,
441
+static int coroutine_fn
311
- bool compress, bool zeroed_grain,
442
+vmdk_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
312
- BlockBackend **pbb,
443
{
313
- QemuOpts *opts, Error **errp)
444
int i;
314
+static int coroutine_fn GRAPH_RDLOCK
445
BDRVVmdkState *s = bs->opaque;
315
+vmdk_create_extent(const char *filename, int64_t filesize, bool flat,
446
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
316
+ bool compress, bool zeroed_grain, BlockBackend **pbb,
447
.bdrv_has_zero_init = vmdk_has_zero_init,
317
+ QemuOpts *opts, Error **errp)
448
.bdrv_get_specific_info = vmdk_get_specific_info,
318
{
449
.bdrv_refresh_limits = vmdk_refresh_limits,
319
int ret;
450
- .bdrv_get_info = vmdk_get_info,
320
BlockBackend *blk = NULL;
451
+ .bdrv_co_get_info = vmdk_co_get_info,
321
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
452
.bdrv_gather_child_options = vmdk_gather_child_options,
322
* non-split format.
453
323
* idx >= 1: get the n-th extent if in a split subformat
454
.is_format = true,
324
*/
325
-typedef BlockBackend * coroutine_fn (*vmdk_create_extent_fn)(int64_t size,
326
- int idx,
327
- bool flat,
328
- bool split,
329
- bool compress,
330
- bool zeroed_grain,
331
- void *opaque,
332
- Error **errp);
333
+typedef BlockBackend * coroutine_fn /* GRAPH_RDLOCK */
334
+ (*vmdk_create_extent_fn)(int64_t size, int idx, bool flat, bool split,
335
+ bool compress, bool zeroed_grain, void *opaque,
336
+ Error **errp);
337
338
static void vmdk_desc_add_extent(GString *desc,
339
const char *extent_line_fmt,
340
@@ -XXX,XX +XXX,XX @@ static void vmdk_desc_add_extent(GString *desc,
341
g_free(basename);
342
}
343
344
-static int coroutine_fn vmdk_co_do_create(int64_t size,
345
- BlockdevVmdkSubformat subformat,
346
- BlockdevVmdkAdapterType adapter_type,
347
- const char *backing_file,
348
- const char *hw_version,
349
- const char *toolsversion,
350
- bool compat6,
351
- bool zeroed_grain,
352
- vmdk_create_extent_fn extent_fn,
353
- void *opaque,
354
- Error **errp)
355
+static int coroutine_fn GRAPH_RDLOCK
356
+vmdk_co_do_create(int64_t size,
357
+ BlockdevVmdkSubformat subformat,
358
+ BlockdevVmdkAdapterType adapter_type,
359
+ const char *backing_file,
360
+ const char *hw_version,
361
+ const char *toolsversion,
362
+ bool compat6,
363
+ bool zeroed_grain,
364
+ vmdk_create_extent_fn extent_fn,
365
+ void *opaque,
366
+ Error **errp)
367
{
368
int extent_idx;
369
BlockBackend *blk = NULL;
370
@@ -XXX,XX +XXX,XX @@ typedef struct {
371
QemuOpts *opts;
372
} VMDKCreateOptsData;
373
374
-static BlockBackend * coroutine_fn vmdk_co_create_opts_cb(int64_t size, int idx,
375
- bool flat, bool split, bool compress,
376
- bool zeroed_grain, void *opaque,
377
- Error **errp)
378
+static BlockBackend * coroutine_fn GRAPH_RDLOCK
379
+vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
380
+ bool compress, bool zeroed_grain, void *opaque,
381
+ Error **errp)
382
{
383
BlockBackend *blk = NULL;
384
BlockDriverState *bs = NULL;
385
@@ -XXX,XX +XXX,XX @@ exit:
386
return blk;
387
}
388
389
-static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
390
- const char *filename,
391
- QemuOpts *opts,
392
- Error **errp)
393
+static int coroutine_fn GRAPH_RDLOCK
394
+vmdk_co_create_opts(BlockDriver *drv, const char *filename,
395
+ QemuOpts *opts, Error **errp)
396
{
397
Error *local_err = NULL;
398
char *desc = NULL;
399
@@ -XXX,XX +XXX,XX @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
400
return blk;
401
}
402
403
-static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options,
404
- Error **errp)
405
+static int coroutine_fn GRAPH_RDLOCK
406
+vmdk_co_create(BlockdevCreateOptions *create_options, Error **errp)
407
{
408
BlockdevCreateOptionsVmdk *opts;
409
410
diff --git a/block/vpc.c b/block/vpc.c
455
diff --git a/block/vpc.c b/block/vpc.c
411
index XXXXXXX..XXXXXXX 100644
456
index XXXXXXX..XXXXXXX 100644
412
--- a/block/vpc.c
457
--- a/block/vpc.c
413
+++ b/block/vpc.c
458
+++ b/block/vpc.c
414
@@ -XXX,XX +XXX,XX @@ out:
459
@@ -XXX,XX +XXX,XX @@ fail:
415
return ret;
460
return ret;
416
}
461
}
417
462
418
-static int coroutine_fn vpc_co_create_opts(BlockDriver *drv,
463
-static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
419
- const char *filename,
464
+static int coroutine_fn
420
- QemuOpts *opts,
465
+vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
421
- Error **errp)
466
{
422
+static int coroutine_fn GRAPH_RDLOCK
467
BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
423
+vpc_co_create_opts(BlockDriver *drv, const char *filename,
468
424
+ QemuOpts *opts, Error **errp)
469
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
425
{
470
.bdrv_co_pwritev = vpc_co_pwritev,
426
BlockdevCreateOptions *create_options = NULL;
471
.bdrv_co_block_status = vpc_co_block_status,
427
QDict *qdict;
472
473
- .bdrv_get_info = vpc_get_info,
474
+ .bdrv_co_get_info = vpc_co_get_info,
475
476
.is_format = true,
477
.create_opts = &vpc_create_opts,
428
--
478
--
429
2.39.2
479
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_eject() and bdrv_co_lock_medium() need to hold a reader lock for
2
3
the graph.
3
bdrv_eject() is categorized as an I/O function, and it currently
4
doesn't run in a coroutine. We should let it take a graph rdlock since
5
it traverses the block nodes graph, which however is only possible in a
6
coroutine.
7
8
The only caller of this function is blk_eject(). Therefore make
9
blk_eject() a co_wrapper, so that it always creates a new coroutine, and
10
then make bdrv_eject() coroutine_fn where the lock can be taken.
4
11
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-Id: <20230203152202.49054-20-kwolf@redhat.com>
14
Message-Id: <20230113204212.359076-12-kwolf@redhat.com>
8
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
17
---
11
include/block/block-io.h | 7 +++++--
18
include/block/block-io.h | 3 ++-
12
include/block/block_int-common.h | 6 ++++--
19
include/block/block_int-common.h | 2 +-
13
block.c | 2 ++
20
include/sysemu/block-backend-io.h | 4 +++-
14
block/block-backend.c | 2 ++
21
block.c | 6 +++---
15
block/copy-on-read.c | 6 ++++--
22
block/block-backend.c | 4 ++--
16
block/filter-compress.c | 4 ++--
23
block/copy-on-read.c | 6 +++---
17
block/raw-format.c | 6 ++++--
24
block/file-posix.c | 8 ++++----
18
7 files changed, 23 insertions(+), 10 deletions(-)
25
block/filter-compress.c | 7 ++++---
26
block/raw-format.c | 6 +++---
27
9 files changed, 25 insertions(+), 21 deletions(-)
19
28
20
diff --git a/include/block/block-io.h b/include/block/block-io.h
29
diff --git a/include/block/block-io.h b/include/block/block-io.h
21
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block-io.h
31
--- a/include/block/block-io.h
23
+++ b/include/block/block-io.h
32
+++ b/include/block/block-io.h
24
@@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs);
33
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
25
bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
34
bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
26
bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
35
27
36
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
28
-void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
37
-void bdrv_eject(BlockDriverState *bs, bool eject_flag);
29
-void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
38
+void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
30
+void coroutine_fn GRAPH_RDLOCK
31
+bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
32
+
39
+
33
+void coroutine_fn GRAPH_RDLOCK
34
+bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
35
36
const char *bdrv_get_format_name(BlockDriverState *bs);
40
const char *bdrv_get_format_name(BlockDriverState *bs);
37
41
42
bool bdrv_supports_compressed_writes(BlockDriverState *bs);
38
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
39
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block_int-common.h
45
--- a/include/block/block_int-common.h
41
+++ b/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
42
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
43
/* removable device specific */
49
/* removable device specific */
44
bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
50
bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
45
BlockDriverState *bs);
51
- void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag);
46
- void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
52
+ void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
47
- void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
53
void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
48
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_eject)(
49
+ BlockDriverState *bs, bool eject_flag);
50
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_lock_medium)(
51
+ BlockDriverState *bs, bool locked);
52
54
53
/* to control generic scsi devices */
55
/* to control generic scsi devices */
54
BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)(
56
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
57
index XXXXXXX..XXXXXXX 100644
58
--- a/include/sysemu/block-backend-io.h
59
+++ b/include/sysemu/block-backend-io.h
60
@@ -XXX,XX +XXX,XX @@ bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
61
62
bool blk_is_available(BlockBackend *blk);
63
void blk_lock_medium(BlockBackend *blk, bool locked);
64
-void blk_eject(BlockBackend *blk, bool eject_flag);
65
+
66
+void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag);
67
+void co_wrapper blk_eject(BlockBackend *blk, bool eject_flag);
68
69
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk);
70
int64_t co_wrapper_mixed blk_getlength(BlockBackend *blk);
55
diff --git a/block.c b/block.c
71
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
73
--- a/block.c
58
+++ b/block.c
74
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
75
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
76
/**
77
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
78
*/
79
-void bdrv_eject(BlockDriverState *bs, bool eject_flag)
80
+void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
60
{
81
{
61
BlockDriver *drv = bs->drv;
82
BlockDriver *drv = bs->drv;
62
IO_CODE();
83
IO_CODE();
63
+ assert_bdrv_graph_readable();
84
64
85
- if (drv && drv->bdrv_eject) {
65
if (drv && drv->bdrv_co_eject) {
86
- drv->bdrv_eject(bs, eject_flag);
66
drv->bdrv_co_eject(bs, eject_flag);
87
+ if (drv && drv->bdrv_co_eject) {
67
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
88
+ drv->bdrv_co_eject(bs, eject_flag);
68
{
89
}
69
BlockDriver *drv = bs->drv;
90
}
70
IO_CODE();
91
71
+ assert_bdrv_graph_readable();
72
trace_bdrv_lock_medium(bs, locked);
73
74
if (drv && drv->bdrv_co_lock_medium) {
75
diff --git a/block/block-backend.c b/block/block-backend.c
92
diff --git a/block/block-backend.c b/block/block-backend.c
76
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
77
--- a/block/block-backend.c
94
--- a/block/block-backend.c
78
+++ b/block/block-backend.c
95
+++ b/block/block-backend.c
79
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
96
@@ -XXX,XX +XXX,XX @@ void blk_lock_medium(BlockBackend *blk, bool locked)
80
{
97
}
81
BlockDriverState *bs = blk_bs(blk);
98
}
82
IO_CODE();
99
83
+ GRAPH_RDLOCK_GUARD();
100
-void blk_eject(BlockBackend *blk, bool eject_flag)
84
101
+void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
85
if (bs) {
102
{
86
bdrv_co_lock_medium(bs, locked);
87
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
88
BlockDriverState *bs = blk_bs(blk);
103
BlockDriverState *bs = blk_bs(blk);
89
char *id;
104
char *id;
90
IO_CODE();
105
IO_CODE();
91
+ GRAPH_RDLOCK_GUARD();
92
106
93
if (bs) {
107
if (bs) {
94
bdrv_co_eject(bs, eject_flag);
108
- bdrv_eject(bs, eject_flag);
109
+ bdrv_co_eject(bs, eject_flag);
110
}
111
112
/* Whether or not we ejected on the backend,
95
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
113
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
96
index XXXXXXX..XXXXXXX 100644
114
index XXXXXXX..XXXXXXX 100644
97
--- a/block/copy-on-read.c
115
--- a/block/copy-on-read.c
98
+++ b/block/copy-on-read.c
116
+++ b/block/copy-on-read.c
99
@@ -XXX,XX +XXX,XX @@ cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
100
}
118
}
101
119
102
120
103
-static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
121
-static void cor_eject(BlockDriverState *bs, bool eject_flag)
104
+static void coroutine_fn GRAPH_RDLOCK
122
+static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
105
+cor_co_eject(BlockDriverState *bs, bool eject_flag)
123
{
106
{
124
- bdrv_eject(bs->file->bs, eject_flag);
107
bdrv_co_eject(bs->file->bs, eject_flag);
125
+ bdrv_co_eject(bs->file->bs, eject_flag);
108
}
126
}
109
127
110
128
111
-static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = {
112
+static void coroutine_fn GRAPH_RDLOCK
130
.bdrv_co_pdiscard = cor_co_pdiscard,
113
+cor_co_lock_medium(BlockDriverState *bs, bool locked)
131
.bdrv_co_pwritev_compressed = cor_co_pwritev_compressed,
114
{
132
115
bdrv_co_lock_medium(bs->file->bs, locked);
133
- .bdrv_eject = cor_eject,
116
}
134
+ .bdrv_co_eject = cor_co_eject,
135
.bdrv_lock_medium = cor_lock_medium,
136
137
.has_variable_length = true,
138
diff --git a/block/file-posix.c b/block/file-posix.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/file-posix.c
141
+++ b/block/file-posix.c
142
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
143
return ret == CDS_DISC_OK;
144
}
145
146
-static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
147
+static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
148
{
149
BDRVRawState *s = bs->opaque;
150
151
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
152
153
/* removable device support */
154
.bdrv_co_is_inserted = cdrom_co_is_inserted,
155
- .bdrv_eject = cdrom_eject,
156
+ .bdrv_co_eject = cdrom_co_eject,
157
.bdrv_lock_medium = cdrom_lock_medium,
158
159
/* generic scsi device */
160
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs)
161
return raw_co_getlength(bs) > 0;
162
}
163
164
-static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
165
+static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
166
{
167
BDRVRawState *s = bs->opaque;
168
169
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
170
171
/* removable device support */
172
.bdrv_co_is_inserted = cdrom_co_is_inserted,
173
- .bdrv_eject = cdrom_eject,
174
+ .bdrv_co_eject = cdrom_co_eject,
175
.bdrv_lock_medium = cdrom_lock_medium,
176
};
177
#endif /* __FreeBSD__ */
117
diff --git a/block/filter-compress.c b/block/filter-compress.c
178
diff --git a/block/filter-compress.c b/block/filter-compress.c
118
index XXXXXXX..XXXXXXX 100644
179
index XXXXXXX..XXXXXXX 100644
119
--- a/block/filter-compress.c
180
--- a/block/filter-compress.c
120
+++ b/block/filter-compress.c
181
+++ b/block/filter-compress.c
121
@@ -XXX,XX +XXX,XX @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
182
@@ -XXX,XX +XXX,XX @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
122
}
183
}
123
184
124
185
125
-static void coroutine_fn
186
-static void compress_eject(BlockDriverState *bs, bool eject_flag)
126
+static void coroutine_fn GRAPH_RDLOCK
187
+static void coroutine_fn
127
compress_co_eject(BlockDriverState *bs, bool eject_flag)
188
+compress_co_eject(BlockDriverState *bs, bool eject_flag)
128
{
189
{
129
bdrv_co_eject(bs->file->bs, eject_flag);
190
- bdrv_eject(bs->file->bs, eject_flag);
130
}
191
+ bdrv_co_eject(bs->file->bs, eject_flag);
131
192
}
132
193
133
-static void coroutine_fn
194
134
+static void coroutine_fn GRAPH_RDLOCK
195
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = {
135
compress_co_lock_medium(BlockDriverState *bs, bool locked)
196
.bdrv_co_pdiscard = compress_co_pdiscard,
136
{
197
.bdrv_refresh_limits = compress_refresh_limits,
137
bdrv_co_lock_medium(bs->file->bs, locked);
198
199
- .bdrv_eject = compress_eject,
200
+ .bdrv_co_eject = compress_co_eject,
201
.bdrv_lock_medium = compress_lock_medium,
202
203
.has_variable_length = true,
138
diff --git a/block/raw-format.c b/block/raw-format.c
204
diff --git a/block/raw-format.c b/block/raw-format.c
139
index XXXXXXX..XXXXXXX 100644
205
index XXXXXXX..XXXXXXX 100644
140
--- a/block/raw-format.c
206
--- a/block/raw-format.c
141
+++ b/block/raw-format.c
207
+++ b/block/raw-format.c
142
@@ -XXX,XX +XXX,XX @@ raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
143
return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
209
return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
144
}
210
}
145
211
146
-static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
212
-static void raw_eject(BlockDriverState *bs, bool eject_flag)
147
+static void coroutine_fn GRAPH_RDLOCK
213
+static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
148
+raw_co_eject(BlockDriverState *bs, bool eject_flag)
214
{
149
{
215
- bdrv_eject(bs->file->bs, eject_flag);
150
bdrv_co_eject(bs->file->bs, eject_flag);
216
+ bdrv_co_eject(bs->file->bs, eject_flag);
151
}
217
}
152
218
153
-static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
219
static void raw_lock_medium(BlockDriverState *bs, bool locked)
154
+static void coroutine_fn GRAPH_RDLOCK
220
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
155
+raw_co_lock_medium(BlockDriverState *bs, bool locked)
221
.bdrv_refresh_limits = &raw_refresh_limits,
156
{
222
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
157
bdrv_co_lock_medium(bs->file->bs, locked);
223
.bdrv_probe_geometry = &raw_probe_geometry,
158
}
224
- .bdrv_eject = &raw_eject,
225
+ .bdrv_co_eject = &raw_co_eject,
226
.bdrv_lock_medium = &raw_lock_medium,
227
.bdrv_co_ioctl = &raw_co_ioctl,
228
.create_opts = &raw_create_opts,
159
--
229
--
160
2.39.2
230
2.38.1
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This adds GRAPH_RDLOCK annotations to declare that callers of
3
bdrv_lock_medium() is categorized as an I/O function, and it currently
4
bdrv_co_pdiscard() need to hold a reader lock for the graph.
4
doesn't run in a coroutine. We should let it take a graph rdlock since
5
5
it traverses the block nodes graph, which however is only possible in a
6
For some places, we know that they will hold the lock, but we don't have
6
coroutine.
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
7
8
with a FIXME comment. These places will be removed once everything is
8
The only caller of this function is blk_lock_medium(). Therefore make
9
properly annotated.
9
blk_lock_medium() a co_wrapper, so that it always creates a new
10
10
coroutine, and then make bdrv_lock_medium() a coroutine_fn where the
11
lock can be taken.
12
13
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20230203152202.49054-9-kwolf@redhat.com>
15
Message-Id: <20230113204212.359076-13-kwolf@redhat.com>
13
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
16
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
18
---
16
include/block/block-io.h | 5 +++--
19
include/block/block-io.h | 2 +-
17
include/block/block_int-common.h | 15 +++++++++------
20
include/block/block_int-common.h | 2 +-
18
include/block/block_int-io.h | 2 +-
21
include/sysemu/block-backend-io.h | 4 +++-
19
block/blkdebug.c | 4 ++--
22
block.c | 6 +++---
20
block/blklogwrites.c | 5 ++---
23
block/block-backend.c | 4 ++--
21
block/blkreplay.c | 4 ++--
24
block/copy-on-read.c | 6 +++---
22
block/block-backend.c | 1 +
25
block/file-posix.c | 8 ++++----
23
block/copy-before-write.c | 8 ++++----
26
block/filter-compress.c | 7 ++++---
24
block/copy-on-read.c | 4 ++--
27
block/raw-format.c | 6 +++---
25
block/filter-compress.c | 4 ++--
28
9 files changed, 24 insertions(+), 21 deletions(-)
26
block/io.c | 2 ++
27
block/mirror.c | 14 +++++++++-----
28
block/preallocate.c | 4 ++--
29
block/raw-format.c | 4 ++--
30
block/snapshot-access.c | 4 ++--
31
block/throttle.c | 4 ++--
32
16 files changed, 47 insertions(+), 37 deletions(-)
33
29
34
diff --git a/include/block/block-io.h b/include/block/block-io.h
30
diff --git a/include/block/block-io.h b/include/block/block-io.h
35
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block-io.h
32
--- a/include/block/block-io.h
37
+++ b/include/block/block-io.h
33
+++ b/include/block/block-io.h
38
@@ -XXX,XX +XXX,XX @@ bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
34
@@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs);
39
/* Ensure contents are flushed to disk. */
35
bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
40
int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
36
bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
41
37
42
-int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
38
-void bdrv_lock_medium(BlockDriverState *bs, bool locked);
43
- int64_t bytes);
39
+void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
44
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
40
void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
45
+ int64_t bytes);
41
46
+
42
const char *bdrv_get_format_name(BlockDriverState *bs);
47
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
48
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
49
int64_t bytes, int64_t *pnum, int64_t *map,
50
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
51
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block_int-common.h
45
--- a/include/block/block_int-common.h
53
+++ b/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
54
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
55
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
48
/* removable device specific */
56
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
49
bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
57
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
50
void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
58
- BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
51
- void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
59
- int64_t offset, int bytes,
52
+ void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
53
54
/* to control generic scsi devices */
55
BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
56
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
57
index XXXXXXX..XXXXXXX 100644
58
--- a/include/sysemu/block-backend-io.h
59
+++ b/include/sysemu/block-backend-io.h
60
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
61
bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
62
63
bool blk_is_available(BlockBackend *blk);
64
-void blk_lock_medium(BlockBackend *blk, bool locked);
60
+
65
+
61
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pdiscard)(
66
+void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked);
62
+ BlockDriverState *bs, int64_t offset, int bytes,
67
+void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked);
63
BlockCompletionFunc *cb, void *opaque);
68
64
69
void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag);
65
int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
70
void co_wrapper blk_eject(BlockBackend *blk, bool eject_flag);
66
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
71
diff --git a/block.c b/block.c
67
*/
72
index XXXXXXX..XXXXXXX 100644
68
int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
73
--- a/block.c
69
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
74
+++ b/block.c
70
- int coroutine_fn (*bdrv_co_pdiscard)(BlockDriverState *bs,
75
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
71
- int64_t offset, int64_t bytes);
76
* Lock or unlock the media (if it is locked, the user won't be able
72
+
77
* to eject it manually).
73
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)(
78
*/
74
+ BlockDriverState *bs, int64_t offset, int64_t bytes);
79
-void bdrv_lock_medium(BlockDriverState *bs, bool locked)
75
80
+void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
76
/*
81
{
77
* Map [offset, offset + nbytes) range onto a child of @bs to copy from,
82
BlockDriver *drv = bs->drv;
78
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
83
IO_CODE();
79
int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs,
84
trace_bdrv_lock_medium(bs, locked);
80
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
85
81
int64_t *map, BlockDriverState **file);
86
- if (drv && drv->bdrv_lock_medium) {
82
- int coroutine_fn (*bdrv_co_pdiscard_snapshot)(BlockDriverState *bs,
87
- drv->bdrv_lock_medium(bs, locked);
83
- int64_t offset, int64_t bytes);
88
+ if (drv && drv->bdrv_co_lock_medium) {
84
+
89
+ drv->bdrv_co_lock_medium(bs, locked);
85
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
90
}
86
+ BlockDriverState *bs, int64_t offset, int64_t bytes);
91
}
87
92
88
/*
89
* Invalidate any cached meta-data.
90
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
91
index XXXXXXX..XXXXXXX 100644
92
--- a/include/block/block_int-io.h
93
+++ b/include/block/block_int-io.h
94
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child,
95
int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs,
96
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
97
int64_t *map, BlockDriverState **file);
98
-int coroutine_fn bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
99
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
100
int64_t offset, int64_t bytes);
101
102
103
diff --git a/block/blkdebug.c b/block/blkdebug.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/blkdebug.c
106
+++ b/block/blkdebug.c
107
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
108
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
109
}
110
111
-static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
112
- int64_t offset, int64_t bytes)
113
+static int coroutine_fn GRAPH_RDLOCK
114
+blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
115
{
116
uint32_t align = bs->bl.pdiscard_alignment;
117
int err;
118
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/block/blklogwrites.c
121
+++ b/block/blklogwrites.c
122
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
123
return bdrv_co_flush(fr->bs->file->bs);
124
}
125
126
-static int coroutine_fn
127
+static int coroutine_fn GRAPH_RDLOCK
128
blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
129
{
130
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
131
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
132
LOG_FLUSH_FLAG, false);
133
}
134
135
-static int coroutine_fn
136
+static int coroutine_fn GRAPH_RDLOCK
137
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
138
{
139
- assume_graph_lock(); /* FIXME */
140
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,
141
blk_log_writes_co_do_file_pdiscard,
142
LOG_DISCARD_FLAG, false);
143
diff --git a/block/blkreplay.c b/block/blkreplay.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/block/blkreplay.c
146
+++ b/block/blkreplay.c
147
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
148
return ret;
149
}
150
151
-static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
152
- int64_t offset, int64_t bytes)
153
+static int coroutine_fn GRAPH_RDLOCK
154
+blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
155
{
156
uint64_t reqid = blkreplay_next_id();
157
int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
158
diff --git a/block/block-backend.c b/block/block-backend.c
93
diff --git a/block/block-backend.c b/block/block-backend.c
159
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
160
--- a/block/block-backend.c
95
--- a/block/block-backend.c
161
+++ b/block/block-backend.c
96
+++ b/block/block-backend.c
162
@@ -XXX,XX +XXX,XX @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
97
@@ -XXX,XX +XXX,XX @@ bool blk_is_available(BlockBackend *blk)
98
return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
99
}
100
101
-void blk_lock_medium(BlockBackend *blk, bool locked)
102
+void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
103
{
104
BlockDriverState *bs = blk_bs(blk);
163
IO_CODE();
105
IO_CODE();
164
106
165
blk_wait_while_drained(blk);
107
if (bs) {
166
+ GRAPH_RDLOCK_GUARD();
108
- bdrv_lock_medium(bs, locked);
167
109
+ bdrv_co_lock_medium(bs, locked);
168
ret = blk_check_byte_request(blk, offset, bytes);
110
}
169
if (ret < 0) {
111
}
170
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/copy-before-write.c
173
+++ b/block/copy-before-write.c
174
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
175
return 0;
176
}
177
178
-static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
179
- int64_t offset, int64_t bytes)
180
+static int coroutine_fn GRAPH_RDLOCK
181
+cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
182
{
183
int ret = cbw_do_copy_before_write(bs, offset, bytes, 0);
184
if (ret < 0) {
185
@@ -XXX,XX +XXX,XX @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
186
return ret;
187
}
188
189
-static int coroutine_fn cbw_co_pdiscard_snapshot(BlockDriverState *bs,
190
- int64_t offset, int64_t bytes)
191
+static int coroutine_fn GRAPH_RDLOCK
192
+cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
193
{
194
BDRVCopyBeforeWriteState *s = bs->opaque;
195
112
196
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
113
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
197
index XXXXXXX..XXXXXXX 100644
114
index XXXXXXX..XXXXXXX 100644
198
--- a/block/copy-on-read.c
115
--- a/block/copy-on-read.c
199
+++ b/block/copy-on-read.c
116
+++ b/block/copy-on-read.c
200
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
117
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
201
}
118
}
202
119
203
120
204
-static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
121
-static void cor_lock_medium(BlockDriverState *bs, bool locked)
205
- int64_t offset, int64_t bytes)
122
+static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
206
+static int coroutine_fn GRAPH_RDLOCK
123
{
207
+cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
124
- bdrv_lock_medium(bs->file->bs, locked);
208
{
125
+ bdrv_co_lock_medium(bs->file->bs, locked);
209
return bdrv_co_pdiscard(bs->file, offset, bytes);
126
}
210
}
127
128
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = {
130
.bdrv_co_pwritev_compressed = cor_co_pwritev_compressed,
131
132
.bdrv_co_eject = cor_co_eject,
133
- .bdrv_lock_medium = cor_lock_medium,
134
+ .bdrv_co_lock_medium = cor_co_lock_medium,
135
136
.has_variable_length = true,
137
.is_filter = true,
138
diff --git a/block/file-posix.c b/block/file-posix.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/file-posix.c
141
+++ b/block/file-posix.c
142
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
143
}
144
}
145
146
-static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
147
+static void coroutine_fn cdrom_co_lock_medium(BlockDriverState *bs, bool locked)
148
{
149
BDRVRawState *s = bs->opaque;
150
151
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
152
/* removable device support */
153
.bdrv_co_is_inserted = cdrom_co_is_inserted,
154
.bdrv_co_eject = cdrom_co_eject,
155
- .bdrv_lock_medium = cdrom_lock_medium,
156
+ .bdrv_co_lock_medium = cdrom_co_lock_medium,
157
158
/* generic scsi device */
159
.bdrv_co_ioctl = hdev_co_ioctl,
160
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag)
161
cdrom_reopen(bs);
162
}
163
164
-static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
165
+static void coroutine_fn cdrom_co_lock_medium(BlockDriverState *bs, bool locked)
166
{
167
BDRVRawState *s = bs->opaque;
168
169
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
170
/* removable device support */
171
.bdrv_co_is_inserted = cdrom_co_is_inserted,
172
.bdrv_co_eject = cdrom_co_eject,
173
- .bdrv_lock_medium = cdrom_lock_medium,
174
+ .bdrv_co_lock_medium = cdrom_co_lock_medium,
175
};
176
#endif /* __FreeBSD__ */
177
211
diff --git a/block/filter-compress.c b/block/filter-compress.c
178
diff --git a/block/filter-compress.c b/block/filter-compress.c
212
index XXXXXXX..XXXXXXX 100644
179
index XXXXXXX..XXXXXXX 100644
213
--- a/block/filter-compress.c
180
--- a/block/filter-compress.c
214
+++ b/block/filter-compress.c
181
+++ b/block/filter-compress.c
215
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
182
@@ -XXX,XX +XXX,XX @@ compress_co_eject(BlockDriverState *bs, bool eject_flag)
216
}
183
}
217
184
218
185
219
-static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
186
-static void compress_lock_medium(BlockDriverState *bs, bool locked)
220
- int64_t offset, int64_t bytes)
187
+static void coroutine_fn
221
+static int coroutine_fn GRAPH_RDLOCK
188
+compress_co_lock_medium(BlockDriverState *bs, bool locked)
222
+compress_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
189
{
223
{
190
- bdrv_lock_medium(bs->file->bs, locked);
224
return bdrv_co_pdiscard(bs->file, offset, bytes);
191
+ bdrv_co_lock_medium(bs->file->bs, locked);
225
}
192
}
226
diff --git a/block/io.c b/block/io.c
193
227
index XXXXXXX..XXXXXXX 100644
194
228
--- a/block/io.c
195
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = {
229
+++ b/block/io.c
196
.bdrv_refresh_limits = compress_refresh_limits,
230
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
197
231
int head, tail, align;
198
.bdrv_co_eject = compress_co_eject,
232
BlockDriverState *bs = child->bs;
199
- .bdrv_lock_medium = compress_lock_medium,
233
IO_CODE();
200
+ .bdrv_co_lock_medium = compress_co_lock_medium,
234
+ assert_bdrv_graph_readable();
201
235
202
.has_variable_length = true,
236
if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
203
.is_filter = true,
237
return -ENOMEDIUM;
238
@@ -XXX,XX +XXX,XX @@ bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
239
BlockDriver *drv = bs->drv;
240
int ret;
241
IO_CODE();
242
+ assert_bdrv_graph_readable();
243
244
if (!drv) {
245
return -ENOMEDIUM;
246
diff --git a/block/mirror.c b/block/mirror.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/block/mirror.c
249
+++ b/block/mirror.c
250
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
251
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
252
}
253
254
-static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs,
255
- MirrorMethod method, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
256
- int flags)
257
+static int coroutine_fn GRAPH_RDLOCK
258
+bdrv_mirror_top_do_write(BlockDriverState *bs, MirrorMethod method,
259
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
260
+ int flags)
261
{
262
MirrorOp *op = NULL;
263
MirrorBDSOpaque *s = bs->opaque;
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
265
int ret = 0;
266
bool copy_to_target = false;
267
268
+ assume_graph_lock(); /* FIXME */
269
+
270
if (s->job) {
271
copy_to_target = s->job->ret >= 0 &&
272
!job_is_cancelled(&s->job->common.job) &&
273
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
274
static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
275
int64_t offset, int64_t bytes, BdrvRequestFlags flags)
276
{
277
+ assume_graph_lock(); /* FIXME */
278
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
279
flags);
280
}
281
282
-static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,
283
- int64_t offset, int64_t bytes)
284
+static int coroutine_fn GRAPH_RDLOCK
285
+bdrv_mirror_top_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
286
{
287
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_DISCARD, offset, bytes,
288
NULL, 0);
289
diff --git a/block/preallocate.c b/block/preallocate.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/block/preallocate.c
292
+++ b/block/preallocate.c
293
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_preadv_part(
294
flags);
295
}
296
297
-static int coroutine_fn preallocate_co_pdiscard(BlockDriverState *bs,
298
- int64_t offset, int64_t bytes)
299
+static int coroutine_fn GRAPH_RDLOCK
300
+preallocate_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
301
{
302
return bdrv_co_pdiscard(bs->file, offset, bytes);
303
}
304
diff --git a/block/raw-format.c b/block/raw-format.c
204
diff --git a/block/raw-format.c b/block/raw-format.c
305
index XXXXXXX..XXXXXXX 100644
205
index XXXXXXX..XXXXXXX 100644
306
--- a/block/raw-format.c
206
--- a/block/raw-format.c
307
+++ b/block/raw-format.c
207
+++ b/block/raw-format.c
308
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
208
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
309
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
209
bdrv_co_eject(bs->file->bs, eject_flag);
310
}
210
}
311
211
312
-static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
212
-static void raw_lock_medium(BlockDriverState *bs, bool locked)
313
- int64_t offset, int64_t bytes)
213
+static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
314
+static int coroutine_fn GRAPH_RDLOCK
214
{
315
+raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
215
- bdrv_lock_medium(bs->file->bs, locked);
316
{
216
+ bdrv_co_lock_medium(bs->file->bs, locked);
317
int ret;
217
}
318
218
319
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
219
static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
320
index XXXXXXX..XXXXXXX 100644
220
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
321
--- a/block/snapshot-access.c
221
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
322
+++ b/block/snapshot-access.c
222
.bdrv_probe_geometry = &raw_probe_geometry,
323
@@ -XXX,XX +XXX,XX @@ snapshot_access_co_block_status(BlockDriverState *bs,
223
.bdrv_co_eject = &raw_co_eject,
324
bytes, pnum, map, file);
224
- .bdrv_lock_medium = &raw_lock_medium,
325
}
225
+ .bdrv_co_lock_medium = &raw_co_lock_medium,
326
226
.bdrv_co_ioctl = &raw_co_ioctl,
327
-static int coroutine_fn snapshot_access_co_pdiscard(BlockDriverState *bs,
227
.create_opts = &raw_create_opts,
328
- int64_t offset, int64_t bytes)
228
.bdrv_has_zero_init = &raw_has_zero_init,
329
+static int coroutine_fn GRAPH_RDLOCK
330
+snapshot_access_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
331
{
332
return bdrv_co_pdiscard_snapshot(bs->file->bs, offset, bytes);
333
}
334
diff --git a/block/throttle.c b/block/throttle.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/block/throttle.c
337
+++ b/block/throttle.c
338
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
339
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
340
}
341
342
-static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
343
- int64_t offset, int64_t bytes)
344
+static int coroutine_fn GRAPH_RDLOCK
345
+throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
346
{
347
ThrottleGroupMember *tgm = bs->opaque;
348
throttle_group_co_io_limits_intercept(tgm, bytes, true);
349
--
229
--
350
2.39.2
230
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_co_pwrite_zeroes() need to hold a reader lock for the graph.
3
2
4
For some places, we know that they will hold the lock, but we don't have
3
bdrv_debug_event() is categorized as an I/O function, and it currently
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
4
doesn't run in a coroutine. We should let it take a graph rdlock since
6
with a FIXME comment. These places will be removed once everything is
5
it traverses the block nodes graph, which however is only possible in a
7
properly annotated.
6
coroutine.
8
7
8
Therefore turn it into a co_wrapper_mixed to move the actual function
9
into a coroutine where the lock can be taken.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230203152202.49054-10-kwolf@redhat.com>
13
Message-Id: <20230113204212.359076-14-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
16
---
14
block/qcow2.h | 6 ++++--
17
include/block/block-io.h | 5 ++++-
15
include/block/block-io.h | 9 +++++----
18
include/block/block_int-common.h | 3 ++-
16
include/block/block_int-common.h | 5 +++--
19
block.c | 6 +++---
17
block/blkdebug.c | 6 +++---
20
block/blkdebug.c | 5 +++--
18
block/blklogwrites.c | 5 ++---
21
block/io.c | 22 +++++++++++-----------
19
block/blkreplay.c | 5 +++--
22
5 files changed, 23 insertions(+), 18 deletions(-)
20
block/block-copy.c | 13 +++++++------
21
block/copy-before-write.c | 5 +++--
22
block/copy-on-read.c | 6 +++---
23
block/filter-compress.c | 6 +++---
24
block/io.c | 12 +++++++++---
25
block/mirror.c | 6 +++---
26
block/preallocate.c | 11 +++++++----
27
block/qcow2.c | 30 ++++++++++++++++++------------
28
block/qed.c | 9 +++------
29
block/quorum.c | 15 ++++++++++-----
30
block/raw-format.c | 6 +++---
31
block/throttle.c | 6 +++---
32
18 files changed, 92 insertions(+), 69 deletions(-)
33
23
34
diff --git a/block/qcow2.h b/block/qcow2.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/qcow2.h
37
+++ b/block/qcow2.h
38
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
39
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
40
uint64_t bytes, enum qcow2_discard_type type,
41
bool full_discard);
42
-int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
43
- uint64_t bytes, int flags);
44
+
45
+int coroutine_fn GRAPH_RDLOCK
46
+qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
47
+ int flags);
48
49
int qcow2_expand_zero_clusters(BlockDriverState *bs,
50
BlockDriverAmendStatusCB *status_cb,
51
diff --git a/include/block/block-io.h b/include/block/block-io.h
24
diff --git a/include/block/block-io.h b/include/block/block-io.h
52
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
53
--- a/include/block/block-io.h
26
--- a/include/block/block-io.h
54
+++ b/include/block/block-io.h
27
+++ b/include/block/block-io.h
55
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
28
@@ -XXX,XX +XXX,XX @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
56
* function is not suitable for zeroing the entire image in a single request
29
void bdrv_enable_copy_on_read(BlockDriverState *bs);
57
* because it may allocate memory for the entire region.
30
void bdrv_disable_copy_on_read(BlockDriverState *bs);
58
*/
31
59
-int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
32
-void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event);
60
- int64_t bytes, BdrvRequestFlags flags);
33
+void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs,
61
+int coroutine_fn GRAPH_RDLOCK
34
+ BlkdebugEvent event);
62
+bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes,
35
+void co_wrapper_mixed bdrv_debug_event(BlockDriverState *bs,
63
+ BdrvRequestFlags flags);
36
+ BlkdebugEvent event);
64
37
65
int coroutine_fn GRAPH_RDLOCK
38
#define BLKDBG_EVENT(child, evt) \
66
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
39
do { \
67
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
68
bool include_base, int64_t offset, int64_t bytes,
69
int64_t *pnum);
70
71
-int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
72
- int64_t bytes);
73
+int coroutine_fn GRAPH_RDLOCK
74
+bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
75
76
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
77
Error **errp);
78
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
40
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
79
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
80
--- a/include/block/block_int-common.h
42
--- a/include/block/block_int-common.h
81
+++ b/include/block/block_int-common.h
43
+++ b/include/block/block_int-common.h
82
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
83
* function pointer may be NULL or return -ENOSUP and .bdrv_co_writev()
45
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_check)(
84
* will be called instead.
46
BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix);
85
*/
47
86
- int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
48
- void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
87
- int64_t offset, int64_t bytes, BdrvRequestFlags flags);
49
+ void coroutine_fn (*bdrv_co_debug_event)(BlockDriverState *bs,
88
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwrite_zeroes)(
50
+ BlkdebugEvent event);
89
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
51
90
+ BdrvRequestFlags flags);
52
/* io queue for linux-aio */
91
53
void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
92
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)(
54
diff --git a/block.c b/block.c
93
BlockDriverState *bs, int64_t offset, int64_t bytes);
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block.c
57
+++ b/block.c
58
@@ -XXX,XX +XXX,XX @@ BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
59
return drv->bdrv_get_specific_stats(bs);
60
}
61
62
-void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
63
+void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
64
{
65
IO_CODE();
66
- if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
67
+ if (!bs || !bs->drv || !bs->drv->bdrv_co_debug_event) {
68
return;
69
}
70
71
- bs->drv->bdrv_debug_event(bs, event);
72
+ bs->drv->bdrv_co_debug_event(bs, event);
73
}
74
75
static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
94
diff --git a/block/blkdebug.c b/block/blkdebug.c
76
diff --git a/block/blkdebug.c b/block/blkdebug.c
95
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
96
--- a/block/blkdebug.c
78
--- a/block/blkdebug.c
97
+++ b/block/blkdebug.c
79
+++ b/block/blkdebug.c
98
@@ -XXX,XX +XXX,XX @@ static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
80
@@ -XXX,XX +XXX,XX @@ static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
99
return bdrv_co_flush(bs->file->bs);
81
}
100
}
82
}
101
83
102
-static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
84
-static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event)
103
- int64_t offset, int64_t bytes,
85
+static void coroutine_fn
104
- BdrvRequestFlags flags)
86
+blkdebug_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
105
+static int coroutine_fn GRAPH_RDLOCK
106
+blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
107
+ BdrvRequestFlags flags)
108
{
87
{
109
uint32_t align = MAX(bs->bl.request_alignment,
88
BDRVBlkdebugState *s = bs->opaque;
110
bs->bl.pwrite_zeroes_alignment);
89
struct BlkdebugRule *rule, *next;
111
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
90
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
112
index XXXXXXX..XXXXXXX 100644
91
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
113
--- a/block/blklogwrites.c
92
.bdrv_co_block_status = blkdebug_co_block_status,
114
+++ b/block/blklogwrites.c
93
115
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
94
- .bdrv_debug_event = blkdebug_debug_event,
116
fr->qiov, fr->file_flags);
95
+ .bdrv_co_debug_event = blkdebug_co_debug_event,
117
}
96
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
118
97
.bdrv_debug_remove_breakpoint
119
-static int coroutine_fn
98
= blkdebug_debug_remove_breakpoint,
120
+static int coroutine_fn GRAPH_RDLOCK
121
blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
122
{
123
return bdrv_co_pwrite_zeroes(fr->bs->file, fr->offset, fr->bytes,
124
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
125
blk_log_writes_co_do_file_pwritev, 0, false);
126
}
127
128
-static int coroutine_fn
129
+static int coroutine_fn GRAPH_RDLOCK
130
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
131
int64_t bytes, BdrvRequestFlags flags)
132
{
133
- assume_graph_lock(); /* FIXME */
134
return blk_log_writes_co_log(bs, offset, bytes, NULL, flags,
135
blk_log_writes_co_do_file_pwrite_zeroes, 0,
136
true);
137
diff --git a/block/blkreplay.c b/block/blkreplay.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/block/blkreplay.c
140
+++ b/block/blkreplay.c
141
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
142
return ret;
143
}
144
145
-static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
146
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
147
+static int coroutine_fn GRAPH_RDLOCK
148
+blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
149
+ BdrvRequestFlags flags)
150
{
151
uint64_t reqid = blkreplay_next_id();
152
int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
153
diff --git a/block/block-copy.c b/block/block-copy.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/block/block-copy.c
156
+++ b/block/block-copy.c
157
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
158
* value of @method should be used for subsequent tasks.
159
* Returns 0 on success.
160
*/
161
-static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
162
- int64_t offset, int64_t bytes,
163
- BlockCopyMethod *method,
164
- bool *error_is_read)
165
+static int coroutine_fn GRAPH_RDLOCK
166
+block_copy_do_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
167
+ BlockCopyMethod *method, bool *error_is_read)
168
{
169
int ret;
170
int64_t nbytes = MIN(offset + bytes, s->len) - offset;
171
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
172
BlockCopyMethod method = t->method;
173
int ret;
174
175
- ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
176
- &error_is_read);
177
+ WITH_GRAPH_RDLOCK_GUARD() {
178
+ ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
179
+ &error_is_read);
180
+ }
181
182
WITH_QEMU_LOCK_GUARD(&s->lock) {
183
if (s->method == t->method) {
184
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/block/copy-before-write.c
187
+++ b/block/copy-before-write.c
188
@@ -XXX,XX +XXX,XX @@ cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
189
return bdrv_co_pdiscard(bs->file, offset, bytes);
190
}
191
192
-static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
193
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
194
+static int coroutine_fn GRAPH_RDLOCK
195
+cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
196
+ BdrvRequestFlags flags)
197
{
198
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
199
if (ret < 0) {
200
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
201
index XXXXXXX..XXXXXXX 100644
202
--- a/block/copy-on-read.c
203
+++ b/block/copy-on-read.c
204
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
205
}
206
207
208
-static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
209
- int64_t offset, int64_t bytes,
210
- BdrvRequestFlags flags)
211
+static int coroutine_fn GRAPH_RDLOCK
212
+cor_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
213
+ BdrvRequestFlags flags)
214
{
215
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
216
}
217
diff --git a/block/filter-compress.c b/block/filter-compress.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/filter-compress.c
220
+++ b/block/filter-compress.c
221
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
222
}
223
224
225
-static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
226
- int64_t offset, int64_t bytes,
227
- BdrvRequestFlags flags)
228
+static int coroutine_fn GRAPH_RDLOCK
229
+compress_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
230
+ BdrvRequestFlags flags)
231
{
232
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
233
}
234
diff --git a/block/io.c b/block/io.c
99
diff --git a/block/io.c b/block/io.c
235
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
236
--- a/block/io.c
101
--- a/block/io.c
237
+++ b/block/io.c
102
+++ b/block/io.c
238
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
239
int64_t progress = 0;
104
goto err;
240
bool skip_write;
105
}
241
106
242
+ assume_graph_lock(); /* FIXME */
107
- bdrv_debug_event(bs, BLKDBG_COR_WRITE);
243
+
108
+ bdrv_co_debug_event(bs, BLKDBG_COR_WRITE);
244
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
109
if (drv->bdrv_co_pwrite_zeroes &&
245
110
buffer_is_zero(bounce_buffer, pnum)) {
246
if (!drv) {
111
/* FIXME: Should we (perhaps conditionally) be setting
247
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
112
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
248
bs->bl.request_alignment);
113
qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
249
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
114
250
115
if (pad->head) {
251
+ assert_bdrv_graph_readable();
116
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
252
bdrv_check_request(offset, bytes, &error_abort);
117
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
253
118
}
254
if (!drv) {
119
if (pad->merge_reads && pad->tail) {
120
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
121
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
122
}
123
ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
124
align, &local_qiov, 0, 0);
125
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
126
return ret;
127
}
128
if (pad->head) {
129
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
130
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
131
}
132
if (pad->merge_reads && pad->tail) {
133
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
134
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
135
}
136
137
if (pad->merge_reads) {
138
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
139
if (pad->tail) {
140
qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
141
142
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
143
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
144
ret = bdrv_aligned_preadv(
145
child, req,
146
req->overlap_offset + req->overlap_bytes - align,
147
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
148
if (ret < 0) {
149
return ret;
150
}
151
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
152
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
153
}
154
155
zero_mem:
255
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
156
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
256
int64_t bytes_remaining = bytes;
157
if (ret < 0) {
257
int max_transfer;
158
/* Do nothing, write notifier decided to fail this request */
258
159
} else if (flags & BDRV_REQ_ZERO_WRITE) {
259
+ assume_graph_lock(); /* FIXME */
160
- bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
260
+
161
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_ZERO);
261
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
162
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
262
163
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
263
if (!drv) {
164
ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
264
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
165
qiov, qiov_offset);
265
{
166
} else if (bytes <= max_transfer) {
266
IO_CODE();
167
- bdrv_debug_event(bs, BLKDBG_PWRITEV);
267
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
168
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV);
268
+ assert_bdrv_graph_readable();
169
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags);
269
170
} else {
270
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
171
- bdrv_debug_event(bs, BLKDBG_PWRITEV);
271
flags &= ~BDRV_REQ_MAY_UNMAP;
172
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV);
272
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
173
while (bytes_remaining) {
273
int64_t pnum = bytes;
174
int num = MIN(bytes_remaining, max_transfer);
274
IO_CODE();
175
int local_flags = flags;
275
176
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
276
- assume_graph_lock(); /* FIXME */
177
bytes_remaining -= num;
277
-
178
}
278
if (!bytes) {
279
return 1;
280
}
179
}
281
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
180
- bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);
282
}
181
+ bdrv_co_debug_event(bs, BLKDBG_PWRITEV_DONE);
283
}
182
284
183
if (ret >= 0) {
285
-static int coroutine_fn bdrv_co_copy_range_internal(
184
ret = 0;
286
+static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
287
BdrvChild *src, int64_t src_offset, BdrvChild *dst,
288
int64_t dst_offset, int64_t bytes,
289
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
290
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
291
BdrvRequestFlags write_flags)
292
{
293
IO_CODE();
294
+ assume_graph_lock(); /* FIXME */
295
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
296
read_flags, write_flags);
297
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
298
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
299
BdrvRequestFlags write_flags)
300
{
301
IO_CODE();
302
+ assume_graph_lock(); /* FIXME */
303
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
304
read_flags, write_flags);
305
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
306
diff --git a/block/mirror.c b/block/mirror.c
307
index XXXXXXX..XXXXXXX 100644
308
--- a/block/mirror.c
309
+++ b/block/mirror.c
310
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
311
return bdrv_co_flush(bs->backing->bs);
312
}
313
314
-static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
315
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
316
+static int coroutine_fn GRAPH_RDLOCK
317
+bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
318
+ int64_t bytes, BdrvRequestFlags flags)
319
{
320
- assume_graph_lock(); /* FIXME */
321
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
322
flags);
323
}
324
diff --git a/block/preallocate.c b/block/preallocate.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/block/preallocate.c
327
+++ b/block/preallocate.c
328
@@ -XXX,XX +XXX,XX @@ static bool has_prealloc_perms(BlockDriverState *bs)
329
* want_merge_zero is used to merge write-zero request with preallocation in
330
* one bdrv_co_pwrite_zeroes() call.
331
*/
332
-static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
333
- int64_t bytes, bool want_merge_zero)
334
+static bool coroutine_fn GRAPH_RDLOCK
335
+handle_write(BlockDriverState *bs, int64_t offset, int64_t bytes,
336
+ bool want_merge_zero)
337
{
338
BDRVPreallocateState *s = bs->opaque;
339
int64_t end = offset + bytes;
340
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
341
return want_merge_zero;
342
}
343
344
-static int coroutine_fn preallocate_co_pwrite_zeroes(BlockDriverState *bs,
345
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
346
+static int coroutine_fn GRAPH_RDLOCK
347
+preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
348
+ int64_t bytes, BdrvRequestFlags flags)
349
{
350
bool want_merge_zero =
351
!(flags & ~(BDRV_REQ_ZERO_WRITE | BDRV_REQ_NO_FALLBACK));
352
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
353
size_t qiov_offset,
354
BdrvRequestFlags flags)
355
{
356
+ assume_graph_lock(); /* FIXME */
357
handle_write(bs, offset, bytes, false);
358
359
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
360
diff --git a/block/qcow2.c b/block/qcow2.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/qcow2.c
363
+++ b/block/qcow2.c
364
@@ -XXX,XX +XXX,XX @@ static bool merge_cow(uint64_t offset, unsigned bytes,
365
* Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error.
366
* Note that returning 0 does not guarantee non-zero data.
367
*/
368
-static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
369
+static int coroutine_fn GRAPH_RDLOCK
370
+is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
371
{
372
/*
373
* This check is designed for optimization shortcut so it must be
374
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
375
m->cow_end.nb_bytes);
376
}
377
378
-static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
379
- QCowL2Meta *l2meta)
380
+static int coroutine_fn GRAPH_RDLOCK
381
+handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
382
{
383
BDRVQcow2State *s = bs->opaque;
384
QCowL2Meta *m;
385
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
386
* l2meta - if not NULL, qcow2_co_pwritev_task() will consume it. Caller must
387
* not use it somehow after qcow2_co_pwritev_task() call
388
*/
389
-static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
390
- uint64_t host_offset,
391
- uint64_t offset, uint64_t bytes,
392
- QEMUIOVector *qiov,
393
- uint64_t qiov_offset,
394
- QCowL2Meta *l2meta)
395
+static coroutine_fn GRAPH_RDLOCK
396
+int qcow2_co_pwritev_task(BlockDriverState *bs, uint64_t host_offset,
397
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
398
+ uint64_t qiov_offset, QCowL2Meta *l2meta)
399
{
400
int ret;
401
BDRVQcow2State *s = bs->opaque;
402
@@ -XXX,XX +XXX,XX @@ out_locked:
403
return ret;
404
}
405
406
-static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
407
+/*
408
+ * This function can count as GRAPH_RDLOCK because qcow2_co_pwritev_part() holds
409
+ * the graph lock and keeps it until this coroutine has terminated.
410
+ */
411
+static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task)
412
{
413
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
414
415
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
416
QCowL2Meta *l2meta = NULL;
417
AioTaskPool *aio = NULL;
418
419
+ assume_graph_lock(); /* FIXME */
420
+
421
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
422
423
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
424
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
425
return res >= 0 && (res & BDRV_BLOCK_ZERO) && bytes == 0;
426
}
427
428
-static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
429
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
430
+static int coroutine_fn GRAPH_RDLOCK
431
+qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
432
+ BdrvRequestFlags flags)
433
{
434
int ret;
435
BDRVQcow2State *s = bs->opaque;
436
diff --git a/block/qed.c b/block/qed.c
437
index XXXXXXX..XXXXXXX 100644
438
--- a/block/qed.c
439
+++ b/block/qed.c
440
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
441
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
442
}
443
444
-static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
445
- int64_t offset,
446
- int64_t bytes,
447
- BdrvRequestFlags flags)
448
+static int coroutine_fn GRAPH_RDLOCK
449
+bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
450
+ BdrvRequestFlags flags)
451
{
452
BDRVQEDState *s = bs->opaque;
453
454
- assume_graph_lock(); /* FIXME */
455
-
456
/*
457
* Zero writes start without an I/O buffer. If a buffer becomes necessary
458
* then it will be allocated during request processing.
459
diff --git a/block/quorum.c b/block/quorum.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/block/quorum.c
462
+++ b/block/quorum.c
463
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
464
return ret;
465
}
466
467
-static void coroutine_fn write_quorum_entry(void *opaque)
468
+/*
469
+ * This function can count as GRAPH_RDLOCK because quorum_co_pwritev() holds the
470
+ * graph lock and keeps it until this coroutine has terminated.
471
+ */
472
+static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque)
473
{
474
QuorumCo *co = opaque;
475
QuorumAIOCB *acb = co->acb;
476
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
477
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
478
int i, ret;
479
480
+ assume_graph_lock(); /* FIXME */
481
+
482
for (i = 0; i < s->num_children; i++) {
483
Coroutine *co;
484
QuorumCo data = {
485
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
486
return ret;
487
}
488
489
-static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
490
- int64_t offset, int64_t bytes,
491
- BdrvRequestFlags flags)
492
-
493
+static int coroutine_fn GRAPH_RDLOCK
494
+quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
495
+ BdrvRequestFlags flags)
496
{
497
return quorum_co_pwritev(bs, offset, bytes, NULL,
498
flags | BDRV_REQ_ZERO_WRITE);
499
diff --git a/block/raw-format.c b/block/raw-format.c
500
index XXXXXXX..XXXXXXX 100644
501
--- a/block/raw-format.c
502
+++ b/block/raw-format.c
503
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
504
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
505
}
506
507
-static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
508
- int64_t offset, int64_t bytes,
509
- BdrvRequestFlags flags)
510
+static int coroutine_fn GRAPH_RDLOCK
511
+raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
512
+ BdrvRequestFlags flags)
513
{
514
int ret;
515
516
diff --git a/block/throttle.c b/block/throttle.c
517
index XXXXXXX..XXXXXXX 100644
518
--- a/block/throttle.c
519
+++ b/block/throttle.c
520
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
521
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
522
}
523
524
-static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
525
- int64_t offset, int64_t bytes,
526
- BdrvRequestFlags flags)
527
+static int coroutine_fn GRAPH_RDLOCK
528
+throttle_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
529
+ BdrvRequestFlags flags)
530
{
531
ThrottleGroupMember *tgm = bs->opaque;
532
throttle_group_co_io_limits_intercept(tgm, bytes, true);
533
--
185
--
534
2.39.2
186
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
bdrv_driver_*() need to hold a reader lock for the graph. It doesn't add
3
the annotation to public functions yet.
4
2
5
For some places, we know that they will hold the lock, but we don't have
3
Since these functions always run in coroutine context, adjust
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
4
their name to include "_co_", just like all other BlockDriver callbacks.
7
with a FIXME comment. These places will be removed once everything is
8
properly annotated.
9
5
6
No functional change intended.
7
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20230203152202.49054-11-kwolf@redhat.com>
10
Message-Id: <20230113204212.359076-15-kwolf@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
block/qcow2.h | 5 ++-
14
include/block/block_int-common.h | 4 ++--
16
include/block/block_int-common.h | 40 ++++++++++---------
15
block/io.c | 8 ++++----
17
block/io.c | 66 +++++++++++++++-----------------
16
block/qcow2.c | 12 ++++++------
18
block/parallels.c | 8 ++--
17
3 files changed, 12 insertions(+), 12 deletions(-)
19
block/qcow.c | 20 ++++------
20
block/qcow2-cluster.c | 10 ++---
21
block/qcow2.c | 37 ++++++++++--------
22
block/qed.c | 14 +++----
23
block/quorum.c | 8 ++--
24
block/vmdk.c | 4 +-
25
10 files changed, 101 insertions(+), 111 deletions(-)
26
18
27
diff --git a/block/qcow2.h b/block/qcow2.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/qcow2.h
30
+++ b/block/qcow2.h
31
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
32
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
33
uint64_t *coffset, int *csize);
34
35
-int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
36
- QCowL2Meta *m);
37
+int coroutine_fn GRAPH_RDLOCK
38
+qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
39
+
40
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
41
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
42
uint64_t bytes, enum qcow2_discard_type type,
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
19
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
44
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/block_int-common.h
21
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
22
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
23
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
Error **errp);
24
Error **errp);
49
25
BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs);
50
/* aio */
26
51
- BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
27
- int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_save_vmstate)(
52
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_preadv)(BlockDriverState *bs,
28
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_save_vmstate)(
53
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
29
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
54
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
30
55
- BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
31
- int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_load_vmstate)(
56
+
32
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_load_vmstate)(
57
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pwritev)(BlockDriverState *bs,
33
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
58
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
34
59
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
35
/* removable device specific */
60
+
61
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
62
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
63
64
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
65
BlockDriverState *bs, int64_t offset, int bytes,
66
BlockCompletionFunc *cb, void *opaque);
67
68
- int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
69
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_readv)(BlockDriverState *bs,
70
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
71
72
/**
73
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
74
*
75
* The buffer in @qiov may point directly to guest memory.
76
*/
77
- int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
78
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv)(BlockDriverState *bs,
79
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
80
BdrvRequestFlags flags);
81
82
- int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs,
83
- int64_t offset, int64_t bytes,
84
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_part)(
85
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
86
QEMUIOVector *qiov, size_t qiov_offset,
87
BdrvRequestFlags flags);
88
89
- int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
90
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_writev)(BlockDriverState *bs,
91
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
92
int flags);
93
/**
94
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
95
*
96
* The buffer in @qiov may point directly to guest memory.
97
*/
98
- int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs,
99
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
100
- BdrvRequestFlags flags);
101
- int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs,
102
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset,
103
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev)(
104
+ BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
105
BdrvRequestFlags flags);
106
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_part)(
107
+ BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
108
+ size_t qiov_offset, BdrvRequestFlags flags);
109
110
/*
111
* Efficiently zero a region of the disk image. Typically an image format
112
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
113
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
114
Error **errp);
115
116
- int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
117
- int64_t offset, int64_t bytes, QEMUIOVector *qiov);
118
- int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs,
119
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
120
- size_t qiov_offset);
121
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed)(
122
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
123
+ QEMUIOVector *qiov);
124
+
125
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed_part)(
126
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
127
+ QEMUIOVector *qiov, size_t qiov_offset);
128
129
int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
130
BlockDriverInfo *bdi);
131
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
132
BlockDriverState *bs, const char *name, Error **errp);
133
};
134
135
-static inline bool block_driver_can_compress(BlockDriver *drv)
136
+static inline bool TSA_NO_TSA block_driver_can_compress(BlockDriver *drv)
137
{
138
return drv->bdrv_co_pwritev_compressed ||
139
drv->bdrv_co_pwritev_compressed_part;
140
diff --git a/block/io.c b/block/io.c
36
diff --git a/block/io.c b/block/io.c
141
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
142
--- a/block/io.c
38
--- a/block/io.c
143
+++ b/block/io.c
39
+++ b/block/io.c
144
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
40
@@ -XXX,XX +XXX,XX @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
145
bool have_limits;
41
146
42
bdrv_inc_in_flight(bs);
147
GLOBAL_STATE_CODE();
43
148
+ assume_graph_lock(); /* FIXME */
44
- if (drv->bdrv_load_vmstate) {
149
45
- ret = drv->bdrv_load_vmstate(bs, qiov, pos);
150
if (tran) {
46
+ if (drv->bdrv_co_load_vmstate) {
151
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
47
+ ret = drv->bdrv_co_load_vmstate(bs, qiov, pos);
152
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
48
} else if (child_bs) {
153
aio_co_wake(co->coroutine);
49
ret = bdrv_co_readv_vmstate(child_bs, qiov, pos);
154
}
50
} else {
155
51
@@ -XXX,XX +XXX,XX @@ bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
156
-static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
52
157
- int64_t offset, int64_t bytes,
53
bdrv_inc_in_flight(bs);
158
- QEMUIOVector *qiov,
54
159
- size_t qiov_offset, int flags)
55
- if (drv->bdrv_save_vmstate) {
160
+static int coroutine_fn GRAPH_RDLOCK
56
- ret = drv->bdrv_save_vmstate(bs, qiov, pos);
161
+bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
57
+ if (drv->bdrv_co_save_vmstate) {
162
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
58
+ ret = drv->bdrv_co_save_vmstate(bs, qiov, pos);
163
{
59
} else if (child_bs) {
164
BlockDriver *drv = bs->drv;
60
ret = bdrv_co_writev_vmstate(child_bs, qiov, pos);
165
int64_t sector_num;
61
} else {
166
@@ -XXX,XX +XXX,XX @@ out:
167
return ret;
168
}
169
170
-static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
171
- int64_t offset, int64_t bytes,
172
- QEMUIOVector *qiov,
173
- size_t qiov_offset,
174
- BdrvRequestFlags flags)
175
+static int coroutine_fn GRAPH_RDLOCK
176
+bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
177
+ QEMUIOVector *qiov, size_t qiov_offset,
178
+ BdrvRequestFlags flags)
179
{
180
BlockDriver *drv = bs->drv;
181
bool emulate_fua = false;
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
183
QEMUIOVector local_qiov;
184
int ret;
185
186
- assume_graph_lock(); /* FIXME */
187
-
188
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
189
190
if (!drv) {
191
@@ -XXX,XX +XXX,XX @@ emulate_flags:
192
return ret;
193
}
194
195
-static int coroutine_fn
196
+static int coroutine_fn GRAPH_RDLOCK
197
bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
198
int64_t bytes, QEMUIOVector *qiov,
199
size_t qiov_offset)
200
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
201
return ret;
202
}
203
204
-static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
205
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
206
- size_t qiov_offset, int flags)
207
+static int coroutine_fn GRAPH_RDLOCK
208
+bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
209
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
210
{
211
BlockDriverState *bs = child->bs;
212
213
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
214
int64_t progress = 0;
215
bool skip_write;
216
217
- assume_graph_lock(); /* FIXME */
218
-
219
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
220
221
if (!drv) {
222
@@ -XXX,XX +XXX,XX @@ err:
223
* handles copy on read, zeroing after EOF, and fragmentation of large
224
* reads; any other features must be implemented by the caller.
225
*/
226
-static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
227
- BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
228
- int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
229
+static int coroutine_fn GRAPH_RDLOCK
230
+bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req,
231
+ int64_t offset, int64_t bytes, int64_t align,
232
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
233
{
234
BlockDriverState *bs = child->bs;
235
int64_t total_bytes, max_bytes;
236
@@ -XXX,XX +XXX,XX @@ static bool bdrv_init_padding(BlockDriverState *bs,
237
return true;
238
}
239
240
-static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
241
- BdrvTrackedRequest *req,
242
- BdrvRequestPadding *pad,
243
- bool zero_middle)
244
+static int coroutine_fn GRAPH_RDLOCK
245
+bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req,
246
+ BdrvRequestPadding *pad, bool zero_middle)
247
{
248
QEMUIOVector local_qiov;
249
BlockDriverState *bs = child->bs;
250
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
251
int ret;
252
IO_CODE();
253
254
+ assume_graph_lock(); /* FIXME */
255
+
256
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
257
258
if (!bdrv_co_is_inserted(bs)) {
259
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
260
* Forwards an already correctly aligned write request to the BlockDriver,
261
* after possibly fragmenting it.
262
*/
263
-static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
264
- BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
265
- int64_t align, QEMUIOVector *qiov, size_t qiov_offset,
266
- BdrvRequestFlags flags)
267
+static int coroutine_fn GRAPH_RDLOCK
268
+bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req,
269
+ int64_t offset, int64_t bytes, int64_t align,
270
+ QEMUIOVector *qiov, size_t qiov_offset,
271
+ BdrvRequestFlags flags)
272
{
273
BlockDriverState *bs = child->bs;
274
BlockDriver *drv = bs->drv;
275
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
276
int64_t bytes_remaining = bytes;
277
int max_transfer;
278
279
- assume_graph_lock(); /* FIXME */
280
-
281
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
282
283
if (!drv) {
284
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
285
return ret;
286
}
287
288
-static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
289
- int64_t offset,
290
- int64_t bytes,
291
- BdrvRequestFlags flags,
292
- BdrvTrackedRequest *req)
293
+static int coroutine_fn GRAPH_RDLOCK
294
+bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
295
+ BdrvRequestFlags flags, BdrvTrackedRequest *req)
296
{
297
BlockDriverState *bs = child->bs;
298
QEMUIOVector local_qiov;
299
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
300
bool padded = false;
301
IO_CODE();
302
303
+ assume_graph_lock(); /* FIXME */
304
+
305
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
306
307
if (!bdrv_co_is_inserted(bs)) {
308
diff --git a/block/parallels.c b/block/parallels.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/block/parallels.c
311
+++ b/block/parallels.c
312
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
313
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
314
}
315
316
-static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
317
- int64_t sector_num, int nb_sectors,
318
- QEMUIOVector *qiov, int flags)
319
+static int coroutine_fn GRAPH_RDLOCK
320
+parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
321
+ QEMUIOVector *qiov, int flags)
322
{
323
BDRVParallelsState *s = bs->opaque;
324
uint64_t bytes_done = 0;
325
QEMUIOVector hd_qiov;
326
int ret = 0;
327
328
- assume_graph_lock(); /* FIXME */
329
-
330
qemu_iovec_init(&hd_qiov, qiov->niov);
331
332
while (nb_sectors > 0) {
333
diff --git a/block/qcow.c b/block/qcow.c
334
index XXXXXXX..XXXXXXX 100644
335
--- a/block/qcow.c
336
+++ b/block/qcow.c
337
@@ -XXX,XX +XXX,XX @@ static void qcow_refresh_limits(BlockDriverState *bs, Error **errp)
338
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
339
}
340
341
-static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
342
- int64_t bytes, QEMUIOVector *qiov,
343
- BdrvRequestFlags flags)
344
+static int coroutine_fn GRAPH_RDLOCK
345
+qcow_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
346
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
347
{
348
BDRVQcowState *s = bs->opaque;
349
int offset_in_cluster;
350
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
351
uint8_t *buf;
352
void *orig_buf;
353
354
- assume_graph_lock(); /* FIXME */
355
-
356
if (qiov->niov > 1) {
357
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
358
if (buf == NULL) {
359
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
360
return ret;
361
}
362
363
-static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
364
- int64_t bytes, QEMUIOVector *qiov,
365
- BdrvRequestFlags flags)
366
+static int coroutine_fn GRAPH_RDLOCK
367
+qcow_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
368
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
369
{
370
BDRVQcowState *s = bs->opaque;
371
int offset_in_cluster;
372
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
373
uint8_t *buf;
374
void *orig_buf;
375
376
- assume_graph_lock(); /* FIXME */
377
-
378
s->cluster_cache_offset = -1; /* disable compressed cache */
379
380
/* We must always copy the iov when encrypting, so we
381
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
382
383
/* XXX: put compressed sectors first, then all the cluster aligned
384
tables to avoid losing bytes in alignment */
385
-static coroutine_fn int
386
+static int coroutine_fn GRAPH_RDLOCK
387
qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
388
QEMUIOVector *qiov)
389
{
390
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
391
uint8_t *buf, *out_buf;
392
uint64_t cluster_offset;
393
394
- assume_graph_lock(); /* FIXME */
395
-
396
buf = qemu_blockalign(bs, s->cluster_size);
397
if (bytes != s->cluster_size) {
398
if (bytes > s->cluster_size ||
399
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/block/qcow2-cluster.c
402
+++ b/block/qcow2-cluster.c
403
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters,
404
return count;
405
}
406
407
-static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
408
- uint64_t src_cluster_offset,
409
- unsigned offset_in_cluster,
410
- QEMUIOVector *qiov)
411
+static int coroutine_fn GRAPH_RDLOCK
412
+do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset,
413
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
414
{
415
int ret;
416
417
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
418
return 0;
419
}
420
421
-static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m)
422
+static int coroutine_fn GRAPH_RDLOCK
423
+perform_cow(BlockDriverState *bs, QCowL2Meta *m)
424
{
425
BDRVQcow2State *s = bs->opaque;
426
Qcow2COWRegion *start = &m->cow_start;
427
diff --git a/block/qcow2.c b/block/qcow2.c
62
diff --git a/block/qcow2.c b/block/qcow2.c
428
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
429
--- a/block/qcow2.c
64
--- a/block/qcow2.c
430
+++ b/block/qcow2.c
65
+++ b/block/qcow2.c
431
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
432
return status;
433
}
434
435
-static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
436
- QCowL2Meta **pl2meta,
437
- bool link_l2)
438
+static int coroutine_fn GRAPH_RDLOCK
439
+qcow2_handle_l2meta(BlockDriverState *bs, QCowL2Meta **pl2meta, bool link_l2)
440
{
441
int ret = 0;
442
QCowL2Meta *l2meta = *pl2meta;
443
@@ -XXX,XX +XXX,XX @@ static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task)
444
t->l2meta);
445
}
446
447
-static coroutine_fn int qcow2_co_pwritev_part(
448
- BlockDriverState *bs, int64_t offset, int64_t bytes,
449
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
450
+static int coroutine_fn GRAPH_RDLOCK
451
+qcow2_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
452
+ QEMUIOVector *qiov, size_t qiov_offset,
453
+ BdrvRequestFlags flags)
454
{
455
BDRVQcow2State *s = bs->opaque;
456
int offset_in_cluster;
457
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
458
QCowL2Meta *l2meta = NULL;
459
AioTaskPool *aio = NULL;
460
461
- assume_graph_lock(); /* FIXME */
462
-
463
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
464
465
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
466
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
467
uint64_t host_offset;
468
QCowL2Meta *l2meta = NULL;
469
470
+ assume_graph_lock(); /* FIXME */
471
assert(!bs->encrypted);
472
473
qemu_co_mutex_lock(&s->lock);
474
@@ -XXX,XX +XXX,XX @@ fail:
475
return ret;
476
}
477
478
-static coroutine_fn int
479
+static int coroutine_fn GRAPH_RDLOCK
480
qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
481
uint64_t offset, uint64_t bytes,
482
QEMUIOVector *qiov, size_t qiov_offset)
483
@@ -XXX,XX +XXX,XX @@ fail:
484
return ret;
485
}
486
487
-static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
488
+/*
489
+ * This function can count as GRAPH_RDLOCK because
490
+ * qcow2_co_pwritev_compressed_part() holds the graph lock and keeps it until
491
+ * this coroutine has terminated.
492
+ */
493
+static int coroutine_fn GRAPH_RDLOCK
494
+qcow2_co_pwritev_compressed_task_entry(AioTask *task)
495
{
496
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
497
498
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
499
* XXX: put compressed sectors first, then all the cluster aligned
500
* tables to avoid losing bytes in alignment
501
*/
502
-static coroutine_fn int
503
+static int coroutine_fn GRAPH_RDLOCK
504
qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
505
int64_t offset, int64_t bytes,
506
QEMUIOVector *qiov, size_t qiov_offset)
507
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
508
AioTaskPool *aio = NULL;
509
int ret = 0;
510
511
- assume_graph_lock(); /* FIXME */
512
-
513
if (has_data_file(bs)) {
514
return -ENOTSUP;
515
}
516
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
66
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
517
return pos;
67
return pos;
518
}
68
}
519
69
520
-static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
70
-static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
521
- QEMUIOVector *qiov, int64_t pos)
71
- QEMUIOVector *qiov, int64_t pos)
522
+static int coroutine_fn GRAPH_RDLOCK
72
+static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
523
+qcow2_co_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
73
+ QEMUIOVector *qiov, int64_t pos)
524
{
74
{
525
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
75
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
526
if (offset < 0) {
76
if (offset < 0) {
527
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
77
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
528
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
78
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
529
}
79
}
530
80
531
-static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs,
81
-static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs,
532
- QEMUIOVector *qiov, int64_t pos)
82
- QEMUIOVector *qiov, int64_t pos)
533
+static int coroutine_fn GRAPH_RDLOCK
83
+static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs,
534
+qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
84
+ QEMUIOVector *qiov, int64_t pos)
535
{
85
{
536
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
86
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
537
if (offset < 0) {
87
if (offset < 0) {
538
diff --git a/block/qed.c b/block/qed.c
88
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
539
index XXXXXXX..XXXXXXX 100644
89
.bdrv_co_get_info = qcow2_co_get_info,
540
--- a/block/qed.c
90
.bdrv_get_specific_info = qcow2_get_specific_info,
541
+++ b/block/qed.c
91
542
@@ -XXX,XX +XXX,XX @@ qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
92
- .bdrv_save_vmstate = qcow2_save_vmstate,
543
return qed_aio_next_io(&acb);
93
- .bdrv_load_vmstate = qcow2_load_vmstate,
544
}
94
+ .bdrv_co_save_vmstate = qcow2_co_save_vmstate,
545
95
+ .bdrv_co_load_vmstate = qcow2_co_load_vmstate,
546
-static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
96
547
- int64_t sector_num, int nb_sectors,
97
.is_format = true,
548
- QEMUIOVector *qiov)
98
.supports_backing = true,
549
+static int coroutine_fn GRAPH_RDLOCK
550
+bdrv_qed_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
551
+ QEMUIOVector *qiov)
552
{
553
- assume_graph_lock(); /* FIXME */
554
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
555
}
556
557
-static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
558
- int64_t sector_num, int nb_sectors,
559
- QEMUIOVector *qiov, int flags)
560
+static int coroutine_fn GRAPH_RDLOCK
561
+bdrv_qed_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
562
+ QEMUIOVector *qiov, int flags)
563
{
564
- assume_graph_lock(); /* FIXME */
565
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
566
}
567
568
diff --git a/block/quorum.c b/block/quorum.c
569
index XXXXXXX..XXXXXXX 100644
570
--- a/block/quorum.c
571
+++ b/block/quorum.c
572
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque)
573
}
574
}
575
576
-static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
577
- int64_t bytes, QEMUIOVector *qiov,
578
- BdrvRequestFlags flags)
579
+static int coroutine_fn GRAPH_RDLOCK
580
+quorum_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
581
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
582
{
583
BDRVQuorumState *s = bs->opaque;
584
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
585
int i, ret;
586
587
- assume_graph_lock(); /* FIXME */
588
-
589
for (i = 0; i < s->num_children; i++) {
590
Coroutine *co;
591
QuorumCo data = {
592
diff --git a/block/vmdk.c b/block/vmdk.c
593
index XXXXXXX..XXXXXXX 100644
594
--- a/block/vmdk.c
595
+++ b/block/vmdk.c
596
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
597
return ret;
598
}
599
600
-static int coroutine_fn
601
+static int coroutine_fn GRAPH_RDLOCK
602
vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
603
QEMUIOVector *qiov)
604
{
605
- assume_graph_lock(); /* FIXME */
606
-
607
if (bytes == 0) {
608
/* The caller will write bytes 0 to signal EOF.
609
* When receive it, we align EOF to a sector boundary. */
610
--
99
--
611
2.39.2
100
2.38.1
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
1
2
3
The inlined nbd_readXX() functions call beXX_to_cpu(), themselves
4
declared in <qemu/bswap.h>. This fixes when refactoring:
5
6
In file included from ../../block/nbd.c:44:
7
include/block/nbd.h: In function 'nbd_read16':
8
include/block/nbd.h:383:12: error: implicit declaration of function 'be16_to_cpu' [-Werror=implicit-function-declaration]
9
383 | *val = be##bits##_to_cpu(*val); \
10
| ^~
11
include/block/nbd.h:387:1: note: in expansion of macro 'DEF_NBD_READ_N'
12
387 | DEF_NBD_READ_N(16) /* Defines nbd_read16(). */
13
| ^~~~~~~~~~~~~~
14
15
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Message-Id: <20221125175328.48539-1-philmd@linaro.org>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
include/block/nbd.h | 1 +
22
1 file changed, 1 insertion(+)
23
24
diff --git a/include/block/nbd.h b/include/block/nbd.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/nbd.h
27
+++ b/include/block/nbd.h
28
@@ -XXX,XX +XXX,XX @@
29
#include "io/channel-socket.h"
30
#include "crypto/tlscreds.h"
31
#include "qapi/error.h"
32
+#include "qemu/bswap.h"
33
34
extern const BlockExportDriver blk_exp_nbd;
35
36
--
37
2.38.1
38
39
diff view generated by jsdifflib
1
It is never called outside of block.c.
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
When a block driver supports obtaining format-specific information, but
4
Message-Id: <20230203152202.49054-2-kwolf@redhat.com>
4
that object only contains optional fields, it is possible that none of
5
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
them are present, so that dump_qobject() (called by
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
6
bdrv_image_info_specific_dump()) will not print anything.
7
8
The callers of bdrv_image_info_specific_dump() put a header above this
9
information ("Format specific information:\n"), which will look strange
10
when there is nothing below. Modify bdrv_image_info_specific_dump() to
11
print this header instead of its callers, and only if there is indeed
12
something to be printed.
13
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
Message-Id: <20220620162704.80987-2-hreitz@redhat.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
18
---
9
include/block/block-io.h | 2 --
19
include/block/qapi.h | 3 ++-
10
block.c | 4 ++--
20
block/qapi.c | 41 +++++++++++++++++++++++++++++++++++++----
11
2 files changed, 2 insertions(+), 4 deletions(-)
21
qemu-io-cmds.c | 4 ++--
22
3 files changed, 41 insertions(+), 7 deletions(-)
12
23
13
diff --git a/include/block/block-io.h b/include/block/block-io.h
24
diff --git a/include/block/qapi.h b/include/block/qapi.h
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block-io.h
26
--- a/include/block/qapi.h
16
+++ b/include/block/block-io.h
27
+++ b/include/block/qapi.h
17
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
28
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
18
int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
29
Error **errp);
19
int64_t bytes);
30
20
31
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
21
-int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
32
-void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec);
22
- bool ignore_allow_rdw, Error **errp);
33
+void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
23
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
34
+ const char *prefix);
24
Error **errp);
35
void bdrv_image_info_dump(ImageInfo *info);
25
bool bdrv_is_read_only(BlockDriverState *bs);
36
#endif
26
diff --git a/block.c b/block.c
37
diff --git a/block/qapi.c b/block/qapi.c
27
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
28
--- a/block.c
39
--- a/block/qapi.c
29
+++ b/block.c
40
+++ b/block/qapi.c
30
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
41
@@ -XXX,XX +XXX,XX @@ static void dump_qdict(int indentation, QDict *dict)
31
return !(bs->open_flags & BDRV_O_RDWR);
42
}
32
}
43
}
33
44
34
-int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
45
-void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec)
35
- bool ignore_allow_rdw, Error **errp)
46
+/*
36
+static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
47
+ * Return whether dumping the given QObject with dump_qobject() would
37
+ bool ignore_allow_rdw, Error **errp)
48
+ * yield an empty dump, i.e. not print anything.
49
+ */
50
+static bool qobject_is_empty_dump(const QObject *obj)
51
+{
52
+ switch (qobject_type(obj)) {
53
+ case QTYPE_QNUM:
54
+ case QTYPE_QSTRING:
55
+ case QTYPE_QBOOL:
56
+ return false;
57
+
58
+ case QTYPE_QDICT:
59
+ return qdict_size(qobject_to(QDict, obj)) == 0;
60
+
61
+ case QTYPE_QLIST:
62
+ return qlist_empty(qobject_to(QList, obj));
63
+
64
+ default:
65
+ abort();
66
+ }
67
+}
68
+
69
+/**
70
+ * Dumps the given ImageInfoSpecific object in a human-readable form,
71
+ * prepending an optional prefix if the dump is not empty.
72
+ */
73
+void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
74
+ const char *prefix)
38
{
75
{
39
IO_CODE();
76
QObject *obj, *data;
77
Visitor *v = qobject_output_visitor_new(&obj);
78
@@ -XXX,XX +XXX,XX @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec)
79
visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
80
visit_complete(v, &obj);
81
data = qdict_get(qobject_to(QDict, obj), "data");
82
- dump_qobject(1, data);
83
+ if (!qobject_is_empty_dump(data)) {
84
+ if (prefix) {
85
+ qemu_printf("%s", prefix);
86
+ }
87
+ dump_qobject(1, data);
88
+ }
89
qobject_unref(obj);
90
visit_free(v);
91
}
92
@@ -XXX,XX +XXX,XX @@ void bdrv_image_info_dump(ImageInfo *info)
93
}
94
95
if (info->format_specific) {
96
- qemu_printf("Format specific information:\n");
97
- bdrv_image_info_specific_dump(info->format_specific);
98
+ bdrv_image_info_specific_dump(info->format_specific,
99
+ "Format specific information:\n");
100
}
101
}
102
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/qemu-io-cmds.c
105
+++ b/qemu-io-cmds.c
106
@@ -XXX,XX +XXX,XX @@ static int info_f(BlockBackend *blk, int argc, char **argv)
107
return -EIO;
108
}
109
if (spec_info) {
110
- printf("Format specific information:\n");
111
- bdrv_image_info_specific_dump(spec_info);
112
+ bdrv_image_info_specific_dump(spec_info,
113
+ "Format specific information:\n");
114
qapi_free_ImageInfoSpecific(spec_info);
115
}
40
116
41
--
117
--
42
2.39.2
118
2.38.1
diff view generated by jsdifflib
1
From: Or Ozeri <oro@il.ibm.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Ceph RBD encryption API required specifying the encryption format
3
Add some (optional) information that the file driver can provide for
4
for loading encryption. The supported formats were LUKS (v1) and LUKS2.
4
image files, namely the extent size hint.
5
5
6
Starting from Reef release, RBD also supports loading with "luks-any" format,
6
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
which works for both versions of LUKS.
7
Message-Id: <20220620162704.80987-3-hreitz@redhat.com>
8
9
This commit extends the qemu rbd driver API to enable qemu users to use
10
this luks-any wildcard format.
11
12
Signed-off-by: Or Ozeri <oro@il.ibm.com>
13
Message-Id: <20230129113120.722708-3-oro@oro.sl.cloud9.ibm.com>
14
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
10
---
18
qapi/block-core.json | 16 ++++++++++++++--
11
qapi/block-core.json | 26 ++++++++++++++++++++++++--
19
block/rbd.c | 19 +++++++++++++++++++
12
block/file-posix.c | 30 ++++++++++++++++++++++++++++++
20
2 files changed, 33 insertions(+), 2 deletions(-)
13
2 files changed, 54 insertions(+), 2 deletions(-)
21
14
22
diff --git a/qapi/block-core.json b/qapi/block-core.json
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/qapi/block-core.json
17
--- a/qapi/block-core.json
25
+++ b/qapi/block-core.json
18
+++ b/qapi/block-core.json
26
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
27
##
20
'*encryption-format': 'RbdImageEncryptionFormat'
28
# @RbdImageEncryptionFormat:
21
} }
29
#
22
30
+# @luks-any: Used for opening either luks or luks2 (Since 8.0)
23
+##
24
+# @ImageInfoSpecificFile:
31
+#
25
+#
32
# Since: 6.1
26
+# @extent-size-hint: Extent size hint (if available)
33
##
34
{ 'enum': 'RbdImageEncryptionFormat',
35
- 'data': [ 'luks', 'luks2' ] }
36
+ 'data': [ 'luks', 'luks2', 'luks-any' ] }
37
38
##
39
# @RbdEncryptionOptionsLUKSBase:
40
@@ -XXX,XX +XXX,XX @@
41
'base': 'RbdEncryptionOptionsLUKSBase',
42
'data': { } }
43
44
+##
45
+# @RbdEncryptionOptionsLUKSAny:
46
+#
27
+#
47
+# Since: 8.0
28
+# Since: 8.0
48
+##
29
+##
49
+{ 'struct': 'RbdEncryptionOptionsLUKSAny',
30
+{ 'struct': 'ImageInfoSpecificFile',
50
+ 'base': 'RbdEncryptionOptionsLUKSBase',
31
+ 'data': {
51
+ 'data': { } }
32
+ '*extent-size-hint': 'size'
33
+ } }
52
+
34
+
53
##
35
##
54
# @RbdEncryptionCreateOptionsLUKS:
36
# @ImageInfoSpecificKind:
37
#
38
# @luks: Since 2.7
39
# @rbd: Since 6.1
40
+# @file: Since 8.0
41
#
42
# Since: 1.7
43
##
44
{ 'enum': 'ImageInfoSpecificKind',
45
- 'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] }
46
+ 'data': [ 'qcow2', 'vmdk', 'luks', 'rbd', 'file' ] }
47
48
##
49
# @ImageInfoSpecificQCow2Wrapper:
50
@@ -XXX,XX +XXX,XX @@
51
{ 'struct': 'ImageInfoSpecificRbdWrapper',
52
'data': { 'data': 'ImageInfoSpecificRbd' } }
53
54
+##
55
+# @ImageInfoSpecificFileWrapper:
56
+#
57
+# Since: 8.0
58
+##
59
+{ 'struct': 'ImageInfoSpecificFileWrapper',
60
+ 'data': { 'data': 'ImageInfoSpecificFile' } }
61
+
62
##
63
# @ImageInfoSpecific:
55
#
64
#
56
@@ -XXX,XX +XXX,XX @@
65
@@ -XXX,XX +XXX,XX @@
57
'base': { 'format': 'RbdImageEncryptionFormat' },
66
'qcow2': 'ImageInfoSpecificQCow2Wrapper',
58
'discriminator': 'format',
67
'vmdk': 'ImageInfoSpecificVmdkWrapper',
59
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
68
'luks': 'ImageInfoSpecificLUKSWrapper',
60
- 'luks2': 'RbdEncryptionOptionsLUKS2' } }
69
- 'rbd': 'ImageInfoSpecificRbdWrapper'
61
+ 'luks2': 'RbdEncryptionOptionsLUKS2',
70
+ 'rbd': 'ImageInfoSpecificRbdWrapper',
62
+ 'luks-any': 'RbdEncryptionOptionsLUKSAny'} }
71
+ 'file': 'ImageInfoSpecificFileWrapper'
72
} }
63
73
64
##
74
##
65
# @RbdEncryptionCreateOptions:
75
diff --git a/block/file-posix.c b/block/file-posix.c
66
diff --git a/block/rbd.c b/block/rbd.c
67
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
68
--- a/block/rbd.c
77
--- a/block/file-posix.c
69
+++ b/block/rbd.c
78
+++ b/block/file-posix.c
70
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
79
@@ -XXX,XX +XXX,XX @@ raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
71
g_autofree char *passphrase = NULL;
80
return 0;
72
rbd_encryption_luks1_format_options_t luks_opts;
81
}
73
rbd_encryption_luks2_format_options_t luks2_opts;
82
74
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
83
+static ImageInfoSpecific *raw_get_specific_info(BlockDriverState *bs,
75
+ rbd_encryption_luks_format_options_t luks_any_opts;
84
+ Error **errp)
85
+{
86
+ BDRVRawState *s = bs->opaque;
87
+ ImageInfoSpecificFile *file_info = g_new0(ImageInfoSpecificFile, 1);
88
+ ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
89
+
90
+ *spec_info = (ImageInfoSpecific){
91
+ .type = IMAGE_INFO_SPECIFIC_KIND_FILE,
92
+ .u.file.data = file_info,
93
+ };
94
+
95
+#ifdef FS_IOC_FSGETXATTR
96
+ {
97
+ struct fsxattr attr;
98
+ int ret;
99
+
100
+ ret = ioctl(s->fd, FS_IOC_FSGETXATTR, &attr);
101
+ if (!ret && attr.fsx_extsize != 0) {
102
+ file_info->has_extent_size_hint = true;
103
+ file_info->extent_size_hint = attr.fsx_extsize;
104
+ }
105
+ }
76
+#endif
106
+#endif
77
rbd_encryption_format_t format;
107
+
78
rbd_encryption_options_t opts;
108
+ return spec_info;
79
size_t opts_size;
109
+}
80
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
110
+
81
luks2_opts.passphrase = passphrase;
111
static BlockStatsSpecificFile get_blockstats_specific_file(BlockDriverState *bs)
82
break;
112
{
83
}
113
BDRVRawState *s = bs->opaque;
84
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
114
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
85
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
115
.bdrv_co_truncate = raw_co_truncate,
86
+ memset(&luks_any_opts, 0, sizeof(luks_any_opts));
116
.bdrv_co_getlength = raw_co_getlength,
87
+ format = RBD_ENCRYPTION_FORMAT_LUKS;
117
.bdrv_co_get_info = raw_co_get_info,
88
+ opts = &luks_any_opts;
118
+ .bdrv_get_specific_info = raw_get_specific_info,
89
+ opts_size = sizeof(luks_any_opts);
119
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
90
+ r = qemu_rbd_convert_luks_options(
120
.bdrv_get_specific_stats = raw_get_specific_stats,
91
+ qapi_RbdEncryptionOptionsLUKSAny_base(&encrypt->u.luks_any),
121
.bdrv_check_perm = raw_check_perm,
92
+ &passphrase, &luks_any_opts.passphrase_size, errp);
122
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
93
+ if (r < 0) {
123
.bdrv_co_truncate = raw_co_truncate,
94
+ return r;
124
.bdrv_co_getlength = raw_co_getlength,
95
+ }
125
.bdrv_co_get_info = raw_co_get_info,
96
+ luks_any_opts.passphrase = passphrase;
126
+ .bdrv_get_specific_info = raw_get_specific_info,
97
+ break;
127
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
98
+ }
128
.bdrv_get_specific_stats = hdev_get_specific_stats,
99
+#endif
129
.bdrv_check_perm = raw_check_perm,
100
default: {
101
r = -ENOTSUP;
102
error_setg_errno(
103
--
130
--
104
2.39.2
131
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Hanna Reitz <hreitz@redhat.com>
2
bdrv_co_truncate() need to hold a reader lock for the graph.
3
2
4
For some places, we know that they will hold the lock, but we don't have
3
VMDK's implementation of .bdrv_get_specific_info() returns information
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
4
about its extent files, ostensibly in the form of ImageInfo objects.
6
with a FIXME comment. These places will be removed once everything is
5
However, it does not get this information through
7
properly annotated.
6
bdrv_query_image_info(), but fills only a select few fields with custom
7
information that does not always match the fields' purposes.
8
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
For example, @format, which is supposed to be a block driver name, is
10
Message-Id: <20230203152202.49054-4-kwolf@redhat.com>
10
filled with the extent type, e.g. SPARSE or FLAT.
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
12
In ImageInfo, @compressed shows whether the data that can be seen in the
13
image is stored in compressed form or not. For example, a compressed
14
qcow2 image will store compressed data in its data file, but when
15
accessing the qcow2 node, you will see normal data. This is not how
16
VMDK uses the @compressed field for its extent files: Instead, it
17
signifies whether accessing the extent file will yield compressed data
18
(which the VMDK driver then (de-)compresses).
19
20
Create a new structure to represent the extent information. This allows
21
us to clarify the fields' meanings, and it clearly shows that these are
22
not complete ImageInfo objects. (That is, if a user wants an extent
23
file's ImageInfo object, they will need to query it separately, and will
24
not get it from ImageInfoSpecificVmdk.extents.)
25
26
Note that this removes the last use of ['ImageInfo'] (i.e. an array of
27
ImageInfo objects), so the QAPI generator will no longer generate
28
ImageInfoList by default. However, we use it in qemu-img.c, so we need
29
to create a dummy object to force the generate to create that type,
30
similarly to DummyForceArrays in machine.json (introduced in commit
31
9f08c8ec73878122ad4b061ed334f0437afaaa32 ("qapi: Lazy creation of array
32
types")).
33
34
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
35
Message-Id: <20220620162704.80987-4-hreitz@redhat.com>
36
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
37
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
38
---
14
include/block/block-io.h | 6 +++---
39
qapi/block-core.json | 38 +++++++++++++++++++++++++++++++++++++-
15
include/block/block_int-common.h | 7 ++++---
40
block/vmdk.c | 8 ++++----
16
block/block-backend.c | 1 +
41
2 files changed, 41 insertions(+), 5 deletions(-)
17
block/crypto.c | 2 +-
18
block/io.c | 1 +
19
block/parallels.c | 14 ++++++++------
20
block/preallocate.c | 2 +-
21
block/qcow.c | 17 ++++++++++++-----
22
block/qcow2.c | 14 ++++++++------
23
block/raw-format.c | 6 +++---
24
block/vmdk.c | 2 ++
25
11 files changed, 44 insertions(+), 28 deletions(-)
26
42
27
diff --git a/include/block/block-io.h b/include/block/block-io.h
43
diff --git a/qapi/block-core.json b/qapi/block-core.json
28
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block-io.h
45
--- a/qapi/block-core.json
30
+++ b/include/block/block-io.h
46
+++ b/qapi/block-core.json
31
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
47
@@ -XXX,XX +XXX,XX @@
32
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
48
'create-type': 'str',
33
int64_t bytes, BdrvRequestFlags flags);
49
'cid': 'int',
34
50
'parent-cid': 'int',
35
-int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
51
- 'extents': ['ImageInfo']
36
- PreallocMode prealloc, BdrvRequestFlags flags,
52
+ 'extents': ['VmdkExtentInfo']
37
- Error **errp);
53
+ } }
38
+int coroutine_fn GRAPH_RDLOCK
39
+bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
43
int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
* If @exact is true and this function fails but would succeed
50
* with @exact = false, it should return -ENOTSUP.
51
*/
52
- int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
53
- bool exact, PreallocMode prealloc,
54
- BdrvRequestFlags flags, Error **errp);
55
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_truncate)(
56
+ BlockDriverState *bs, int64_t offset, bool exact,
57
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
58
+
54
+
59
int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
55
+##
60
int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
56
+# @VmdkExtentInfo:
61
BlockDriverState *bs);
57
+#
62
diff --git a/block/block-backend.c b/block/block-backend.c
58
+# Information about a VMDK extent file
63
index XXXXXXX..XXXXXXX 100644
59
+#
64
--- a/block/block-backend.c
60
+# @filename: Name of the extent file
65
+++ b/block/block-backend.c
61
+#
66
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
62
+# @format: Extent type (e.g. FLAT or SPARSE)
67
Error **errp)
63
+#
68
{
64
+# @virtual-size: Number of bytes covered by this extent
69
IO_OR_GS_CODE();
65
+#
70
+ GRAPH_RDLOCK_GUARD();
66
+# @cluster-size: Cluster size in bytes (for non-flat extents)
71
if (!blk_is_available(blk)) {
67
+#
72
error_setg(errp, "No medium inserted");
68
+# @compressed: Whether this extent contains compressed data
73
return -ENOMEDIUM;
69
+#
74
diff --git a/block/crypto.c b/block/crypto.c
70
+# Since: 8.0
75
index XXXXXXX..XXXXXXX 100644
71
+##
76
--- a/block/crypto.c
72
+{ 'struct': 'VmdkExtentInfo',
77
+++ b/block/crypto.c
73
+ 'data': {
78
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
74
+ 'filename': 'str',
79
return ret;
75
+ 'format': 'str',
80
}
76
+ 'virtual-size': 'int',
81
77
+ '*cluster-size': 'int',
82
-static int coroutine_fn
78
+ '*compressed': 'bool'
83
+static int coroutine_fn GRAPH_RDLOCK
79
} }
84
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
80
85
PreallocMode prealloc, BdrvRequestFlags flags,
81
##
86
Error **errp)
82
@@ -XXX,XX +XXX,XX @@
87
diff --git a/block/io.c b/block/io.c
83
'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
88
index XXXXXXX..XXXXXXX 100644
84
'returns': 'SnapshotInfo',
89
--- a/block/io.c
85
'allow-preconfig': true }
90
+++ b/block/io.c
91
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
92
int64_t old_size, new_bytes;
93
int ret;
94
IO_CODE();
95
+ assert_bdrv_graph_readable();
96
97
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
98
if (!drv) {
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
104
return start_off;
105
}
106
107
-static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
108
- int64_t sector_num,
109
- int nb_sectors, int *pnum)
110
+static int64_t coroutine_fn GRAPH_RDLOCK
111
+allocate_clusters(BlockDriverState *bs, int64_t sector_num,
112
+ int nb_sectors, int *pnum)
113
{
114
int ret = 0;
115
BDRVParallelsState *s = bs->opaque;
116
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
117
QEMUIOVector hd_qiov;
118
int ret = 0;
119
120
+ assume_graph_lock(); /* FIXME */
121
+
86
+
122
qemu_iovec_init(&hd_qiov, qiov->niov);
87
+##
123
88
+# @DummyBlockCoreForceArrays:
124
while (nb_sectors > 0) {
89
+#
125
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
90
+# Not used by QMP; hack to let us use ImageInfoList internally
126
}
91
+#
127
92
+# Since: 8.0
128
93
+##
129
-static int coroutine_fn parallels_co_check(BlockDriverState *bs,
94
+{ 'struct': 'DummyBlockCoreForceArrays',
130
- BdrvCheckResult *res,
95
+ 'data': { 'unused-image-info': ['ImageInfo'] } }
131
- BdrvCheckMode fix)
132
+static int coroutine_fn GRAPH_RDLOCK
133
+parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
134
+ BdrvCheckMode fix)
135
{
136
BDRVParallelsState *s = bs->opaque;
137
int64_t size, prev_off, high_off;
138
diff --git a/block/preallocate.c b/block/preallocate.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/preallocate.c
141
+++ b/block/preallocate.c
142
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
143
flags);
144
}
145
146
-static int coroutine_fn
147
+static int coroutine_fn GRAPH_RDLOCK
148
preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
149
bool exact, PreallocMode prealloc,
150
BdrvRequestFlags flags, Error **errp)
151
diff --git a/block/qcow.c b/block/qcow.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/qcow.c
154
+++ b/block/qcow.c
155
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
156
* return 0 if not allocated, 1 if *result is assigned, and negative
157
* errno on failure.
158
*/
159
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
160
- uint64_t offset, int allocate,
161
- int compressed_size,
162
- int n_start, int n_end,
163
- uint64_t *result)
164
+static int coroutine_fn GRAPH_RDLOCK
165
+get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
166
+ int compressed_size, int n_start, int n_end,
167
+ uint64_t *result)
168
{
169
BDRVQcowState *s = bs->opaque;
170
int min_index, i, j, l1_index, l2_index, ret;
171
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
172
int64_t n;
173
uint64_t cluster_offset;
174
175
+ assume_graph_lock(); /* FIXME */
176
+
177
qemu_co_mutex_lock(&s->lock);
178
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
179
qemu_co_mutex_unlock(&s->lock);
180
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
181
uint8_t *buf;
182
void *orig_buf;
183
184
+ assume_graph_lock(); /* FIXME */
185
+
186
if (qiov->niov > 1) {
187
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
188
if (buf == NULL) {
189
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
190
uint8_t *buf;
191
void *orig_buf;
192
193
+ assume_graph_lock(); /* FIXME */
194
+
195
s->cluster_cache_offset = -1; /* disable compressed cache */
196
197
/* We must always copy the iov when encrypting, so we
198
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
199
uint8_t *buf, *out_buf;
200
uint64_t cluster_offset;
201
202
+ assume_graph_lock(); /* FIXME */
203
+
204
buf = qemu_blockalign(bs, s->cluster_size);
205
if (bytes != s->cluster_size) {
206
if (bytes > s->cluster_size ||
207
diff --git a/block/qcow2.c b/block/qcow2.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/block/qcow2.c
210
+++ b/block/qcow2.c
211
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
212
*
213
* Returns: 0 on success, -errno on failure.
214
*/
215
-static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
216
- uint64_t new_length, PreallocMode mode,
217
- Error **errp)
218
+static int coroutine_fn GRAPH_RDLOCK
219
+preallocate_co(BlockDriverState *bs, uint64_t offset, uint64_t new_length,
220
+ PreallocMode mode, Error **errp)
221
{
222
BDRVQcow2State *s = bs->opaque;
223
uint64_t bytes;
224
@@ -XXX,XX +XXX,XX @@ fail:
225
return ret;
226
}
227
228
-static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
229
- bool exact, PreallocMode prealloc,
230
- BdrvRequestFlags flags, Error **errp)
231
+static int coroutine_fn GRAPH_RDLOCK
232
+qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
233
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
234
{
235
BDRVQcow2State *s = bs->opaque;
236
uint64_t old_length;
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
AioTaskPool *aio = NULL;
239
int ret = 0;
240
241
+ assume_graph_lock(); /* FIXME */
242
+
243
if (has_data_file(bs)) {
244
return -ENOTSUP;
245
}
246
diff --git a/block/raw-format.c b/block/raw-format.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/block/raw-format.c
249
+++ b/block/raw-format.c
250
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
251
}
252
}
253
254
-static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
255
- bool exact, PreallocMode prealloc,
256
- BdrvRequestFlags flags, Error **errp)
257
+static int coroutine_fn GRAPH_RDLOCK
258
+raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
259
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
260
{
261
BDRVRawState *s = bs->opaque;
262
263
diff --git a/block/vmdk.c b/block/vmdk.c
96
diff --git a/block/vmdk.c b/block/vmdk.c
264
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
265
--- a/block/vmdk.c
98
--- a/block/vmdk.c
266
+++ b/block/vmdk.c
99
+++ b/block/vmdk.c
267
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
100
@@ -XXX,XX +XXX,XX @@ static int vmdk_has_zero_init(BlockDriverState *bs)
268
vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
101
return 1;
269
QEMUIOVector *qiov)
102
}
103
104
-static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
105
+static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
270
{
106
{
271
+ assume_graph_lock(); /* FIXME */
107
- ImageInfo *info = g_new0(ImageInfo, 1);
272
+
108
+ VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1);
273
if (bytes == 0) {
109
274
/* The caller will write bytes 0 to signal EOF.
110
bdrv_refresh_filename(extent->file->bs);
275
* When receive it, we align EOF to a sector boundary. */
111
- *info = (ImageInfo){
112
+ *info = (VmdkExtentInfo){
113
.filename = g_strdup(extent->file->bs->filename),
114
.format = g_strdup(extent->type),
115
.virtual_size = extent->sectors * BDRV_SECTOR_SIZE,
116
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
117
int i;
118
BDRVVmdkState *s = bs->opaque;
119
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
120
- ImageInfoList **tail;
121
+ VmdkExtentInfoList **tail;
122
123
*spec_info = (ImageInfoSpecific){
124
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
276
--
125
--
277
2.39.2
126
2.38.1
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
When an IOThread is configured, the ctrl virtqueue is processed in the
3
ImageInfo sometimes contains flat information, and sometimes it does
4
IOThread. TMFs that reset SCSI devices are currently called directly
4
not. Split off a BlockNodeInfo struct, which only contains information
5
from the IOThread and trigger an assertion failure in blk_drain() from
5
about a single node and has no link to the backing image.
6
the following call stack:
6
7
7
We do this so we can extend BlockNodeInfo to a BlockGraphInfo struct,
8
virtio_scsi_handle_ctrl_req -> virtio_scsi_do_tmf -> device_code_reset
8
which has links to all child nodes, not just the backing node. It would
9
-> scsi_disk_reset -> scsi_device_purge_requests -> blk_drain
9
be strange to base BlockGraphInfo on ImageInfo, because then this
10
10
extended struct would have two links to the backing node (one in
11
../block/block-backend.c:1780: void blk_drain(BlockBackend *): Assertion `qemu_in_main_thread()' failed.
11
BlockGraphInfo as one of all the child links, and one in ImageInfo).
12
12
13
The blk_drain() function is not designed to be called from an IOThread
13
Furthermore, it is quite common to ignore the backing-image field
14
because it needs the Big QEMU Lock (BQL).
14
altogether: bdrv_query_image_info() does not set it, and
15
15
bdrv_image_info_dump() does not evaluate it. That signals that we
16
This patch defers TMFs that reset SCSI devices to a Bottom Half (BH)
16
should have different structs for describing a single node and one that
17
that runs in the main loop thread under the BQL. This way it's safe to
17
has a link to the backing image.
18
call blk_drain() and the assertion failure is avoided.
18
19
19
Still, bdrv_query_image_info() and bdrv_image_info_dump() are not
20
Introduce s->tmf_bh_list for tracking TMF requests that have been
20
changed too much in this patch. Follow-up patches will handle them.
21
deferred to the BH. When the BH runs it will grab the entire list and
21
22
process all requests. Care must be taken to clear the list when the
22
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
23
virtio-scsi device is reset or unrealized. Otherwise deferred TMF
23
Message-Id: <20220620162704.80987-5-hreitz@redhat.com>
24
requests could execute later and lead to use-after-free or other
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
undefined behavior.
26
27
The s->resetting counter that's used by TMFs that reset SCSI devices is
28
accessed from multiple threads. This patch makes that explicit by using
29
atomic accessor functions. With this patch applied the counter is only
30
modified by the main loop thread under the BQL but can be read by any
31
thread.
32
33
Reported-by: Qing Wang <qinwang@redhat.com>
34
Cc: Paolo Bonzini <pbonzini@redhat.com>
35
Reviewed-by: Eric Blake <eblake@redhat.com>
36
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
37
Message-Id: <20230221212218.1378734-4-stefanha@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
---
26
---
40
include/hw/virtio/virtio-scsi.h | 11 ++-
27
qapi/block-core.json | 24 +++++++++----
41
hw/scsi/virtio-scsi.c | 169 +++++++++++++++++++++++++-------
28
include/block/qapi.h | 3 ++
42
2 files changed, 143 insertions(+), 37 deletions(-)
29
block/qapi.c | 86 ++++++++++++++++++++++++++++++++------------
43
30
3 files changed, 85 insertions(+), 28 deletions(-)
44
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
31
32
diff --git a/qapi/block-core.json b/qapi/block-core.json
45
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/virtio/virtio-scsi.h
34
--- a/qapi/block-core.json
47
+++ b/include/hw/virtio/virtio-scsi.h
35
+++ b/qapi/block-core.json
48
@@ -XXX,XX +XXX,XX @@ struct VirtIOSCSICommon {
36
@@ -XXX,XX +XXX,XX @@
49
VirtQueue **cmd_vqs;
37
} }
50
};
38
51
39
##
52
+struct VirtIOSCSIReq;
40
-# @ImageInfo:
53
+
41
+# @BlockNodeInfo:
54
struct VirtIOSCSI {
42
#
55
VirtIOSCSICommon parent_obj;
43
# Information about a QEMU image file
56
44
#
57
SCSIBus bus;
45
@@ -XXX,XX +XXX,XX @@
58
- int resetting;
46
#
59
+ int resetting; /* written from main loop thread, read from any thread */
47
# @snapshots: list of VM snapshots
60
bool events_dropped;
48
#
61
49
-# @backing-image: info of the backing image (since 1.6)
62
+ /*
50
-#
63
+ * TMFs deferred to main loop BH. These fields are protected by
51
# @format-specific: structure supplying additional format-specific
64
+ * virtio_scsi_acquire().
52
# information (since 1.7)
65
+ */
53
#
66
+ QEMUBH *tmf_bh;
54
-# Since: 1.3
67
+ QTAILQ_HEAD(, VirtIOSCSIReq) tmf_bh_list;
55
+# Since: 8.0
68
+
56
##
69
/* Fields for dataplane below */
57
-{ 'struct': 'ImageInfo',
70
AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
58
+{ 'struct': 'BlockNodeInfo',
71
59
'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
72
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
60
'*actual-size': 'int', 'virtual-size': 'int',
61
'*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
62
'*backing-filename': 'str', '*full-backing-filename': 'str',
63
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
64
- '*backing-image': 'ImageInfo',
65
'*format-specific': 'ImageInfoSpecific' } }
66
67
+##
68
+# @ImageInfo:
69
+#
70
+# Information about a QEMU image file, and potentially its backing image
71
+#
72
+# @backing-image: info of the backing image
73
+#
74
+# Since: 1.3
75
+##
76
+{ 'struct': 'ImageInfo',
77
+ 'base': 'BlockNodeInfo',
78
+ 'data': {
79
+ '*backing-image': 'ImageInfo'
80
+ } }
81
+
82
##
83
# @ImageCheck:
84
#
85
diff --git a/include/block/qapi.h b/include/block/qapi.h
73
index XXXXXXX..XXXXXXX 100644
86
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/scsi/virtio-scsi.c
87
--- a/include/block/qapi.h
75
+++ b/hw/scsi/virtio-scsi.c
88
+++ b/include/block/qapi.h
76
@@ -XXX,XX +XXX,XX @@ typedef struct VirtIOSCSIReq {
89
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
77
QEMUSGList qsgl;
90
int bdrv_query_snapshot_info_list(BlockDriverState *bs,
78
QEMUIOVector resp_iov;
91
SnapshotInfoList **p_list,
79
92
Error **errp);
80
- union {
93
+void bdrv_query_block_node_info(BlockDriverState *bs,
81
- /* Used for two-stage request submission */
94
+ BlockNodeInfo **p_info,
82
- QTAILQ_ENTRY(VirtIOSCSIReq) next;
95
+ Error **errp);
83
+ /* Used for two-stage request submission and TMFs deferred to BH */
96
void bdrv_query_image_info(BlockDriverState *bs,
84
+ QTAILQ_ENTRY(VirtIOSCSIReq) next;
97
ImageInfo **p_info,
85
98
Error **errp);
86
- /* Used for cancellation of request during TMFs */
99
diff --git a/block/qapi.c b/block/qapi.c
87
- int remaining;
100
index XXXXXXX..XXXXXXX 100644
88
- };
101
--- a/block/qapi.c
89
+ /* Used for cancellation of request during TMFs */
102
+++ b/block/qapi.c
90
+ int remaining;
103
@@ -XXX,XX +XXX,XX @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
91
104
}
92
SCSIRequest *sreq;
105
93
size_t resp_size;
106
/**
94
@@ -XXX,XX +XXX,XX @@ static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
107
- * bdrv_query_image_info:
108
- * @bs: block device to examine
109
- * @p_info: location to store image information
110
- * @errp: location to store error information
111
- *
112
- * Store "flat" image information in @p_info.
113
- *
114
- * "Flat" means it does *not* query backing image information,
115
- * i.e. (*pinfo)->has_backing_image will be set to false and
116
- * (*pinfo)->backing_image to NULL even when the image does in fact have
117
- * a backing image.
118
- *
119
- * @p_info will be set only on success. On error, store error in @errp.
120
+ * Helper function for other query info functions. Store information about @bs
121
+ * in @info, setting @errp on error.
122
*/
123
-void bdrv_query_image_info(BlockDriverState *bs,
124
- ImageInfo **p_info,
125
- Error **errp)
126
+static void bdrv_do_query_node_info(BlockDriverState *bs,
127
+ BlockNodeInfo *info,
128
+ Error **errp)
129
{
130
int64_t size;
131
const char *backing_filename;
132
BlockDriverInfo bdi;
133
int ret;
134
Error *err = NULL;
135
- ImageInfo *info;
136
137
aio_context_acquire(bdrv_get_aio_context(bs));
138
139
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
140
141
bdrv_refresh_filename(bs);
142
143
- info = g_new0(ImageInfo, 1);
144
info->filename = g_strdup(bs->filename);
145
info->format = g_strdup(bdrv_get_format_name(bs));
146
info->virtual_size = size;
147
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
148
info->format_specific = bdrv_get_specific_info(bs, &err);
149
if (err) {
150
error_propagate(errp, err);
151
- qapi_free_ImageInfo(info);
152
goto out;
95
}
153
}
154
backing_filename = bs->backing_file;
155
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
156
break;
157
default:
158
error_propagate(errp, err);
159
- qapi_free_ImageInfo(info);
160
goto out;
161
}
162
163
- *p_info = info;
164
-
165
out:
166
aio_context_release(bdrv_get_aio_context(bs));
96
}
167
}
97
168
98
+static void virtio_scsi_do_one_tmf_bh(VirtIOSCSIReq *req)
169
+/**
170
+ * bdrv_query_block_node_info:
171
+ * @bs: block node to examine
172
+ * @p_info: location to store node information
173
+ * @errp: location to store error information
174
+ *
175
+ * Store image information about @bs in @p_info.
176
+ *
177
+ * @p_info will be set only on success. On error, store error in @errp.
178
+ */
179
+void bdrv_query_block_node_info(BlockDriverState *bs,
180
+ BlockNodeInfo **p_info,
181
+ Error **errp)
99
+{
182
+{
100
+ VirtIOSCSI *s = req->dev;
183
+ BlockNodeInfo *info;
101
+ SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
184
+ ERRP_GUARD();
102
+ BusChild *kid;
185
+
103
+ int target;
186
+ info = g_new0(BlockNodeInfo, 1);
104
+
187
+ bdrv_do_query_node_info(bs, info, errp);
105
+ switch (req->req.tmf.subtype) {
188
+ if (*errp) {
106
+ case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
189
+ qapi_free_BlockNodeInfo(info);
107
+ if (!d) {
190
+ return;
108
+ req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
109
+ goto out;
110
+ }
111
+ if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
112
+ req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
113
+ goto out;
114
+ }
115
+ qatomic_inc(&s->resetting);
116
+ device_cold_reset(&d->qdev);
117
+ qatomic_dec(&s->resetting);
118
+ break;
119
+
120
+ case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
121
+ target = req->req.tmf.lun[1];
122
+ qatomic_inc(&s->resetting);
123
+
124
+ rcu_read_lock();
125
+ QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
126
+ SCSIDevice *d1 = SCSI_DEVICE(kid->child);
127
+ if (d1->channel == 0 && d1->id == target) {
128
+ device_cold_reset(&d1->qdev);
129
+ }
130
+ }
131
+ rcu_read_unlock();
132
+
133
+ qatomic_dec(&s->resetting);
134
+ break;
135
+
136
+ default:
137
+ g_assert_not_reached();
138
+ break;
139
+ }
191
+ }
140
+
192
+
141
+out:
193
+ *p_info = info;
142
+ object_unref(OBJECT(d));
143
+
144
+ virtio_scsi_acquire(s);
145
+ virtio_scsi_complete_req(req);
146
+ virtio_scsi_release(s);
147
+}
194
+}
148
+
195
+
149
+/* Some TMFs must be processed from the main loop thread */
196
+/**
150
+static void virtio_scsi_do_tmf_bh(void *opaque)
197
+ * bdrv_query_image_info:
198
+ * @bs: block node to examine
199
+ * @p_info: location to store image information
200
+ * @errp: location to store error information
201
+ *
202
+ * Store "flat" image information in @p_info.
203
+ *
204
+ * "Flat" means it does *not* query backing image information,
205
+ * i.e. (*pinfo)->has_backing_image will be set to false and
206
+ * (*pinfo)->backing_image to NULL even when the image does in fact have
207
+ * a backing image.
208
+ *
209
+ * @p_info will be set only on success. On error, store error in @errp.
210
+ */
211
+void bdrv_query_image_info(BlockDriverState *bs,
212
+ ImageInfo **p_info,
213
+ Error **errp)
151
+{
214
+{
152
+ VirtIOSCSI *s = opaque;
215
+ ImageInfo *info;
153
+ QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
216
+ ERRP_GUARD();
154
+ VirtIOSCSIReq *req;
217
+
155
+ VirtIOSCSIReq *tmp;
218
+ info = g_new0(ImageInfo, 1);
156
+
219
+ bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
157
+ GLOBAL_STATE_CODE();
220
+ if (*errp) {
158
+
221
+ qapi_free_ImageInfo(info);
159
+ virtio_scsi_acquire(s);
222
+ return;
160
+
161
+ QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) {
162
+ QTAILQ_REMOVE(&s->tmf_bh_list, req, next);
163
+ QTAILQ_INSERT_TAIL(&reqs, req, next);
164
+ }
223
+ }
165
+
224
+
166
+ qemu_bh_delete(s->tmf_bh);
225
+ *p_info = info;
167
+ s->tmf_bh = NULL;
168
+
169
+ virtio_scsi_release(s);
170
+
171
+ QTAILQ_FOREACH_SAFE(req, &reqs, next, tmp) {
172
+ QTAILQ_REMOVE(&reqs, req, next);
173
+ virtio_scsi_do_one_tmf_bh(req);
174
+ }
175
+}
226
+}
176
+
227
+
177
+static void virtio_scsi_reset_tmf_bh(VirtIOSCSI *s)
228
/* @p_info will be set only on success. */
178
+{
229
static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
179
+ VirtIOSCSIReq *req;
230
Error **errp)
180
+ VirtIOSCSIReq *tmp;
181
+
182
+ GLOBAL_STATE_CODE();
183
+
184
+ virtio_scsi_acquire(s);
185
+
186
+ if (s->tmf_bh) {
187
+ qemu_bh_delete(s->tmf_bh);
188
+ s->tmf_bh = NULL;
189
+ }
190
+
191
+ QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) {
192
+ QTAILQ_REMOVE(&s->tmf_bh_list, req, next);
193
+
194
+ /* SAM-6 6.3.2 Hard reset */
195
+ req->resp.tmf.response = VIRTIO_SCSI_S_TARGET_FAILURE;
196
+ virtio_scsi_complete_req(req);
197
+ }
198
+
199
+ virtio_scsi_release(s);
200
+}
201
+
202
+static void virtio_scsi_defer_tmf_to_bh(VirtIOSCSIReq *req)
203
+{
204
+ VirtIOSCSI *s = req->dev;
205
+
206
+ QTAILQ_INSERT_TAIL(&s->tmf_bh_list, req, next);
207
+
208
+ if (!s->tmf_bh) {
209
+ s->tmf_bh = qemu_bh_new(virtio_scsi_do_tmf_bh, s);
210
+ qemu_bh_schedule(s->tmf_bh);
211
+ }
212
+}
213
+
214
/* Return 0 if the request is ready to be completed and return to guest;
215
* -EINPROGRESS if the request is submitted and will be completed later, in the
216
* case of async cancellation. */
217
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
218
{
219
SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
220
SCSIRequest *r, *next;
221
- BusChild *kid;
222
- int target;
223
int ret = 0;
224
225
virtio_scsi_ctx_check(s, d);
226
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
227
break;
228
229
case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
230
- if (!d) {
231
- goto fail;
232
- }
233
- if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
234
- goto incorrect_lun;
235
- }
236
- s->resetting++;
237
- device_cold_reset(&d->qdev);
238
- s->resetting--;
239
+ case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
240
+ virtio_scsi_defer_tmf_to_bh(req);
241
+ ret = -EINPROGRESS;
242
break;
243
244
case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
245
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
246
}
247
break;
248
249
- case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
250
- target = req->req.tmf.lun[1];
251
- s->resetting++;
252
-
253
- rcu_read_lock();
254
- QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
255
- SCSIDevice *d1 = SCSI_DEVICE(kid->child);
256
- if (d1->channel == 0 && d1->id == target) {
257
- device_cold_reset(&d1->qdev);
258
- }
259
- }
260
- rcu_read_unlock();
261
-
262
- s->resetting--;
263
- break;
264
-
265
case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
266
default:
267
req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
268
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_request_cancelled(SCSIRequest *r)
269
if (!req) {
270
return;
271
}
272
- if (req->dev->resetting) {
273
+ if (qatomic_read(&req->dev->resetting)) {
274
req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
275
} else {
276
req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
277
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_reset(VirtIODevice *vdev)
278
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
279
280
assert(!s->dataplane_started);
281
- s->resetting++;
282
+
283
+ virtio_scsi_reset_tmf_bh(s);
284
+
285
+ qatomic_inc(&s->resetting);
286
bus_cold_reset(BUS(&s->bus));
287
- s->resetting--;
288
+ qatomic_dec(&s->resetting);
289
290
vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
291
vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
292
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
293
VirtIOSCSI *s = VIRTIO_SCSI(dev);
294
Error *err = NULL;
295
296
+ QTAILQ_INIT(&s->tmf_bh_list);
297
+
298
virtio_scsi_common_realize(dev,
299
virtio_scsi_handle_ctrl,
300
virtio_scsi_handle_event,
301
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_unrealize(DeviceState *dev)
302
{
303
VirtIOSCSI *s = VIRTIO_SCSI(dev);
304
305
+ virtio_scsi_reset_tmf_bh(s);
306
+
307
qbus_set_hotplug_handler(BUS(&s->bus), NULL);
308
virtio_scsi_common_unrealize(dev);
309
}
310
--
231
--
311
2.39.2
232
2.38.1
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
Message-Id: <20230203152202.49054-16-kwolf@redhat.com>
2
3
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
3
qemu-img info never uses ImageInfo's backing-image field, because it
4
opens the backing chain one by one with BDRV_O_NO_BACKING, and prints
5
all backing chain nodes' information consecutively. Use BlockNodeInfo
6
to make it clear that we only print information about a single node, and
7
that we are not using the backing-image field.
8
9
Notably, bdrv_image_info_dump() does not evaluate the backing-image
10
field, so we can easily make it take a BlockNodeInfo pointer (and
11
consequentially rename it to bdrv_node_info_dump()). It makes more
12
sense this way, because again, the interface now makes it syntactically
13
clear that backing-image is ignored by this function.
14
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
Message-Id: <20220620162704.80987-6-hreitz@redhat.com>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
19
---
6
include/block/block_int-common.h | 12 +++++++-----
20
qapi/block-core.json | 4 +--
7
include/block/block_int-io.h | 8 ++++----
21
include/block/qapi.h | 2 +-
8
block/copy-before-write.c | 6 ++----
22
block/monitor/block-hmp-cmds.c | 2 +-
9
block/io.c | 2 ++
23
block/qapi.c | 2 +-
10
block/snapshot-access.c | 4 ++--
24
qemu-img.c | 48 +++++++++++++++++-----------------
11
5 files changed, 17 insertions(+), 15 deletions(-)
25
5 files changed, 29 insertions(+), 29 deletions(-)
12
26
13
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
27
diff --git a/qapi/block-core.json b/qapi/block-core.json
14
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block_int-common.h
29
--- a/qapi/block-core.json
16
+++ b/include/block/block_int-common.h
30
+++ b/qapi/block-core.json
17
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
18
* - receive the snapshot's actual length (which may differ from bs's
19
* length)
20
*/
21
- int coroutine_fn (*bdrv_co_preadv_snapshot)(BlockDriverState *bs,
22
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
23
- int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs,
24
- bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
25
- int64_t *map, BlockDriverState **file);
26
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_snapshot)(
27
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
28
+ QEMUIOVector *qiov, size_t qiov_offset);
29
+
30
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)(
31
+ BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
32
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
33
34
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
35
BlockDriverState *bs, int64_t offset, int64_t bytes);
36
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/block_int-io.h
39
+++ b/include/block/block_int-io.h
40
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
41
* the I/O API.
32
##
33
# @DummyBlockCoreForceArrays:
34
#
35
-# Not used by QMP; hack to let us use ImageInfoList internally
36
+# Not used by QMP; hack to let us use BlockNodeInfoList internally
37
#
38
# Since: 8.0
39
##
40
{ 'struct': 'DummyBlockCoreForceArrays',
41
- 'data': { 'unused-image-info': ['ImageInfo'] } }
42
+ 'data': { 'unused-block-node-info': ['BlockNodeInfo'] } }
43
diff --git a/include/block/qapi.h b/include/block/qapi.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/qapi.h
46
+++ b/include/block/qapi.h
47
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
48
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
49
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
50
const char *prefix);
51
-void bdrv_image_info_dump(ImageInfo *info);
52
+void bdrv_node_info_dump(BlockNodeInfo *info);
53
#endif
54
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/monitor/block-hmp-cmds.c
57
+++ b/block/monitor/block-hmp-cmds.c
58
@@ -XXX,XX +XXX,XX @@ static void print_block_info(Monitor *mon, BlockInfo *info,
59
monitor_printf(mon, "\nImages:\n");
60
image_info = inserted->image;
61
while (1) {
62
- bdrv_image_info_dump(image_info);
63
+ bdrv_node_info_dump(qapi_ImageInfo_base(image_info));
64
if (image_info->backing_image) {
65
image_info = image_info->backing_image;
66
} else {
67
diff --git a/block/qapi.c b/block/qapi.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/block/qapi.c
70
+++ b/block/qapi.c
71
@@ -XXX,XX +XXX,XX @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
72
visit_free(v);
73
}
74
75
-void bdrv_image_info_dump(ImageInfo *info)
76
+void bdrv_node_info_dump(BlockNodeInfo *info)
77
{
78
char *size_buf, *dsize_buf;
79
if (!info->has_actual_size) {
80
diff --git a/qemu-img.c b/qemu-img.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/qemu-img.c
83
+++ b/qemu-img.c
84
@@ -XXX,XX +XXX,XX @@ static void dump_snapshots(BlockDriverState *bs)
85
g_free(sn_tab);
86
}
87
88
-static void dump_json_image_info_list(ImageInfoList *list)
89
+static void dump_json_block_node_info_list(BlockNodeInfoList *list)
90
{
91
GString *str;
92
QObject *obj;
93
Visitor *v = qobject_output_visitor_new(&obj);
94
95
- visit_type_ImageInfoList(v, NULL, &list, &error_abort);
96
+ visit_type_BlockNodeInfoList(v, NULL, &list, &error_abort);
97
visit_complete(v, &obj);
98
str = qobject_to_json_pretty(obj, true);
99
assert(str != NULL);
100
@@ -XXX,XX +XXX,XX @@ static void dump_json_image_info_list(ImageInfoList *list)
101
g_string_free(str, true);
102
}
103
104
-static void dump_json_image_info(ImageInfo *info)
105
+static void dump_json_block_node_info(BlockNodeInfo *info)
106
{
107
GString *str;
108
QObject *obj;
109
Visitor *v = qobject_output_visitor_new(&obj);
110
111
- visit_type_ImageInfo(v, NULL, &info, &error_abort);
112
+ visit_type_BlockNodeInfo(v, NULL, &info, &error_abort);
113
visit_complete(v, &obj);
114
str = qobject_to_json_pretty(obj, true);
115
assert(str != NULL);
116
@@ -XXX,XX +XXX,XX @@ static void dump_json_image_info(ImageInfo *info)
117
g_string_free(str, true);
118
}
119
120
-static void dump_human_image_info_list(ImageInfoList *list)
121
+static void dump_human_image_info_list(BlockNodeInfoList *list)
122
{
123
- ImageInfoList *elem;
124
+ BlockNodeInfoList *elem;
125
bool delim = false;
126
127
for (elem = list; elem; elem = elem->next) {
128
@@ -XXX,XX +XXX,XX @@ static void dump_human_image_info_list(ImageInfoList *list)
129
}
130
delim = true;
131
132
- bdrv_image_info_dump(elem->value);
133
+ bdrv_node_info_dump(elem->value);
134
}
135
}
136
137
@@ -XXX,XX +XXX,XX @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
138
}
139
140
/**
141
- * Open an image file chain and return an ImageInfoList
142
+ * Open an image file chain and return an BlockNodeInfoList
143
*
144
* @filename: topmost image filename
145
* @fmt: topmost image format (may be NULL to autodetect)
146
* @chain: true - enumerate entire backing file chain
147
* false - only topmost image file
148
*
149
- * Returns a list of ImageInfo objects or NULL if there was an error opening an
150
- * image file. If there was an error a message will have been printed to
151
- * stderr.
152
+ * Returns a list of BlockNodeInfo objects or NULL if there was an error
153
+ * opening an image file. If there was an error a message will have been
154
+ * printed to stderr.
42
*/
155
*/
43
156
-static ImageInfoList *collect_image_info_list(bool image_opts,
44
-int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child,
157
- const char *filename,
45
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child,
158
- const char *fmt,
46
int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
159
- bool chain, bool force_share)
47
-int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs,
160
+static BlockNodeInfoList *collect_image_info_list(bool image_opts,
48
- bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
161
+ const char *filename,
49
- int64_t *map, BlockDriverState **file);
162
+ const char *fmt,
50
+int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status(
163
+ bool chain, bool force_share)
51
+ BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
164
{
52
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
165
- ImageInfoList *head = NULL;
53
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
166
- ImageInfoList **tail = &head;
54
int64_t offset, int64_t bytes);
167
+ BlockNodeInfoList *head = NULL;
55
168
+ BlockNodeInfoList **tail = &head;
56
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
169
GHashTable *filenames;
57
index XXXXXXX..XXXXXXX 100644
170
Error *err = NULL;
58
--- a/block/copy-before-write.c
171
59
+++ b/block/copy-before-write.c
172
@@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts,
60
@@ -XXX,XX +XXX,XX @@ cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
173
while (filename) {
61
g_free(req);
174
BlockBackend *blk;
62
}
175
BlockDriverState *bs;
63
176
- ImageInfo *info;
64
-static coroutine_fn int
177
+ BlockNodeInfo *info;
65
+static int coroutine_fn GRAPH_RDLOCK
178
66
cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
179
if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
67
QEMUIOVector *qiov, size_t qiov_offset)
180
error_report("Backing file '%s' creates an infinite loop.",
68
{
181
@@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts,
69
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
182
}
70
BdrvChild *file;
183
bs = blk_bs(blk);
71
int ret;
184
72
185
- bdrv_query_image_info(bs, &info, &err);
73
- assume_graph_lock(); /* FIXME */
186
+ bdrv_query_block_node_info(bs, &info, &err);
74
-
187
if (err) {
75
/* TODO: upgrade to async loop using AioTask */
188
error_report_err(err);
76
while (bytes) {
189
blk_unref(blk);
77
int64_t cur_bytes;
190
@@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts,
78
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
191
return head;
192
193
err:
194
- qapi_free_ImageInfoList(head);
195
+ qapi_free_BlockNodeInfoList(head);
196
g_hash_table_destroy(filenames);
197
return NULL;
198
}
199
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
200
OutputFormat output_format = OFORMAT_HUMAN;
201
bool chain = false;
202
const char *filename, *fmt, *output;
203
- ImageInfoList *list;
204
+ BlockNodeInfoList *list;
205
bool image_opts = false;
206
bool force_share = false;
207
208
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
209
break;
210
case OFORMAT_JSON:
211
if (chain) {
212
- dump_json_image_info_list(list);
213
+ dump_json_block_node_info_list(list);
214
} else {
215
- dump_json_image_info(list->value);
216
+ dump_json_block_node_info(list->value);
217
}
218
break;
219
}
220
221
- qapi_free_ImageInfoList(list);
222
+ qapi_free_BlockNodeInfoList(list);
79
return 0;
223
return 0;
80
}
224
}
81
225
82
-static int coroutine_fn
83
+static int coroutine_fn GRAPH_RDLOCK
84
cbw_co_snapshot_block_status(BlockDriverState *bs,
85
bool want_zero, int64_t offset, int64_t bytes,
86
int64_t *pnum, int64_t *map,
87
diff --git a/block/io.c b/block/io.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/io.c
90
+++ b/block/io.c
91
@@ -XXX,XX +XXX,XX @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes,
92
BlockDriver *drv = bs->drv;
93
int ret;
94
IO_CODE();
95
+ assert_bdrv_graph_readable();
96
97
if (!drv) {
98
return -ENOMEDIUM;
99
@@ -XXX,XX +XXX,XX @@ bdrv_co_snapshot_block_status(BlockDriverState *bs,
100
BlockDriver *drv = bs->drv;
101
int ret;
102
IO_CODE();
103
+ assert_bdrv_graph_readable();
104
105
if (!drv) {
106
return -ENOMEDIUM;
107
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/snapshot-access.c
110
+++ b/block/snapshot-access.c
111
@@ -XXX,XX +XXX,XX @@
112
#include "qemu/cutils.h"
113
#include "block/block_int.h"
114
115
-static coroutine_fn int
116
+static int coroutine_fn GRAPH_RDLOCK
117
snapshot_access_co_preadv_part(BlockDriverState *bs,
118
int64_t offset, int64_t bytes,
119
QEMUIOVector *qiov, size_t qiov_offset,
120
@@ -XXX,XX +XXX,XX @@ snapshot_access_co_preadv_part(BlockDriverState *bs,
121
return bdrv_co_preadv_snapshot(bs->file, offset, bytes, qiov, qiov_offset);
122
}
123
124
-static int coroutine_fn
125
+static int coroutine_fn GRAPH_RDLOCK
126
snapshot_access_co_block_status(BlockDriverState *bs,
127
bool want_zero, int64_t offset,
128
int64_t bytes, int64_t *pnum,
129
--
226
--
130
2.39.2
227
2.38.1
diff view generated by jsdifflib
New patch
1
From: Hanna Reitz <hreitz@redhat.com>
1
2
3
There is no real reason why bdrv_query_image_info() should generally not
4
recurse. The ImageInfo struct has a pointer to the backing image, so it
5
should generally be filled, unless the caller explicitly opts out.
6
7
This moves the recursing code from bdrv_block_device_info() into
8
bdrv_query_image_info().
9
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220620162704.80987-7-hreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
include/block/qapi.h | 2 +
16
block/qapi.c | 92 +++++++++++++++++++++++++++-----------------
17
2 files changed, 58 insertions(+), 36 deletions(-)
18
19
diff --git a/include/block/qapi.h b/include/block/qapi.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/qapi.h
22
+++ b/include/block/qapi.h
23
@@ -XXX,XX +XXX,XX @@ void bdrv_query_block_node_info(BlockDriverState *bs,
24
Error **errp);
25
void bdrv_query_image_info(BlockDriverState *bs,
26
ImageInfo **p_info,
27
+ bool flat,
28
+ bool skip_implicit_filters,
29
Error **errp);
30
31
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
32
diff --git a/block/qapi.c b/block/qapi.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/qapi.c
35
+++ b/block/qapi.c
36
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
37
Error **errp)
38
{
39
ImageInfo **p_image_info;
40
+ ImageInfo *backing_info;
41
BlockDriverState *bs0, *backing;
42
BlockDeviceInfo *info;
43
+ ERRP_GUARD();
44
45
if (!bs->drv) {
46
error_setg(errp, "Block device %s is ejected", bs->node_name);
47
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
48
bs0 = bs;
49
p_image_info = &info->image;
50
info->backing_file_depth = 0;
51
- while (1) {
52
- Error *local_err = NULL;
53
- bdrv_query_image_info(bs0, p_image_info, &local_err);
54
- if (local_err) {
55
- error_propagate(errp, local_err);
56
- qapi_free_BlockDeviceInfo(info);
57
- return NULL;
58
- }
59
-
60
- /* stop gathering data for flat output */
61
- if (flat) {
62
- break;
63
- }
64
65
- if (bs0->drv && bdrv_filter_or_cow_child(bs0)) {
66
- /*
67
- * Put any filtered child here (for backwards compatibility to when
68
- * we put bs0->backing here, which might be any filtered child).
69
- */
70
- info->backing_file_depth++;
71
- bs0 = bdrv_filter_or_cow_bs(bs0);
72
- p_image_info = &((*p_image_info)->backing_image);
73
- } else {
74
- break;
75
- }
76
+ /*
77
+ * Skip automatically inserted nodes that the user isn't aware of for
78
+ * query-block (blk != NULL), but not for query-named-block-nodes
79
+ */
80
+ bdrv_query_image_info(bs0, p_image_info, flat, blk != NULL, errp);
81
+ if (*errp) {
82
+ qapi_free_BlockDeviceInfo(info);
83
+ return NULL;
84
+ }
85
86
- /* Skip automatically inserted nodes that the user isn't aware of for
87
- * query-block (blk != NULL), but not for query-named-block-nodes */
88
- if (blk) {
89
- bs0 = bdrv_skip_implicit_filters(bs0);
90
- }
91
+ backing_info = info->image->backing_image;
92
+ while (backing_info) {
93
+ info->backing_file_depth++;
94
+ backing_info = backing_info->backing_image;
95
}
96
97
return info;
98
@@ -XXX,XX +XXX,XX @@ void bdrv_query_block_node_info(BlockDriverState *bs,
99
* bdrv_query_image_info:
100
* @bs: block node to examine
101
* @p_info: location to store image information
102
+ * @flat: skip backing node information
103
+ * @skip_implicit_filters: skip implicit filters in the backing chain
104
* @errp: location to store error information
105
*
106
- * Store "flat" image information in @p_info.
107
+ * Store image information in @p_info, potentially recursively covering the
108
+ * backing chain.
109
*
110
- * "Flat" means it does *not* query backing image information,
111
- * i.e. (*pinfo)->has_backing_image will be set to false and
112
- * (*pinfo)->backing_image to NULL even when the image does in fact have
113
- * a backing image.
114
+ * If @flat is true, do not query backing image information, i.e.
115
+ * (*p_info)->has_backing_image will be set to false and
116
+ * (*p_info)->backing_image to NULL even when the image does in fact have a
117
+ * backing image.
118
+ *
119
+ * If @skip_implicit_filters is true, implicit filter nodes in the backing chain
120
+ * will be skipped when querying backing image information.
121
+ * (@skip_implicit_filters is ignored when @flat is true.)
122
*
123
* @p_info will be set only on success. On error, store error in @errp.
124
*/
125
void bdrv_query_image_info(BlockDriverState *bs,
126
ImageInfo **p_info,
127
+ bool flat,
128
+ bool skip_implicit_filters,
129
Error **errp)
130
{
131
ImageInfo *info;
132
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
133
info = g_new0(ImageInfo, 1);
134
bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
135
if (*errp) {
136
- qapi_free_ImageInfo(info);
137
- return;
138
+ goto fail;
139
+ }
140
+
141
+ if (!flat) {
142
+ BlockDriverState *backing;
143
+
144
+ /*
145
+ * Use any filtered child here (for backwards compatibility to when
146
+ * we always took bs->backing, which might be any filtered child).
147
+ */
148
+ backing = bdrv_filter_or_cow_bs(bs);
149
+ if (skip_implicit_filters) {
150
+ backing = bdrv_skip_implicit_filters(backing);
151
+ }
152
+
153
+ if (backing) {
154
+ bdrv_query_image_info(backing, &info->backing_image, false,
155
+ skip_implicit_filters, errp);
156
+ if (*errp) {
157
+ goto fail;
158
+ }
159
+ }
160
}
161
162
*p_info = info;
163
+ return;
164
+
165
+fail:
166
+ assert(*errp);
167
+ qapi_free_ImageInfo(info);
168
}
169
170
/* @p_info will be set only on success. */
171
--
172
2.38.1
diff view generated by jsdifflib
1
From: Or Ozeri <oro@il.ibm.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Starting from ceph Reef, RBD has built-in support for layered encryption,
3
Introduce a new QAPI type BlockGraphInfo and an associated
4
where each ancestor image (in a cloned image setting) can be possibly
4
bdrv_query_block_graph_info() function that recursively gathers
5
encrypted using a unique passphrase.
5
BlockNodeInfo objects through a block graph.
6
6
7
A new function, rbd_encryption_load2, was added to librbd API.
7
A follow-up patch is going to make "qemu-img info" use this to print
8
This new function supports an array of passphrases (via "spec" structs).
8
information about all nodes that are (usually implicitly) opened for a
9
given image file.
9
10
10
This commit extends the qemu rbd driver API to use this new librbd API,
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
in order to support this new layered encryption feature.
12
Message-Id: <20220620162704.80987-8-hreitz@redhat.com>
12
13
Signed-off-by: Or Ozeri <oro@il.ibm.com>
14
Message-Id: <20230129113120.722708-4-oro@oro.sl.cloud9.ibm.com>
15
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
15
---
19
qapi/block-core.json | 11 +++-
16
qapi/block-core.json | 35 ++++++++++++++++++++++++++++++++
20
block/rbd.c | 153 ++++++++++++++++++++++++++++++++++++++++++-
17
include/block/qapi.h | 3 +++
21
2 files changed, 162 insertions(+), 2 deletions(-)
18
block/qapi.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
19
3 files changed, 86 insertions(+)
22
20
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
24
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
25
--- a/qapi/block-core.json
23
--- a/qapi/block-core.json
26
+++ b/qapi/block-core.json
24
+++ b/qapi/block-core.json
27
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
26
'*backing-image': 'ImageInfo'
27
} }
28
29
+##
30
+# @BlockChildInfo:
31
+#
32
+# Information about all nodes in the block graph starting at some node,
33
+# annotated with information about that node in relation to its parent.
34
+#
35
+# @name: Child name of the root node in the BlockGraphInfo struct, in its role
36
+# as the child of some undescribed parent node
37
+#
38
+# @info: Block graph information starting at this node
39
+#
40
+# Since: 8.0
41
+##
42
+{ 'struct': 'BlockChildInfo',
43
+ 'data': {
44
+ 'name': 'str',
45
+ 'info': 'BlockGraphInfo'
46
+ } }
47
+
48
+##
49
+# @BlockGraphInfo:
50
+#
51
+# Information about all nodes in a block (sub)graph in the form of BlockNodeInfo
52
+# data.
53
+# The base BlockNodeInfo struct contains the information for the (sub)graph's
54
+# root node.
55
+#
56
+# @children: Array of links to this node's child nodes' information
57
+#
58
+# Since: 8.0
59
+##
60
+{ 'struct': 'BlockGraphInfo',
61
+ 'base': 'BlockNodeInfo',
62
+ 'data': { 'children': ['BlockChildInfo'] } }
63
+
28
##
64
##
29
# @RbdEncryptionOptions:
65
# @ImageCheck:
30
#
66
#
31
+# @format: Encryption format.
67
diff --git a/include/block/qapi.h b/include/block/qapi.h
32
+#
33
+# @parent: Parent image encryption options (for cloned images).
34
+# Can be left unspecified if this cloned image is encrypted
35
+# using the same format and secret as its parent image (i.e.
36
+# not explicitly formatted) or if its parent image is not
37
+# encrypted. (Since 8.0)
38
+#
39
# Since: 6.1
40
##
41
{ 'union': 'RbdEncryptionOptions',
42
- 'base': { 'format': 'RbdImageEncryptionFormat' },
43
+ 'base': { 'format': 'RbdImageEncryptionFormat',
44
+ '*parent': 'RbdEncryptionOptions' },
45
'discriminator': 'format',
46
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
47
'luks2': 'RbdEncryptionOptionsLUKS2',
48
diff --git a/block/rbd.c b/block/rbd.c
49
index XXXXXXX..XXXXXXX 100644
68
index XXXXXXX..XXXXXXX 100644
50
--- a/block/rbd.c
69
--- a/include/block/qapi.h
51
+++ b/block/rbd.c
70
+++ b/include/block/qapi.h
52
@@ -XXX,XX +XXX,XX @@ static const char rbd_luks2_header_verification[
71
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
53
'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2
72
bool flat,
54
};
73
bool skip_implicit_filters,
55
74
Error **errp);
56
+static const char rbd_layered_luks_header_verification[
75
+void bdrv_query_block_graph_info(BlockDriverState *bs,
57
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
76
+ BlockGraphInfo **p_info,
58
+ 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 1
77
+ Error **errp);
59
+};
78
79
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
80
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
81
diff --git a/block/qapi.c b/block/qapi.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/block/qapi.c
84
+++ b/block/qapi.c
85
@@ -XXX,XX +XXX,XX @@ fail:
86
qapi_free_ImageInfo(info);
87
}
88
89
+/**
90
+ * bdrv_query_block_graph_info:
91
+ * @bs: root node to start from
92
+ * @p_info: location to store image information
93
+ * @errp: location to store error information
94
+ *
95
+ * Store image information about the graph starting from @bs in @p_info.
96
+ *
97
+ * @p_info will be set only on success. On error, store error in @errp.
98
+ */
99
+void bdrv_query_block_graph_info(BlockDriverState *bs,
100
+ BlockGraphInfo **p_info,
101
+ Error **errp)
102
+{
103
+ BlockGraphInfo *info;
104
+ BlockChildInfoList **children_list_tail;
105
+ BdrvChild *c;
106
+ ERRP_GUARD();
60
+
107
+
61
+static const char rbd_layered_luks2_header_verification[
108
+ info = g_new0(BlockGraphInfo, 1);
62
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
109
+ bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp);
63
+ 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 2
110
+ if (*errp) {
64
+};
111
+ goto fail;
65
+
66
typedef enum {
67
RBD_AIO_READ,
68
RBD_AIO_WRITE,
69
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
70
71
return 0;
72
}
73
+
74
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
75
+static int qemu_rbd_encryption_load2(rbd_image_t image,
76
+ RbdEncryptionOptions *encrypt,
77
+ Error **errp)
78
+{
79
+ int r = 0;
80
+ int encrypt_count = 1;
81
+ int i;
82
+ RbdEncryptionOptions *curr_encrypt;
83
+ rbd_encryption_spec_t *specs;
84
+ rbd_encryption_luks1_format_options_t *luks_opts;
85
+ rbd_encryption_luks2_format_options_t *luks2_opts;
86
+ rbd_encryption_luks_format_options_t *luks_any_opts;
87
+
88
+ /* count encryption options */
89
+ for (curr_encrypt = encrypt->parent; curr_encrypt;
90
+ curr_encrypt = curr_encrypt->parent) {
91
+ ++encrypt_count;
92
+ }
112
+ }
93
+
113
+
94
+ specs = g_new0(rbd_encryption_spec_t, encrypt_count);
114
+ children_list_tail = &info->children;
95
+
115
+
96
+ curr_encrypt = encrypt;
116
+ QLIST_FOREACH(c, &bs->children, next) {
97
+ for (i = 0; i < encrypt_count; ++i) {
117
+ BlockChildInfo *c_info;
98
+ switch (curr_encrypt->format) {
99
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: {
100
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS1;
101
+
118
+
102
+ luks_opts = g_new0(rbd_encryption_luks1_format_options_t, 1);
119
+ c_info = g_new0(BlockChildInfo, 1);
103
+ specs[i].opts = luks_opts;
120
+ QAPI_LIST_APPEND(children_list_tail, c_info);
104
+ specs[i].opts_size = sizeof(*luks_opts);
105
+
121
+
106
+ r = qemu_rbd_convert_luks_options(
122
+ c_info->name = g_strdup(c->name);
107
+ qapi_RbdEncryptionOptionsLUKS_base(
123
+ bdrv_query_block_graph_info(c->bs, &c_info->info, errp);
108
+ &curr_encrypt->u.luks),
124
+ if (*errp) {
109
+ (char **)&luks_opts->passphrase,
125
+ goto fail;
110
+ &luks_opts->passphrase_size,
111
+ errp);
112
+ break;
113
+ }
114
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
115
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS2;
116
+
117
+ luks2_opts = g_new0(rbd_encryption_luks2_format_options_t, 1);
118
+ specs[i].opts = luks2_opts;
119
+ specs[i].opts_size = sizeof(*luks2_opts);
120
+
121
+ r = qemu_rbd_convert_luks_options(
122
+ qapi_RbdEncryptionOptionsLUKS2_base(
123
+ &curr_encrypt->u.luks2),
124
+ (char **)&luks2_opts->passphrase,
125
+ &luks2_opts->passphrase_size,
126
+ errp);
127
+ break;
128
+ }
129
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
130
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS;
131
+
132
+ luks_any_opts = g_new0(rbd_encryption_luks_format_options_t, 1);
133
+ specs[i].opts = luks_any_opts;
134
+ specs[i].opts_size = sizeof(*luks_any_opts);
135
+
136
+ r = qemu_rbd_convert_luks_options(
137
+ qapi_RbdEncryptionOptionsLUKSAny_base(
138
+ &curr_encrypt->u.luks_any),
139
+ (char **)&luks_any_opts->passphrase,
140
+ &luks_any_opts->passphrase_size,
141
+ errp);
142
+ break;
143
+ }
144
+ default: {
145
+ r = -ENOTSUP;
146
+ error_setg_errno(
147
+ errp, -r, "unknown image encryption format: %u",
148
+ curr_encrypt->format);
149
+ }
150
+ }
126
+ }
151
+
152
+ if (r < 0) {
153
+ goto exit;
154
+ }
155
+
156
+ curr_encrypt = curr_encrypt->parent;
157
+ }
127
+ }
158
+
128
+
159
+ r = rbd_encryption_load2(image, specs, encrypt_count);
129
+ *p_info = info;
160
+ if (r < 0) {
130
+ return;
161
+ error_setg_errno(errp, -r, "layered encryption load fail");
162
+ goto exit;
163
+ }
164
+
131
+
165
+exit:
132
+fail:
166
+ for (i = 0; i < encrypt_count; ++i) {
133
+ assert(*errp != NULL);
167
+ if (!specs[i].opts) {
134
+ qapi_free_BlockGraphInfo(info);
168
+ break;
135
+}
169
+ }
170
+
136
+
171
+ switch (specs[i].format) {
137
/* @p_info will be set only on success. */
172
+ case RBD_ENCRYPTION_FORMAT_LUKS1: {
138
static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
173
+ luks_opts = specs[i].opts;
139
Error **errp)
174
+ g_free((void *)luks_opts->passphrase);
175
+ break;
176
+ }
177
+ case RBD_ENCRYPTION_FORMAT_LUKS2: {
178
+ luks2_opts = specs[i].opts;
179
+ g_free((void *)luks2_opts->passphrase);
180
+ break;
181
+ }
182
+ case RBD_ENCRYPTION_FORMAT_LUKS: {
183
+ luks_any_opts = specs[i].opts;
184
+ g_free((void *)luks_any_opts->passphrase);
185
+ break;
186
+ }
187
+ }
188
+
189
+ g_free(specs[i].opts);
190
+ }
191
+ g_free(specs);
192
+ return r;
193
+}
194
+#endif
195
#endif
196
197
/* FIXME Deprecate and remove keypairs or make it available in QMP. */
198
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
199
200
if (opts->encrypt) {
201
#ifdef LIBRBD_SUPPORTS_ENCRYPTION
202
- r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
203
+ if (opts->encrypt->parent) {
204
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
205
+ r = qemu_rbd_encryption_load2(s->image, opts->encrypt, errp);
206
+#else
207
+ r = -ENOTSUP;
208
+ error_setg(errp, "RBD library does not support layered encryption");
209
+#endif
210
+ } else {
211
+ r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
212
+ }
213
if (r < 0) {
214
goto failed_post_open;
215
}
216
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qemu_rbd_get_specific_info(BlockDriverState *bs,
217
spec_info->u.rbd.data->encryption_format =
218
RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
219
spec_info->u.rbd.data->has_encryption_format = true;
220
+ } else if (memcmp(buf, rbd_layered_luks_header_verification,
221
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
222
+ spec_info->u.rbd.data->encryption_format =
223
+ RBD_IMAGE_ENCRYPTION_FORMAT_LUKS;
224
+ spec_info->u.rbd.data->has_encryption_format = true;
225
+ } else if (memcmp(buf, rbd_layered_luks2_header_verification,
226
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
227
+ spec_info->u.rbd.data->encryption_format =
228
+ RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
229
+ spec_info->u.rbd.data->has_encryption_format = true;
230
} else {
231
spec_info->u.rbd.data->has_encryption_format = false;
232
}
233
--
140
--
234
2.39.2
141
2.38.1
diff view generated by jsdifflib
1
bdrv_mirror_top_pwritev() accesses the job object when active mirroring
1
From: Hanna Reitz <hreitz@redhat.com>
2
is enabled. It disables this code during early initialisation while
3
s->job isn't set yet.
4
2
5
However, s->job is still set way too early when the job object isn't
3
In order to let qemu-img info present a block graph, add a parameter to
6
fully initialised. For example, &s->ops_in_flight isn't initialised yet
4
bdrv_node_info_dump() and bdrv_image_info_specific_dump() so that the
7
and the in_flight bitmap doesn't exist yet. This causes crashes when a
5
information of nodes below the root level can be given an indentation.
8
write request comes in too early.
9
6
10
Move the assignment of s->job to when the mirror job is actually fully
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
initialised to make sure that the mirror_top driver doesn't access it
8
Message-Id: <20220620162704.80987-9-hreitz@redhat.com>
12
too early.
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Message-Id: <20230203152202.49054-3-kwolf@redhat.com>
16
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
11
---
20
block/mirror.c | 8 +++++++-
12
include/block/qapi.h | 5 ++--
21
1 file changed, 7 insertions(+), 1 deletion(-)
13
block/monitor/block-hmp-cmds.c | 2 +-
14
block/qapi.c | 47 +++++++++++++++++++---------------
15
qemu-img.c | 2 +-
16
qemu-io-cmds.c | 3 ++-
17
5 files changed, 34 insertions(+), 25 deletions(-)
22
18
23
diff --git a/block/mirror.c b/block/mirror.c
19
diff --git a/include/block/qapi.h b/include/block/qapi.h
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
25
--- a/block/mirror.c
21
--- a/include/block/qapi.h
26
+++ b/block/mirror.c
22
+++ b/include/block/qapi.h
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
23
@@ -XXX,XX +XXX,XX @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
24
25
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
26
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
27
- const char *prefix);
28
-void bdrv_node_info_dump(BlockNodeInfo *info);
29
+ const char *prefix,
30
+ int indentation);
31
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation);
32
#endif
33
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block/monitor/block-hmp-cmds.c
36
+++ b/block/monitor/block-hmp-cmds.c
37
@@ -XXX,XX +XXX,XX @@ static void print_block_info(Monitor *mon, BlockInfo *info,
38
monitor_printf(mon, "\nImages:\n");
39
image_info = inserted->image;
40
while (1) {
41
- bdrv_node_info_dump(qapi_ImageInfo_base(image_info));
42
+ bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0);
43
if (image_info->backing_image) {
44
image_info = image_info->backing_image;
45
} else {
46
diff --git a/block/qapi.c b/block/qapi.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block/qapi.c
49
+++ b/block/qapi.c
50
@@ -XXX,XX +XXX,XX @@ static bool qobject_is_empty_dump(const QObject *obj)
51
* prepending an optional prefix if the dump is not empty.
52
*/
53
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
54
- const char *prefix)
55
+ const char *prefix,
56
+ int indentation)
28
{
57
{
29
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
58
QObject *obj, *data;
30
BlockDriverState *bs = s->mirror_top_bs->backing->bs;
59
Visitor *v = qobject_output_visitor_new(&obj);
31
+ MirrorBDSOpaque *mirror_top_opaque = s->mirror_top_bs->opaque;
60
@@ -XXX,XX +XXX,XX @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
32
BlockDriverState *target_bs = blk_bs(s->target);
61
data = qdict_get(qobject_to(QDict, obj), "data");
33
bool need_drain = true;
62
if (!qobject_is_empty_dump(data)) {
34
BlockDeviceIoStatus iostatus;
63
if (prefix) {
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
64
- qemu_printf("%s", prefix);
65
+ qemu_printf("%*s%s", indentation * 4, "", prefix);
66
}
67
- dump_qobject(1, data);
68
+ dump_qobject(indentation + 1, data);
69
}
70
qobject_unref(obj);
71
visit_free(v);
72
}
73
74
-void bdrv_node_info_dump(BlockNodeInfo *info)
75
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation)
76
{
77
char *size_buf, *dsize_buf;
78
+ g_autofree char *ind_s = g_strdup_printf("%*s", indentation * 4, "");
79
+
80
if (!info->has_actual_size) {
81
dsize_buf = g_strdup("unavailable");
82
} else {
83
dsize_buf = size_to_str(info->actual_size);
84
}
85
size_buf = size_to_str(info->virtual_size);
86
- qemu_printf("image: %s\n"
87
- "file format: %s\n"
88
- "virtual size: %s (%" PRId64 " bytes)\n"
89
- "disk size: %s\n",
90
- info->filename, info->format, size_buf,
91
- info->virtual_size,
92
- dsize_buf);
93
+ qemu_printf("%simage: %s\n"
94
+ "%sfile format: %s\n"
95
+ "%svirtual size: %s (%" PRId64 " bytes)\n"
96
+ "%sdisk size: %s\n",
97
+ ind_s, info->filename,
98
+ ind_s, info->format,
99
+ ind_s, size_buf, info->virtual_size,
100
+ ind_s, dsize_buf);
101
g_free(size_buf);
102
g_free(dsize_buf);
103
104
if (info->has_encrypted && info->encrypted) {
105
- qemu_printf("encrypted: yes\n");
106
+ qemu_printf("%sencrypted: yes\n", ind_s);
107
}
108
109
if (info->has_cluster_size) {
110
- qemu_printf("cluster_size: %" PRId64 "\n",
111
- info->cluster_size);
112
+ qemu_printf("%scluster_size: %" PRId64 "\n",
113
+ ind_s, info->cluster_size);
114
}
115
116
if (info->has_dirty_flag && info->dirty_flag) {
117
- qemu_printf("cleanly shut down: no\n");
118
+ qemu_printf("%scleanly shut down: no\n", ind_s);
119
}
120
121
if (info->backing_filename) {
122
- qemu_printf("backing file: %s", info->backing_filename);
123
+ qemu_printf("%sbacking file: %s", ind_s, info->backing_filename);
124
if (!info->full_backing_filename) {
125
qemu_printf(" (cannot determine actual path)");
126
} else if (strcmp(info->backing_filename,
127
@@ -XXX,XX +XXX,XX @@ void bdrv_node_info_dump(BlockNodeInfo *info)
128
}
129
qemu_printf("\n");
130
if (info->backing_filename_format) {
131
- qemu_printf("backing file format: %s\n",
132
- info->backing_filename_format);
133
+ qemu_printf("%sbacking file format: %s\n",
134
+ ind_s, info->backing_filename_format);
36
}
135
}
37
}
136
}
38
137
39
+ /*
138
if (info->has_snapshots) {
40
+ * Only now the job is fully initialised and mirror_top_bs should start
139
SnapshotInfoList *elem;
41
+ * accessing it.
140
42
+ */
141
- qemu_printf("Snapshot list:\n");
43
+ mirror_top_opaque->job = s;
142
+ qemu_printf("%sSnapshot list:\n", ind_s);
44
+
143
+ qemu_printf("%s", ind_s);
45
assert(!s->dbi);
144
bdrv_snapshot_dump(NULL);
46
s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap);
145
qemu_printf("\n");
47
for (;;) {
146
48
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
147
@@ -XXX,XX +XXX,XX @@ void bdrv_node_info_dump(BlockNodeInfo *info)
49
if (!s) {
148
50
goto fail;
149
pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
150
pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
151
+ qemu_printf("%s", ind_s);
152
bdrv_snapshot_dump(&sn);
153
qemu_printf("\n");
154
}
155
@@ -XXX,XX +XXX,XX @@ void bdrv_node_info_dump(BlockNodeInfo *info)
156
157
if (info->format_specific) {
158
bdrv_image_info_specific_dump(info->format_specific,
159
- "Format specific information:\n");
160
+ "Format specific information:\n",
161
+ indentation);
51
}
162
}
52
- bs_opaque->job = s;
163
}
53
164
diff --git a/qemu-img.c b/qemu-img.c
54
/* The block job now has a reference to this node */
165
index XXXXXXX..XXXXXXX 100644
55
bdrv_unref(mirror_top_bs);
166
--- a/qemu-img.c
167
+++ b/qemu-img.c
168
@@ -XXX,XX +XXX,XX @@ static void dump_human_image_info_list(BlockNodeInfoList *list)
169
}
170
delim = true;
171
172
- bdrv_node_info_dump(elem->value);
173
+ bdrv_node_info_dump(elem->value, 0);
174
}
175
}
176
177
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/qemu-io-cmds.c
180
+++ b/qemu-io-cmds.c
181
@@ -XXX,XX +XXX,XX @@ static int info_f(BlockBackend *blk, int argc, char **argv)
182
}
183
if (spec_info) {
184
bdrv_image_info_specific_dump(spec_info,
185
- "Format specific information:\n");
186
+ "Format specific information:\n",
187
+ 0);
188
qapi_free_ImageInfoSpecific(spec_info);
189
}
190
56
--
191
--
57
2.39.2
192
2.38.1
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
If requests are being processed in the IOThread when a SCSIDevice is
3
Before we let qemu-img info print child node information, have
4
unplugged, scsi_device_purge_requests() -> scsi_req_cancel_async() races
4
common.filter, common.rc, and iotests.py filter it from the test output
5
with I/O completion callbacks. Both threads load and store req->aiocb.
5
so we get as few reference output changes as possible.
6
This can lead to assert(r->req.aiocb == NULL) failures and undefined
7
behavior.
8
6
9
Protect r->req.aiocb with the AioContext lock to prevent the race.
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
8
Message-Id: <20220620162704.80987-10-hreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Tested-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20230221212218.1378734-2-stefanha@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
11
---
17
hw/scsi/scsi-disk.c | 23 ++++++++++++++++-------
12
tests/qemu-iotests/iotests.py | 18 +++++++++++++++---
18
hw/scsi/scsi-generic.c | 11 ++++++-----
13
tests/qemu-iotests/common.filter | 22 ++++++++++++++--------
19
2 files changed, 22 insertions(+), 12 deletions(-)
14
tests/qemu-iotests/common.rc | 22 ++++++++++++++--------
15
3 files changed, 43 insertions(+), 19 deletions(-)
20
16
21
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/scsi/scsi-disk.c
19
--- a/tests/qemu-iotests/iotests.py
24
+++ b/hw/scsi/scsi-disk.c
20
+++ b/tests/qemu-iotests/iotests.py
25
@@ -XXX,XX +XXX,XX @@ static void scsi_aio_complete(void *opaque, int ret)
21
@@ -XXX,XX +XXX,XX @@ def qemu_img_log(*args: str, check: bool = True
26
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
22
27
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
23
def img_info_log(filename: str, filter_path: Optional[str] = None,
28
24
use_image_opts: bool = False, extra_args: Sequence[str] = (),
29
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
25
- check: bool = True,
26
+ check: bool = True, drop_child_info: bool = True,
27
) -> None:
28
args = ['info']
29
if use_image_opts:
30
@@ -XXX,XX +XXX,XX @@ def img_info_log(filename: str, filter_path: Optional[str] = None,
31
output = qemu_img(*args, check=check).stdout
32
if not filter_path:
33
filter_path = filename
34
- log(filter_img_info(output, filter_path))
35
+ log(filter_img_info(output, filter_path, drop_child_info))
36
37
def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
38
if '-f' in args or '--image-opts' in args:
39
@@ -XXX,XX +XXX,XX @@ def _filter(_key, value):
40
def filter_generated_node_ids(msg):
41
return re.sub("#block[0-9]+", "NODE_NAME", msg)
42
43
-def filter_img_info(output, filename):
44
+def filter_img_info(output: str, filename: str,
45
+ drop_child_info: bool = True) -> str:
46
lines = []
47
+ drop_indented = False
48
for line in output.split('\n'):
49
if 'disk size' in line or 'actual-size' in line:
50
continue
30
+
51
+
31
assert(r->req.aiocb != NULL);
52
+ # Drop child node info
32
r->req.aiocb = NULL;
53
+ if drop_indented:
33
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
54
+ if line.startswith(' '):
55
+ continue
56
+ drop_indented = False
57
+ if drop_child_info and "Child node '/" in line:
58
+ drop_indented = True
59
+ continue
34
+
60
+
35
if (scsi_disk_req_check_error(r, ret, true)) {
61
line = line.replace(filename, 'TEST_IMG')
36
goto done;
62
line = filter_testfiles(line)
37
}
63
line = line.replace(imgfmt, 'IMGFMT')
38
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
64
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
39
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
40
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
41
42
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
43
+
44
assert(r->req.aiocb != NULL);
45
r->req.aiocb = NULL;
46
47
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
48
if (ret < 0) {
49
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
50
} else {
51
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void *opaque, int ret)
52
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
53
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
54
55
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
56
+
57
assert(r->req.aiocb != NULL);
58
r->req.aiocb = NULL;
59
60
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
61
if (ret < 0) {
62
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
63
} else {
64
@@ -XXX,XX +XXX,XX @@ static void scsi_do_read_cb(void *opaque, int ret)
65
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
66
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
67
68
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
69
+
70
assert (r->req.aiocb != NULL);
71
r->req.aiocb = NULL;
72
73
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
74
if (ret < 0) {
75
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
76
} else {
77
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
78
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
79
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
80
81
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
82
+
83
assert (r->req.aiocb != NULL);
84
r->req.aiocb = NULL;
85
86
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
87
if (ret < 0) {
88
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
89
} else {
90
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete(void *opaque, int ret)
91
SCSIDiskReq *r = data->r;
92
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
93
94
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
95
+
96
assert(r->req.aiocb != NULL);
97
r->req.aiocb = NULL;
98
99
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
100
if (scsi_disk_req_check_error(r, ret, true)) {
101
scsi_req_unref(&r->req);
102
g_free(data);
103
@@ -XXX,XX +XXX,XX @@ static void scsi_write_same_complete(void *opaque, int ret)
104
SCSIDiskReq *r = data->r;
105
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
106
107
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
108
+
109
assert(r->req.aiocb != NULL);
110
r->req.aiocb = NULL;
111
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
112
+
113
if (scsi_disk_req_check_error(r, ret, true)) {
114
goto done;
115
}
116
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
117
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/scsi/scsi-generic.c
66
--- a/tests/qemu-iotests/common.filter
119
+++ b/hw/scsi/scsi-generic.c
67
+++ b/tests/qemu-iotests/common.filter
120
@@ -XXX,XX +XXX,XX @@ static void scsi_command_complete(void *opaque, int ret)
68
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
121
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
69
122
SCSIDevice *s = r->req.dev;
70
discard=0
123
71
regex_json_spec_start='^ *"format-specific": \{'
124
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
72
+ regex_json_child_start='^ *"children": \['
125
+
73
gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
126
assert(r->req.aiocb != NULL);
74
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
127
r->req.aiocb = NULL;
75
-e "s#$TEST_DIR#TEST_DIR#g" \
128
76
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
129
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
77
-e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \
130
scsi_command_complete_noio(r, ret);
78
-e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \
131
aio_context_release(blk_get_aio_context(s->conf.blk));
79
while IFS='' read -r line; do
132
}
80
- if [[ $format_specific == 1 ]]; then
133
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
81
- discard=0
134
SCSIDevice *s = r->req.dev;
82
- elif [[ $line == "Format specific information:" ]]; then
135
int len;
83
- discard=1
136
84
- elif [[ $line =~ $regex_json_spec_start ]]; then
137
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
85
- discard=2
138
+
86
- regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
139
assert(r->req.aiocb != NULL);
87
+ if [[ $discard == 0 ]]; then
140
r->req.aiocb = NULL;
88
+ if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
141
89
+ discard=1
142
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
90
+ elif [[ $line =~ "Child node '/" ]]; then
143
-
91
+ discard=1
144
if (ret || r->req.io_canceled) {
92
+ elif [[ $line =~ $regex_json_spec_start ]]; then
145
scsi_command_complete_noio(r, ret);
93
+ discard=2
146
goto done;
94
+ regex_json_end="^${line%%[^ ]*}\\},? *$"
147
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
95
+ elif [[ $line =~ $regex_json_child_start ]]; then
148
96
+ discard=2
149
trace_scsi_generic_write_complete(ret);
97
+ regex_json_end="^${line%%[^ ]*}\\],? *$"
150
98
+ fi
151
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
99
fi
152
+
100
if [[ $discard == 0 ]]; then
153
assert(r->req.aiocb != NULL);
101
echo "$line"
154
r->req.aiocb = NULL;
102
elif [[ $discard == 1 && ! $line ]]; then
155
103
echo
156
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
104
discard=0
157
-
105
- elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
158
if (ret || r->req.io_canceled) {
106
+ elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
159
scsi_command_complete_noio(r, ret);
107
discard=0
160
goto done;
108
fi
109
done
110
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/common.rc
113
+++ b/tests/qemu-iotests/common.rc
114
@@ -XXX,XX +XXX,XX @@ _img_info()
115
116
discard=0
117
regex_json_spec_start='^ *"format-specific": \{'
118
+ regex_json_child_start='^ *"children": \['
119
$QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \
120
sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
121
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
122
@@ -XXX,XX +XXX,XX @@ _img_info()
123
-e "/^disk size:/ D" \
124
-e "/actual-size/ D" | \
125
while IFS='' read -r line; do
126
- if [[ $format_specific == 1 ]]; then
127
- discard=0
128
- elif [[ $line == "Format specific information:" ]]; then
129
- discard=1
130
- elif [[ $line =~ $regex_json_spec_start ]]; then
131
- discard=2
132
- regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
133
+ if [[ $discard == 0 ]]; then
134
+ if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
135
+ discard=1
136
+ elif [[ $line =~ "Child node '/" ]]; then
137
+ discard=1
138
+ elif [[ $format_specific == 0 && $line =~ $regex_json_spec_start ]]; then
139
+ discard=2
140
+ regex_json_end="^${line%%[^ ]*}\\},? *$"
141
+ elif [[ $line =~ $regex_json_child_start ]]; then
142
+ discard=2
143
+ regex_json_end="^${line%%[^ ]*}\\],? *$"
144
+ fi
145
fi
146
if [[ $discard == 0 ]]; then
147
echo "$line"
148
elif [[ $discard == 1 && ! $line ]]; then
149
echo
150
discard=0
151
- elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
152
+ elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
153
discard=0
154
fi
155
done
161
--
156
--
162
2.39.2
157
2.38.1
diff view generated by jsdifflib
1
From: Or Ozeri <oro@il.ibm.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Signed-off-by: Or Ozeri <oro@il.ibm.com>
3
These tests read size information (sometimes disk size, sometimes
4
Message-Id: <20230129113120.722708-2-oro@oro.sl.cloud9.ibm.com>
4
virtual size) from qemu-img info's output. Once qemu-img starts
5
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
5
printing info about child nodes, we are going to see multiple instances
6
of that per image, but these tests are only interested in the first one,
7
so use "head -n 1" to get it.
8
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
Message-Id: <20220620162704.80987-11-hreitz@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
13
---
9
block/rbd.c | 16 ++++++----------
14
tests/qemu-iotests/106 | 4 ++--
10
1 file changed, 6 insertions(+), 10 deletions(-)
15
tests/qemu-iotests/214 | 6 ++++--
16
tests/qemu-iotests/308 | 4 ++--
17
3 files changed, 8 insertions(+), 6 deletions(-)
11
18
12
diff --git a/block/rbd.c b/block/rbd.c
19
diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100755
14
--- a/block/rbd.c
21
--- a/tests/qemu-iotests/106
15
+++ b/block/rbd.c
22
+++ b/tests/qemu-iotests/106
16
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
23
@@ -XXX,XX +XXX,XX @@ for create_mode in off falloc full; do
17
{
24
expected_size=$((expected_size + $GROWTH_SIZE))
18
int r = 0;
25
fi
19
g_autofree char *passphrase = NULL;
26
20
- size_t passphrase_len;
27
- actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size')
21
rbd_encryption_format_t format;
28
+ actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1)
22
rbd_encryption_options_t opts;
29
actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/')
23
rbd_encryption_luks1_format_options_t luks_opts;
30
24
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
31
# The actual size may exceed the expected size, depending on the file
25
opts_size = sizeof(luks_opts);
32
@@ -XXX,XX +XXX,XX @@ for growth_mode in falloc full; do
26
r = qemu_rbd_convert_luks_create_options(
33
_make_test_img -o "extent_size_hint=0" 2G
27
qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks),
34
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
28
- &luks_opts.alg, &passphrase, &passphrase_len, errp);
35
29
+ &luks_opts.alg, &passphrase, &luks_opts.passphrase_size,
36
- actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size')
30
+ errp);
37
+ actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1)
31
if (r < 0) {
38
actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/')
32
return r;
39
33
}
40
if [ $actual_size -lt $GROWTH_SIZE ]; then
34
luks_opts.passphrase = passphrase;
41
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
35
- luks_opts.passphrase_size = passphrase_len;
42
index XXXXXXX..XXXXXXX 100755
36
break;
43
--- a/tests/qemu-iotests/214
37
}
44
+++ b/tests/qemu-iotests/214
38
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
45
@@ -XXX,XX +XXX,XX @@ let data_size="8 * $cluster_size"
39
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
46
$QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
40
r = qemu_rbd_convert_luks_create_options(
47
2>&1 | _filter_qemu_io | _filter_testdir
41
qapi_RbdEncryptionCreateOptionsLUKS2_base(
48
sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
42
&encrypt->u.luks2),
49
- sed -n '/"actual-size":/ s/[^0-9]//gp')
43
- &luks2_opts.alg, &passphrase, &passphrase_len, errp);
50
+ sed -n '/"actual-size":/ s/[^0-9]//gp' |
44
+ &luks2_opts.alg, &passphrase, &luks2_opts.passphrase_size,
51
+ head -n 1)
45
+ errp);
52
46
if (r < 0) {
53
_make_test_img 2M -o cluster_size=$cluster_size
47
return r;
54
echo "Write compressed data:"
48
}
55
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
49
luks2_opts.passphrase = passphrase;
56
_filter_qemu_io | _filter_testdir
50
- luks2_opts.passphrase_size = passphrase_len;
57
51
break;
58
sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
52
}
59
- sed -n '/"actual-size":/ s/[^0-9]//gp')
53
default: {
60
+ sed -n '/"actual-size":/ s/[^0-9]//gp' |
54
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
61
+ head -n 1)
55
{
62
56
int r = 0;
63
if [ $sizeA -lt $sizeB ]
57
g_autofree char *passphrase = NULL;
64
then
58
- size_t passphrase_len;
65
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
59
rbd_encryption_luks1_format_options_t luks_opts;
66
index XXXXXXX..XXXXXXX 100755
60
rbd_encryption_luks2_format_options_t luks2_opts;
67
--- a/tests/qemu-iotests/308
61
rbd_encryption_format_t format;
68
+++ b/tests/qemu-iotests/308
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
69
@@ -XXX,XX +XXX,XX @@ echo
63
opts_size = sizeof(luks_opts);
70
echo '=== Remove export ==='
64
r = qemu_rbd_convert_luks_options(
71
65
qapi_RbdEncryptionOptionsLUKS_base(&encrypt->u.luks),
72
# Double-check that $EXT_MP appears as a non-empty file (the raw image)
66
- &passphrase, &passphrase_len, errp);
73
-$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size'
67
+ &passphrase, &luks_opts.passphrase_size, errp);
74
+$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
68
if (r < 0) {
75
69
return r;
76
fuse_export_del 'export-mp'
70
}
77
71
luks_opts.passphrase = passphrase;
78
# See that the file appears empty again
72
- luks_opts.passphrase_size = passphrase_len;
79
-$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size'
73
break;
80
+$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
74
}
81
75
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
82
echo
76
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
83
echo '=== Writable export ==='
77
opts_size = sizeof(luks2_opts);
78
r = qemu_rbd_convert_luks_options(
79
qapi_RbdEncryptionOptionsLUKS2_base(&encrypt->u.luks2),
80
- &passphrase, &passphrase_len, errp);
81
+ &passphrase, &luks2_opts.passphrase_size, errp);
82
if (r < 0) {
83
return r;
84
}
85
luks2_opts.passphrase = passphrase;
86
- luks2_opts.passphrase_size = passphrase_len;
87
break;
88
}
89
default: {
90
--
84
--
91
2.39.2
85
2.38.1
diff view generated by jsdifflib
1
This adds GRAPH_RDLOCK annotations to declare that callers of
1
From: Hanna Reitz <hreitz@redhat.com>
2
bdrv_*_dirty_bitmap() need to hold a reader lock for the graph.
2
3
3
For every node in the backing chain, collect its BlockGraphInfo struct
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
using bdrv_query_block_graph_info(). Print all nodes' information,
5
Message-Id: <20230203152202.49054-23-kwolf@redhat.com>
5
indenting child nodes and labelling them with a path constructed from
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
the child names leading to the node from the root (e.g. /file/file).
7
8
Note that we open each image with BDRV_O_NO_BACKING, so its backing
9
child is omitted from this graph, and thus presented in the previous
10
manner: By simply concatenating all images' information, separated with
11
blank lines.
12
13
This affects two iotests:
14
- 065: Here we try to get the format node's format specific information.
15
The pre-patch code does so by taking all lines from "Format specific
16
information:" until an empty line. This format specific information
17
is no longer followed by an empty line, though, but by child node
18
information, so limit the range by "Child node '/file':".
19
- 302: Calls qemu_img() for qemu-img info directly, which does not
20
filter the output, so the child node information ends up in the
21
output.
22
23
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
24
Message-Id: <20220620162704.80987-12-hreitz@redhat.com>
25
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
27
---
9
include/block/block-io.h | 14 ++++++--------
28
qapi/block-core.json | 4 +--
10
include/block/block_int-common.h | 6 ++++--
29
qemu-img.c | 69 ++++++++++++++++++++++++++------------
11
include/block/dirty-bitmap.h | 12 ++++++------
30
tests/qemu-iotests/065 | 2 +-
12
block/dirty-bitmap.c | 2 ++
31
tests/qemu-iotests/302.out | 5 +++
13
4 files changed, 18 insertions(+), 16 deletions(-)
32
4 files changed, 56 insertions(+), 24 deletions(-)
14
33
15
diff --git a/include/block/block-io.h b/include/block/block-io.h
34
diff --git a/qapi/block-core.json b/qapi/block-core.json
16
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block-io.h
36
--- a/qapi/block-core.json
18
+++ b/include/block/block-io.h
37
+++ b/qapi/block-core.json
19
@@ -XXX,XX +XXX,XX @@ AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
38
@@ -XXX,XX +XXX,XX @@
20
void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
39
##
21
void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
40
# @DummyBlockCoreForceArrays:
22
41
#
23
-bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
42
-# Not used by QMP; hack to let us use BlockNodeInfoList internally
24
- const char *name,
43
+# Not used by QMP; hack to let us use BlockGraphInfoList internally
25
- uint32_t granularity,
44
#
26
- Error **errp);
45
# Since: 8.0
27
-bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs,
46
##
28
- const char *name,
47
{ 'struct': 'DummyBlockCoreForceArrays',
29
- uint32_t granularity,
48
- 'data': { 'unused-block-node-info': ['BlockNodeInfo'] } }
30
- Error **errp);
49
+ 'data': { 'unused-block-graph-info': ['BlockGraphInfo'] } }
31
+bool coroutine_fn GRAPH_RDLOCK
50
diff --git a/qemu-img.c b/qemu-img.c
32
+bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
51
index XXXXXXX..XXXXXXX 100644
33
+ uint32_t granularity, Error **errp);
52
--- a/qemu-img.c
34
+bool co_wrapper_bdrv_rdlock
53
+++ b/qemu-img.c
35
+bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
54
@@ -XXX,XX +XXX,XX @@ static void dump_snapshots(BlockDriverState *bs)
36
+ uint32_t granularity, Error **errp);
55
g_free(sn_tab);
56
}
57
58
-static void dump_json_block_node_info_list(BlockNodeInfoList *list)
59
+static void dump_json_block_graph_info_list(BlockGraphInfoList *list)
60
{
61
GString *str;
62
QObject *obj;
63
Visitor *v = qobject_output_visitor_new(&obj);
64
65
- visit_type_BlockNodeInfoList(v, NULL, &list, &error_abort);
66
+ visit_type_BlockGraphInfoList(v, NULL, &list, &error_abort);
67
visit_complete(v, &obj);
68
str = qobject_to_json_pretty(obj, true);
69
assert(str != NULL);
70
@@ -XXX,XX +XXX,XX @@ static void dump_json_block_node_info_list(BlockNodeInfoList *list)
71
g_string_free(str, true);
72
}
73
74
-static void dump_json_block_node_info(BlockNodeInfo *info)
75
+static void dump_json_block_graph_info(BlockGraphInfo *info)
76
{
77
GString *str;
78
QObject *obj;
79
Visitor *v = qobject_output_visitor_new(&obj);
80
81
- visit_type_BlockNodeInfo(v, NULL, &info, &error_abort);
82
+ visit_type_BlockGraphInfo(v, NULL, &info, &error_abort);
83
visit_complete(v, &obj);
84
str = qobject_to_json_pretty(obj, true);
85
assert(str != NULL);
86
@@ -XXX,XX +XXX,XX @@ static void dump_json_block_node_info(BlockNodeInfo *info)
87
g_string_free(str, true);
88
}
89
90
-static void dump_human_image_info_list(BlockNodeInfoList *list)
91
+static void dump_human_image_info(BlockGraphInfo *info, int indentation,
92
+ const char *path)
93
{
94
- BlockNodeInfoList *elem;
95
+ BlockChildInfoList *children_list;
96
+
97
+ bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation);
98
+
99
+ for (children_list = info->children; children_list;
100
+ children_list = children_list->next)
101
+ {
102
+ BlockChildInfo *child = children_list->value;
103
+ g_autofree char *child_path;
104
+
105
+ printf("%*sChild node '%s%s':\n",
106
+ indentation * 4, "", path, child->name);
107
+ child_path = g_strdup_printf("%s%s/", path, child->name);
108
+ dump_human_image_info(child->info, indentation + 1, child_path);
109
+ }
110
+}
111
+
112
+static void dump_human_image_info_list(BlockGraphInfoList *list)
113
+{
114
+ BlockGraphInfoList *elem;
115
bool delim = false;
116
117
for (elem = list; elem; elem = elem->next) {
118
@@ -XXX,XX +XXX,XX @@ static void dump_human_image_info_list(BlockNodeInfoList *list)
119
}
120
delim = true;
121
122
- bdrv_node_info_dump(elem->value, 0);
123
+ dump_human_image_info(elem->value, 0, "/");
124
}
125
}
126
127
@@ -XXX,XX +XXX,XX @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
128
}
37
129
38
/**
130
/**
131
- * Open an image file chain and return an BlockNodeInfoList
132
+ * Open an image file chain and return an BlockGraphInfoList
39
*
133
*
40
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
134
* @filename: topmost image filename
135
* @fmt: topmost image format (may be NULL to autodetect)
136
@@ -XXX,XX +XXX,XX @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
137
* opening an image file. If there was an error a message will have been
138
* printed to stderr.
139
*/
140
-static BlockNodeInfoList *collect_image_info_list(bool image_opts,
141
- const char *filename,
142
- const char *fmt,
143
- bool chain, bool force_share)
144
+static BlockGraphInfoList *collect_image_info_list(bool image_opts,
145
+ const char *filename,
146
+ const char *fmt,
147
+ bool chain, bool force_share)
148
{
149
- BlockNodeInfoList *head = NULL;
150
- BlockNodeInfoList **tail = &head;
151
+ BlockGraphInfoList *head = NULL;
152
+ BlockGraphInfoList **tail = &head;
153
GHashTable *filenames;
154
Error *err = NULL;
155
156
@@ -XXX,XX +XXX,XX @@ static BlockNodeInfoList *collect_image_info_list(bool image_opts,
157
while (filename) {
158
BlockBackend *blk;
159
BlockDriverState *bs;
160
- BlockNodeInfo *info;
161
+ BlockGraphInfo *info;
162
163
if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
164
error_report("Backing file '%s' creates an infinite loop.",
165
@@ -XXX,XX +XXX,XX @@ static BlockNodeInfoList *collect_image_info_list(bool image_opts,
166
}
167
bs = blk_bs(blk);
168
169
- bdrv_query_block_node_info(bs, &info, &err);
170
+ /*
171
+ * Note that the returned BlockGraphInfo object will not have
172
+ * information about this image's backing node, because we have opened
173
+ * it with BDRV_O_NO_BACKING. Printing this object will therefore not
174
+ * duplicate the backing chain information that we obtain by walking
175
+ * the chain manually here.
176
+ */
177
+ bdrv_query_block_graph_info(bs, &info, &err);
178
if (err) {
179
error_report_err(err);
180
blk_unref(blk);
181
@@ -XXX,XX +XXX,XX @@ static BlockNodeInfoList *collect_image_info_list(bool image_opts,
182
return head;
183
184
err:
185
- qapi_free_BlockNodeInfoList(head);
186
+ qapi_free_BlockGraphInfoList(head);
187
g_hash_table_destroy(filenames);
188
return NULL;
189
}
190
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
191
OutputFormat output_format = OFORMAT_HUMAN;
192
bool chain = false;
193
const char *filename, *fmt, *output;
194
- BlockNodeInfoList *list;
195
+ BlockGraphInfoList *list;
196
bool image_opts = false;
197
bool force_share = false;
198
199
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
200
break;
201
case OFORMAT_JSON:
202
if (chain) {
203
- dump_json_block_node_info_list(list);
204
+ dump_json_block_graph_info_list(list);
205
} else {
206
- dump_json_block_node_info(list->value);
207
+ dump_json_block_graph_info(list->value);
208
}
209
break;
210
}
211
212
- qapi_free_BlockNodeInfoList(list);
213
+ qapi_free_BlockGraphInfoList(list);
214
return 0;
215
}
216
217
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
218
index XXXXXXX..XXXXXXX 100755
219
--- a/tests/qemu-iotests/065
220
+++ b/tests/qemu-iotests/065
221
@@ -XXX,XX +XXX,XX @@ class TestQemuImgInfo(TestImageInfoSpecific):
222
def test_human(self):
223
data = qemu_img('info', '--output=human', test_img).stdout.split('\n')
224
data = data[(data.index('Format specific information:') + 1)
225
- :data.index('')]
226
+ :data.index("Child node '/file':")]
227
for field in data:
228
self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
229
data = [line.strip() for line in data]
230
diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out
41
index XXXXXXX..XXXXXXX 100644
231
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block_int-common.h
232
--- a/tests/qemu-iotests/302.out
43
+++ b/include/block/block_int-common.h
233
+++ b/tests/qemu-iotests/302.out
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
234
@@ -XXX,XX +XXX,XX @@ image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
45
void (*bdrv_drain_end)(BlockDriverState *bs);
235
file format: raw
46
236
virtual size: 448 KiB (458752 bytes)
47
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
237
disk size: unavailable
48
- bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
238
+Child node '/file':
49
+
239
+ image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
50
+ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_can_store_new_dirty_bitmap)(
240
+ file format: nbd
51
BlockDriverState *bs, const char *name, uint32_t granularity,
241
+ virtual size: 448 KiB (458752 bytes)
52
Error **errp);
242
+ disk size: unavailable
53
- int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
243
54
+
244
=== Converted image info ===
55
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_remove_persistent_dirty_bitmap)(
245
image: TEST_IMG
56
BlockDriverState *bs, const char *name, Error **errp);
57
};
58
59
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
60
index XXXXXXX..XXXXXXX 100644
61
--- a/include/block/dirty-bitmap.h
62
+++ b/include/block/dirty-bitmap.h
63
@@ -XXX,XX +XXX,XX @@ int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
64
void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap);
65
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
66
67
-int coroutine_fn bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
68
- const char *name,
69
- Error **errp);
70
-int co_wrapper bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
71
- const char *name,
72
- Error **errp);
73
+int coroutine_fn GRAPH_RDLOCK
74
+bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
75
+ Error **errp);
76
+int co_wrapper_bdrv_rdlock
77
+bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
78
+ Error **errp);
79
80
void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
81
void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
82
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/block/dirty-bitmap.c
85
+++ b/block/dirty-bitmap.c
86
@@ -XXX,XX +XXX,XX @@ int coroutine_fn
87
bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
88
Error **errp)
89
{
90
+ assert_bdrv_graph_readable();
91
if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) {
92
return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp);
93
}
94
@@ -XXX,XX +XXX,XX @@ bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
95
uint32_t granularity, Error **errp)
96
{
97
BlockDriver *drv = bs->drv;
98
+ assert_bdrv_graph_readable();
99
100
if (!drv) {
101
error_setg_errno(errp, ENOMEDIUM,
102
--
246
--
103
2.39.2
247
2.38.1
diff view generated by jsdifflib
1
All callers are already GRAPH_RDLOCK, so just add the annotation and
1
From: Hanna Reitz <hreitz@redhat.com>
2
remove assume_graph_lock().
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Currently, when querying a qcow2 image, qemu-img info reports something
5
Message-Id: <20230203152202.49054-14-kwolf@redhat.com>
4
like this:
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
6
image: test.qcow2
7
file format: qcow2
8
virtual size: 64 MiB (67108864 bytes)
9
disk size: 196 KiB
10
cluster_size: 65536
11
Format specific information:
12
compat: 1.1
13
compression type: zlib
14
lazy refcounts: false
15
refcount bits: 16
16
corrupt: false
17
extended l2: false
18
Child node '/file':
19
image: test.qcow2
20
file format: file
21
virtual size: 192 KiB (197120 bytes)
22
disk size: 196 KiB
23
Format specific information:
24
extent size hint: 1048576
25
26
Notably, the way the keys are named is specific for image files: The
27
filename is shown under "image", the BDS driver under "file format", and
28
the BDS length under "virtual size". This does not make much sense for
29
nodes that are not actually supposed to be guest images, like the /file
30
child node shown above.
31
32
Give bdrv_node_info_dump() a @protocol parameter that gives a hint that
33
the respective node is probably just used for data storage and does not
34
necessarily present the data for a VM guest disk. This renames the keys
35
so that with this patch, the output becomes:
36
37
image: test.qcow2
38
[...]
39
Child node '/file':
40
filename: test.qcow2
41
protocol type: file
42
file length: 192 KiB (197120 bytes)
43
disk size: 196 KiB
44
Format specific information:
45
extent size hint: 1048576
46
47
(Perhaps we should also rename "Format specific information", but I
48
could not come up with anything better that will not become problematic
49
if we guess wrong with the protocol "heuristic".)
50
51
This change affects iotest 302, which has protocol node information in
52
its reference output.
53
54
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
55
Message-Id: <20220620162704.80987-13-hreitz@redhat.com>
56
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
57
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
58
---
9
block/io.c | 7 +++----
59
include/block/qapi.h | 2 +-
10
1 file changed, 3 insertions(+), 4 deletions(-)
60
block/monitor/block-hmp-cmds.c | 2 +-
61
block/qapi.c | 39 ++++++++++++++++++++++++++++------
62
qemu-img.c | 3 ++-
63
tests/qemu-iotests/302.out | 6 +++---
64
5 files changed, 39 insertions(+), 13 deletions(-)
11
65
12
diff --git a/block/io.c b/block/io.c
66
diff --git a/include/block/qapi.h b/include/block/qapi.h
13
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
14
--- a/block/io.c
68
--- a/include/block/qapi.h
15
+++ b/block/io.c
69
+++ b/include/block/qapi.h
16
@@ -XXX,XX +XXX,XX @@ fail:
70
@@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
17
return ret;
71
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
72
const char *prefix,
73
int indentation);
74
-void bdrv_node_info_dump(BlockNodeInfo *info, int indentation);
75
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol);
76
#endif
77
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/monitor/block-hmp-cmds.c
80
+++ b/block/monitor/block-hmp-cmds.c
81
@@ -XXX,XX +XXX,XX @@ static void print_block_info(Monitor *mon, BlockInfo *info,
82
monitor_printf(mon, "\nImages:\n");
83
image_info = inserted->image;
84
while (1) {
85
- bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0);
86
+ bdrv_node_info_dump(qapi_ImageInfo_base(image_info), 0, false);
87
if (image_info->backing_image) {
88
image_info = image_info->backing_image;
89
} else {
90
diff --git a/block/qapi.c b/block/qapi.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/block/qapi.c
93
+++ b/block/qapi.c
94
@@ -XXX,XX +XXX,XX @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
95
visit_free(v);
18
}
96
}
19
97
20
-static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
98
-void bdrv_node_info_dump(BlockNodeInfo *info, int indentation)
21
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
99
+/**
22
+static int coroutine_fn GRAPH_RDLOCK
100
+ * Print the given @info object in human-readable form. Every field is indented
23
+bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
101
+ * using the given @indentation (four spaces per indentation level).
24
+ BdrvRequestFlags flags)
102
+ *
103
+ * When using this to print a whole block graph, @protocol can be set to true to
104
+ * signify that the given information is associated with a protocol node, i.e.
105
+ * just data storage for an image, such that the data it presents is not really
106
+ * a full VM disk. If so, several fields change name: For example, "virtual
107
+ * size" is printed as "file length".
108
+ * (Consider a qcow2 image, which is represented by a qcow2 node and a file
109
+ * node. Printing a "virtual size" for the file node does not make sense,
110
+ * because without the qcow2 node, it is not really a guest disk, so it does not
111
+ * have a "virtual size". Therefore, we call it "file length" instead.)
112
+ *
113
+ * @protocol is ignored when @indentation is 0, because we take that to mean
114
+ * that the associated node is the root node in the queried block graph, and
115
+ * thus is always to be interpreted as a standalone guest disk.
116
+ */
117
+void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol)
25
{
118
{
26
BlockDriver *drv = bs->drv;
119
char *size_buf, *dsize_buf;
27
QEMUIOVector qiov;
120
g_autofree char *ind_s = g_strdup_printf("%*s", indentation * 4, "");
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
121
29
int head = 0;
122
+ if (indentation == 0) {
30
int tail = 0;
123
+ /* Top level, consider this a normal image */
31
124
+ protocol = false;
32
- assume_graph_lock(); /* FIXME */
125
+ }
33
-
126
+
34
int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
127
if (!info->has_actual_size) {
35
INT64_MAX);
128
dsize_buf = g_strdup("unavailable");
36
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
129
} else {
130
dsize_buf = size_to_str(info->actual_size);
131
}
132
size_buf = size_to_str(info->virtual_size);
133
- qemu_printf("%simage: %s\n"
134
- "%sfile format: %s\n"
135
- "%svirtual size: %s (%" PRId64 " bytes)\n"
136
+ qemu_printf("%s%s: %s\n"
137
+ "%s%s: %s\n"
138
+ "%s%s: %s (%" PRId64 " bytes)\n"
139
"%sdisk size: %s\n",
140
- ind_s, info->filename,
141
- ind_s, info->format,
142
- ind_s, size_buf, info->virtual_size,
143
+ ind_s, protocol ? "filename" : "image", info->filename,
144
+ ind_s, protocol ? "protocol type" : "file format",
145
+ info->format,
146
+ ind_s, protocol ? "file length" : "virtual size",
147
+ size_buf, info->virtual_size,
148
ind_s, dsize_buf);
149
g_free(size_buf);
150
g_free(dsize_buf);
151
diff --git a/qemu-img.c b/qemu-img.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/qemu-img.c
154
+++ b/qemu-img.c
155
@@ -XXX,XX +XXX,XX @@ static void dump_human_image_info(BlockGraphInfo *info, int indentation,
156
{
157
BlockChildInfoList *children_list;
158
159
- bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation);
160
+ bdrv_node_info_dump(qapi_BlockGraphInfo_base(info), indentation,
161
+ info->children == NULL);
162
163
for (children_list = info->children; children_list;
164
children_list = children_list->next)
165
diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out
166
index XXXXXXX..XXXXXXX 100644
167
--- a/tests/qemu-iotests/302.out
168
+++ b/tests/qemu-iotests/302.out
169
@@ -XXX,XX +XXX,XX @@ file format: raw
170
virtual size: 448 KiB (458752 bytes)
171
disk size: unavailable
172
Child node '/file':
173
- image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
174
- file format: nbd
175
- virtual size: 448 KiB (458752 bytes)
176
+ filename: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
177
+ protocol type: nbd
178
+ file length: 448 KiB (458752 bytes)
179
disk size: unavailable
180
181
=== Converted image info ===
37
--
182
--
38
2.39.2
183
2.38.1
diff view generated by jsdifflib