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 |