1 | The following changes since commit 0280396a33c7210c4df5306afeab63411a41535a: | 1 | The following changes since commit 239b8b0699a222fd21da1c5fdeba0a2456085a47: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-gdbstub-150221-1' into staging (2021-02-15 10:13:13 +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 | git://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 b248e61652e20c3353af4b0ccb90f17d76f4db21: | 9 | for you to fetch changes up to 4711b0a8490827c332b3f9281f689ce9555b7fab: |
10 | 10 | ||
11 | monitor/qmp: Stop processing requests when shutdown is requested (2021-02-15 15:10:14 +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 | - qemu-storage-daemon: Enable object-add | 16 | - qemu-img info: Show protocol-level information |
17 | - blockjob: Fix crash with IOthread when block commit after snapshot | 17 | - Move more functions to coroutines |
18 | - monitor: Shutdown fixes | 18 | - Make coroutine annotations ready for static analysis |
19 | - xen-block: fix reporting of discard feature | 19 | - qemu-img: Fix exit code for errors closing the image |
20 | - qcow2: Remove half-initialised image file after failed image creation | 20 | - qcow2 bitmaps: Fix theoretical corruption in error path |
21 | - ahci: Fix DMA direction | 21 | - pflash: Only load non-zero parts of backend image to save memory |
22 | - iotests fixes | 22 | - Code cleanup and test case improvements |
23 | 23 | ||
24 | ---------------------------------------------------------------- | 24 | ---------------------------------------------------------------- |
25 | Alexander Bulekov (1): | 25 | Alberto Faria (2): |
26 | hw/ide/ahci: map cmd_fis as DMA_DIRECTION_TO_DEVICE | 26 | coroutine: annotate coroutine_fn for libclang |
27 | block: Add no_coroutine_fn and coroutine_mixed_fn marker | ||
27 | 28 | ||
28 | Kevin Wolf (3): | 29 | Emanuele Giuseppe Esposito (14): |
29 | qemu-storage-daemon: Enable object-add | 30 | block-coroutine-wrapper: support void functions |
30 | monitor: Fix assertion failure on shutdown | 31 | block: Convert bdrv_io_plug() to co_wrapper |
31 | monitor/qmp: Stop processing requests when shutdown is requested | 32 | block: Convert bdrv_io_unplug() to co_wrapper |
33 | block: Convert bdrv_is_inserted() to co_wrapper | ||
34 | block: Rename refresh_total_sectors to bdrv_refresh_total_sectors | ||
35 | block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed | ||
36 | block-backend: use bdrv_getlength instead of blk_getlength | ||
37 | block: use bdrv_co_refresh_total_sectors when possible | ||
38 | block: Convert bdrv_get_allocated_file_size() to co_wrapper | ||
39 | block: Convert bdrv_get_info() to co_wrapper_mixed | ||
40 | block: Convert bdrv_eject() to co_wrapper | ||
41 | block: Convert bdrv_lock_medium() to co_wrapper | ||
42 | block: Convert bdrv_debug_event() to co_wrapper_mixed | ||
43 | block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate() | ||
32 | 44 | ||
33 | Max Reitz (1): | 45 | Hanna Reitz (12): |
34 | iotests: Consistent $IMGOPTS boundary matching | 46 | block: Improve empty format-specific info dump |
47 | block/file: Add file-specific image info | ||
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 | ||
35 | 58 | ||
36 | Maxim Levitsky (3): | 59 | Kevin Wolf (4): |
37 | crypto: luks: Fix tiny memory leak | 60 | qcow2: Fix theoretical corruption in store_bitmap() error path |
38 | block: add bdrv_co_delete_file_noerr | 61 | qemu-img commit: Report errors while closing the image |
39 | block: qcow2: remove the created file on initialization error | 62 | qemu-img bitmap: Report errors while closing the image |
63 | qemu-iotests: Test qemu-img bitmap/commit exit code on error | ||
40 | 64 | ||
41 | Michael Qiu (1): | 65 | Paolo Bonzini (2): |
42 | blockjob: Fix crash with IOthread when block commit after snapshot | 66 | qemu-io: do not reinvent the blk_pwrite_zeroes wheel |
67 | block: remove bdrv_coroutine_enter | ||
43 | 68 | ||
44 | Roger Pau Monné (1): | 69 | Philippe Mathieu-Daudé (1): |
45 | xen-block: fix reporting of discard feature | 70 | block/nbd: Add missing <qemu/bswap.h> include |
46 | 71 | ||
47 | Thomas Huth (1): | 72 | Thomas Huth (2): |
48 | tests/qemu-iotests: Remove test 259 from the "auto" group | 73 | tests/qemu-iotests/312: Mark "quorum" as required driver |
74 | tests/qemu-iotests/262: Check for availability of "blkverify" first | ||
49 | 75 | ||
50 | include/block/block.h | 1 + | 76 | Xiang Zheng (1): |
51 | block.c | 22 ++++++++++++++++++++++ | 77 | pflash: Only read non-zero parts of backend image |
52 | block/crypto.c | 13 ++----------- | 78 | |
53 | block/qcow2.c | 8 +++++--- | 79 | qapi/block-core.json | 123 +++++++- |
54 | blockjob.c | 8 ++++++-- | 80 | include/block/block-common.h | 11 +- |
55 | hw/block/xen-block.c | 1 + | 81 | include/block/block-io.h | 41 ++- |
56 | hw/ide/ahci.c | 12 ++++++------ | 82 | include/block/block_int-common.h | 26 +- |
57 | monitor/monitor.c | 25 +++++++++++++++---------- | 83 | include/block/block_int-io.h | 5 +- |
58 | monitor/qmp.c | 5 +++++ | 84 | include/block/nbd.h | 1 + |
59 | storage-daemon/qemu-storage-daemon.c | 2 ++ | 85 | include/block/qapi.h | 14 +- |
60 | tests/qemu-iotests/259 | 2 +- | 86 | include/qemu/coroutine.h | 43 +++ |
61 | tests/qemu-iotests/common.rc | 4 +++- | 87 | include/sysemu/block-backend-io.h | 31 +- |
62 | 12 files changed, 69 insertions(+), 34 deletions(-) | 88 | block.c | 88 +++--- |
89 | block/blkdebug.c | 11 +- | ||
90 | block/blkio.c | 15 +- | ||
91 | block/blklogwrites.c | 6 +- | ||
92 | block/blkreplay.c | 6 +- | ||
93 | block/blkverify.c | 6 +- | ||
94 | block/block-backend.c | 38 +-- | ||
95 | block/commit.c | 4 +- | ||
96 | block/copy-on-read.c | 18 +- | ||
97 | block/crypto.c | 14 +- | ||
98 | block/curl.c | 10 +- | ||
99 | block/file-posix.c | 137 +++++---- | ||
100 | block/file-win32.c | 18 +- | ||
101 | block/filter-compress.c | 20 +- | ||
102 | block/gluster.c | 23 +- | ||
103 | block/io.c | 76 ++--- | ||
104 | block/iscsi.c | 17 +- | ||
105 | block/mirror.c | 6 +- | ||
106 | block/monitor/block-hmp-cmds.c | 2 +- | ||
107 | block/nbd.c | 8 +- | ||
108 | block/nfs.c | 4 +- | ||
109 | block/null.c | 13 +- | ||
110 | block/nvme.c | 14 +- | ||
111 | block/preallocate.c | 16 +- | ||
112 | block/qapi.c | 317 ++++++++++++++++----- | ||
113 | block/qcow.c | 5 +- | ||
114 | block/qcow2-bitmap.c | 5 +- | ||
115 | block/qcow2-refcount.c | 2 +- | ||
116 | block/qcow2.c | 17 +- | ||
117 | block/qed.c | 11 +- | ||
118 | block/quorum.c | 8 +- | ||
119 | block/raw-format.c | 25 +- | ||
120 | block/rbd.c | 9 +- | ||
121 | block/replication.c | 6 +- | ||
122 | block/ssh.c | 4 +- | ||
123 | block/throttle.c | 6 +- | ||
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 | ||
63 | 151 | ||
64 | 152 | diff view generated by jsdifflib |
1 | Before this patch, monitor_qmp_dispatcher_co() used to check whether | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | shutdown is requested only when it would have to wait for new requests. | ||
3 | If there were still some queued requests, it would try to execute all of | ||
4 | them before shutting down. | ||
5 | 2 | ||
6 | This can be surprising when the queued QMP commands take long or hang | 3 | "quorum" is required by iotest 312 - if it is not compiled into the |
7 | because Ctrl-C may not actually exit QEMU as soon as possible. | 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. | ||
8 | 6 | ||
9 | Change monitor_qmp_dispatcher_co() so that it additionally checks | 7 | Signed-off-by: Thomas Huth <thuth@redhat.com> |
10 | whether shutdown is request before it gets a new request from the queue. | 8 | Message-Id: <20230104114601.269351-1-thuth@redhat.com> |
11 | 9 | Reviewed-by: Alberto Garcia <berto@igalia.com> | |
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
13 | Message-Id: <20210212172028.288825-3-kwolf@redhat.com> | 11 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> |
14 | Tested-by: Markus Armbruster <armbru@redhat.com> | ||
15 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
17 | --- | 13 | --- |
18 | monitor/qmp.c | 5 +++++ | 14 | tests/qemu-iotests/312 | 1 + |
19 | 1 file changed, 5 insertions(+) | 15 | 1 file changed, 1 insertion(+) |
20 | 16 | ||
21 | diff --git a/monitor/qmp.c b/monitor/qmp.c | 17 | diff --git a/tests/qemu-iotests/312 b/tests/qemu-iotests/312 |
22 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100755 |
23 | --- a/monitor/qmp.c | 19 | --- a/tests/qemu-iotests/312 |
24 | +++ b/monitor/qmp.c | 20 | +++ b/tests/qemu-iotests/312 |
25 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) | 21 | @@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2 |
26 | */ | 22 | _supported_proto file |
27 | qatomic_mb_set(&qmp_dispatcher_co_busy, false); | 23 | _supported_os Linux |
28 | 24 | _unsupported_imgopts cluster_size data_file | |
29 | + /* On shutdown, don't take any more requests from the queue */ | 25 | +_require_drivers quorum |
30 | + if (qmp_dispatcher_co_shutdown) { | 26 | |
31 | + return; | 27 | echo |
32 | + } | 28 | echo '### Create all images' # three source (quorum), one destination |
33 | + | ||
34 | while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) { | ||
35 | /* | ||
36 | * No more requests to process. Wait to be reentered from | ||
37 | -- | 29 | -- |
38 | 2.29.2 | 30 | 2.38.1 |
39 | 31 | ||
40 | 32 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Tests in the "auto" group should support qcow2 so that they can | 3 | In downstream RHEL builds, we do not have "blkverify" enabled, so |
4 | be run during "make check-block". Test 259 only supports "raw", so | 4 | iotest 262 is currently failing there. Thus let's list "blkverify" |
5 | it currently always gets skipped when running "make check-block". | 5 | as required item so that the test properly gets skipped instead if |
6 | Let's skip this unnecessary step and remove it from the auto group. | 6 | "blkverify" is missing. |
7 | 7 | ||
8 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 8 | Signed-off-by: Thomas Huth <thuth@redhat.com> |
9 | Message-Id: <20210215103835.1129145-1-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> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
11 | --- | 13 | --- |
12 | tests/qemu-iotests/259 | 2 +- | 14 | tests/qemu-iotests/262 | 3 ++- |
13 | 1 file changed, 1 insertion(+), 1 deletion(-) | 15 | 1 file changed, 2 insertions(+), 1 deletion(-) |
14 | 16 | ||
15 | diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259 | 17 | diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262 |
16 | index XXXXXXX..XXXXXXX 100755 | 18 | index XXXXXXX..XXXXXXX 100755 |
17 | --- a/tests/qemu-iotests/259 | 19 | --- a/tests/qemu-iotests/262 |
18 | +++ b/tests/qemu-iotests/259 | 20 | +++ b/tests/qemu-iotests/262 |
19 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ import iotests |
20 | #!/usr/bin/env bash | 22 | import os |
21 | -# group: rw auto quick | 23 | |
22 | +# group: rw quick | 24 | iotests.script_initialize(supported_fmts=['qcow2'], |
23 | # | 25 | - supported_platforms=['linux']) |
24 | # Test generic image creation fallback (by using NBD) | 26 | + supported_platforms=['linux'], |
25 | # | 27 | + required_fmts=['blkverify']) |
28 | |||
29 | with iotests.FilePath('img') as img_path, \ | ||
30 | iotests.FilePath('mig_fifo') as fifo, \ | ||
26 | -- | 31 | -- |
27 | 2.29.2 | 32 | 2.38.1 |
28 | 33 | ||
29 | 34 | diff view generated by jsdifflib |
1 | From: Michael Qiu <qiudayu@huayun.com> | 1 | From: Xiang Zheng <zhengxiang9@huawei.com> |
---|---|---|---|
2 | 2 | ||
3 | Currently, if guest has workloads, IO thread will acquire aio_context | 3 | Currently we fill the VIRT_FLASH memory space with two 64MB NOR images |
4 | lock before do io_submit, it leads to segmentfault when do block commit | 4 | when using persistent UEFI variables on virt board. Actually we only use |
5 | after snapshot. Just like below: | 5 | a very small(non-zero) part of the memory while the rest significant |
6 | large(zero) part of memory is wasted. | ||
6 | 7 | ||
7 | Program received signal SIGSEGV, Segmentation fault. | 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. | ||
8 | 11 | ||
9 | [Switching to Thread 0x7f7c7d91f700 (LWP 99907)] | 12 | Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com> |
10 | 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 | ||
11 | 1437 ../block/mirror.c: No such file or directory. | ||
12 | (gdb) p s->job | ||
13 | $17 = (MirrorBlockJob *) 0x0 | ||
14 | (gdb) p s->stop | ||
15 | $18 = false | ||
16 | 13 | ||
17 | Call trace of IO thread: | 14 | [ kraxel: rebased to latest master ] |
18 | 0 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 | ||
19 | 1 0x00005576d0f7f3ab in bdrv_driver_pwritev at ../block/io.c:1174 | ||
20 | 2 0x00005576d0f8139d in bdrv_aligned_pwritev at ../block/io.c:1988 | ||
21 | 3 0x00005576d0f81b65 in bdrv_co_pwritev_part at ../block/io.c:2156 | ||
22 | 4 0x00005576d0f8e6b7 in blk_do_pwritev_part at ../block/block-backend.c:1260 | ||
23 | 5 0x00005576d0f8e84d in blk_aio_write_entry at ../block/block-backend.c:1476 | ||
24 | ... | ||
25 | 15 | ||
26 | Switch to qemu main thread: | 16 | Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> |
27 | 0 0x00007f903be704ed in __lll_lock_wait at | 17 | Message-Id: <20221220084246.1984871-1-kraxel@redhat.com> |
28 | /lib/../lib64/libpthread.so.0 | 18 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> |
29 | 1 0x00007f903be6bde6 in _L_lock_941 at /lib/../lib64/libpthread.so.0 | 19 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> |
30 | 2 0x00007f903be6bcdf in pthread_mutex_lock at | ||
31 | /lib/../lib64/libpthread.so.0 | ||
32 | 3 0x0000564b21456889 in qemu_mutex_lock_impl at | ||
33 | ../util/qemu-thread-posix.c:79 | ||
34 | 4 0x0000564b213af8a5 in block_job_add_bdrv at ../blockjob.c:224 | ||
35 | 5 0x0000564b213b00ad in block_job_create at ../blockjob.c:440 | ||
36 | 6 0x0000564b21357c0a in mirror_start_job at ../block/mirror.c:1622 | ||
37 | 7 0x0000564b2135a9af in commit_active_start at ../block/mirror.c:1867 | ||
38 | 8 0x0000564b2133d132 in qmp_block_commit at ../blockdev.c:2768 | ||
39 | 9 0x0000564b2141fef3 in qmp_marshal_block_commit at | ||
40 | qapi/qapi-commands-block-core.c:346 | ||
41 | 10 0x0000564b214503c9 in do_qmp_dispatch_bh at | ||
42 | ../qapi/qmp-dispatch.c:110 | ||
43 | 11 0x0000564b21451996 in aio_bh_poll at ../util/async.c:164 | ||
44 | 12 0x0000564b2146018e in aio_dispatch at ../util/aio-posix.c:381 | ||
45 | 13 0x0000564b2145187e in aio_ctx_dispatch at ../util/async.c:306 | ||
46 | 14 0x00007f9040239049 in g_main_context_dispatch at | ||
47 | /lib/../lib64/libglib-2.0.so.0 | ||
48 | 15 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:232 | ||
49 | 16 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:255 | ||
50 | 17 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:531 | ||
51 | 18 0x0000564b212304e1 in qemu_main_loop at ../softmmu/runstate.c:721 | ||
52 | 19 0x0000564b20f7975e in main at ../softmmu/main.c:50 | ||
53 | |||
54 | In IO thread when do bdrv_mirror_top_pwritev, the job is NULL, and stop field | ||
55 | is false, this means the MirrorBDSOpaque "s" object has not been initialized | ||
56 | yet, and this object is initialized by block_job_create(), but the initialize | ||
57 | process is stuck in acquiring the lock. | ||
58 | |||
59 | In this situation, IO thread come to bdrv_mirror_top_pwritev(),which means that | ||
60 | mirror-top node is already inserted into block graph, but its bs->opaque->job | ||
61 | is not initialized. | ||
62 | |||
63 | The root cause is that qemu main thread do release/acquire when hold the lock, | ||
64 | at the same time, IO thread get the lock after release stage, and the crash | ||
65 | occured. | ||
66 | |||
67 | Actually, in this situation, job->job.aio_context will not equal to | ||
68 | qemu_get_aio_context(), and will be the same as bs->aio_context, | ||
69 | thus, no need to release the lock, becasue bdrv_root_attach_child() | ||
70 | will not change the context. | ||
71 | |||
72 | This patch fix this issue. | ||
73 | |||
74 | Fixes: 132ada80 "block: Adjust AioContexts when attaching nodes" | ||
75 | |||
76 | Signed-off-by: Michael Qiu <qiudayu@huayun.com> | ||
77 | Message-Id: <20210203024059.52683-1-08005325@163.com> | ||
78 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 20 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
79 | --- | 21 | --- |
80 | blockjob.c | 8 ++++++-- | 22 | hw/block/block.c | 36 +++++++++++++++++++++++++++++++++++- |
81 | 1 file changed, 6 insertions(+), 2 deletions(-) | 23 | 1 file changed, 35 insertions(+), 1 deletion(-) |
82 | 24 | ||
83 | diff --git a/blockjob.c b/blockjob.c | 25 | diff --git a/hw/block/block.c b/hw/block/block.c |
84 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
85 | --- a/blockjob.c | 27 | --- a/hw/block/block.c |
86 | +++ b/blockjob.c | 28 | +++ b/hw/block/block.c |
87 | @@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, | 29 | @@ -XXX,XX +XXX,XX @@ |
88 | uint64_t perm, uint64_t shared_perm, Error **errp) | 30 | #include "qapi/error.h" |
89 | { | 31 | #include "qapi/qapi-types-block.h" |
90 | BdrvChild *c; | 32 | |
91 | + bool need_context_ops; | 33 | +/* |
92 | 34 | + * Read the non-zeroes parts of @blk into @buf | |
93 | bdrv_ref(bs); | 35 | + * Reading all of the @blk is expensive if the zeroes parts of @blk |
94 | - if (job->job.aio_context != qemu_get_aio_context()) { | 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); | ||
95 | + | 46 | + |
96 | + need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context; | 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 | +} | ||
97 | + | 66 | + |
98 | + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { | 67 | /* |
99 | aio_context_release(job->job.aio_context); | 68 | * Read the entire contents of @blk into @buf. |
100 | } | 69 | * @blk's contents must be @size bytes, and @size must be at most |
101 | c = bdrv_root_attach_child(bs, name, &child_job, 0, | 70 | @@ -XXX,XX +XXX,XX @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, |
102 | job->job.aio_context, perm, shared_perm, job, | 71 | * block device and read only on demand. |
103 | errp); | 72 | */ |
104 | - if (job->job.aio_context != qemu_get_aio_context()) { | 73 | assert(size <= BDRV_REQUEST_MAX_BYTES); |
105 | + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { | 74 | - ret = blk_pread(blk, 0, size, buf, 0); |
106 | aio_context_acquire(job->job.aio_context); | 75 | + ret = blk_pread_nonzeroes(blk, size, buf); |
107 | } | 76 | if (ret < 0) { |
108 | if (c == NULL) { | 77 | error_setg_errno(errp, -ret, "can't read block backend"); |
78 | return false; | ||
109 | -- | 79 | -- |
110 | 2.29.2 | 80 | 2.38.1 |
111 | 81 | ||
112 | 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 |
New patch | |||
---|---|---|---|
1 | From: Paolo Bonzini <pbonzini@redhat.com> | ||
1 | 2 | ||
3 | qemu-io's do_co_pwrite_zeroes is reinventing the coroutine wrapper | ||
4 | blk_pwrite_zeroes. Just use the real thing directly. | ||
5 | |||
6 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | ||
7 | Message-Id: <20221215130225.476477-1-pbonzini@redhat.com> | ||
8 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | qemu-io-cmds.c | 57 +++++++++----------------------------------------- | ||
12 | 1 file changed, 10 insertions(+), 47 deletions(-) | ||
13 | |||
14 | diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/qemu-io-cmds.c | ||
17 | +++ b/qemu-io-cmds.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset, | ||
19 | return 1; | ||
20 | } | ||
21 | |||
22 | -typedef struct { | ||
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) | ||
50 | { | ||
51 | - Coroutine *co; | ||
52 | - CoWriteZeroes data = { | ||
53 | - .blk = blk, | ||
54 | - .offset = offset, | ||
55 | - .bytes = bytes, | ||
56 | - .total = total, | ||
57 | - .flags = flags, | ||
58 | - .done = false, | ||
59 | - }; | ||
60 | - | ||
61 | - co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data); | ||
62 | - bdrv_coroutine_enter(blk_bs(blk), co); | ||
63 | - while (!data.done) { | ||
64 | - aio_poll(blk_get_aio_context(blk), true); | ||
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; | ||
75 | } | ||
76 | + *total = bytes; | ||
77 | + return 1; | ||
78 | } | ||
79 | |||
80 | static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset, | ||
81 | @@ -XXX,XX +XXX,XX @@ static void write_help(void) | ||
82 | " -C, -- report statistics in a machine parsable format\n" | ||
83 | " -q, -- quiet mode, do not show I/O statistics\n" | ||
84 | " -u, -- with -z, allow unmapping\n" | ||
85 | -" -z, -- write zeroes using blk_co_pwrite_zeroes\n" | ||
86 | +" -z, -- write zeroes using blk_pwrite_zeroes\n" | ||
87 | "\n"); | ||
88 | } | ||
89 | |||
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 { | ||
99 | -- | ||
100 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Paolo Bonzini <pbonzini@redhat.com> | ||
1 | 2 | ||
3 | It has only one caller---inline it and remove the function. | ||
4 | |||
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> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | --- | ||
10 | include/block/block-io.h | 5 ----- | ||
11 | block.c | 6 ------ | ||
12 | block/block-backend.c | 2 +- | ||
13 | 3 files changed, 1 insertion(+), 12 deletions(-) | ||
14 | |||
15 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/include/block/block-io.h | ||
18 | +++ b/include/block/block-io.h | ||
19 | @@ -XXX,XX +XXX,XX @@ AioContext *coroutine_fn bdrv_co_enter(BlockDriverState *bs); | ||
20 | */ | ||
21 | void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx); | ||
22 | |||
23 | -/** | ||
24 | - * Transfer control to @co in the aio context of @bs | ||
25 | - */ | ||
26 | -void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co); | ||
27 | - | ||
28 | AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c); | ||
29 | |||
30 | void bdrv_io_plug(BlockDriverState *bs); | ||
31 | diff --git a/block.c b/block.c | ||
32 | index XXXXXXX..XXXXXXX 100644 | ||
33 | --- a/block.c | ||
34 | +++ b/block.c | ||
35 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_unlock(BlockDriverState *bs) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | -void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co) | ||
40 | -{ | ||
41 | - IO_CODE(); | ||
42 | - aio_co_enter(bdrv_get_aio_context(bs), co); | ||
43 | -} | ||
44 | - | ||
45 | static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban) | ||
46 | { | ||
47 | GLOBAL_STATE_CODE(); | ||
48 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/block/block-backend.c | ||
51 | +++ b/block/block-backend.c | ||
52 | @@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, | ||
53 | acb->has_returned = false; | ||
54 | |||
55 | co = qemu_coroutine_create(co_entry, acb); | ||
56 | - bdrv_coroutine_enter(blk_bs(blk), co); | ||
57 | + aio_co_enter(blk_get_aio_context(blk), co); | ||
58 | |||
59 | acb->has_returned = true; | ||
60 | if (acb->rwco.ret != NOT_DONE) { | ||
61 | -- | ||
62 | 2.38.1 | diff view generated by jsdifflib |
1 | From: Roger Pau Monne <roger.pau@citrix.com> | 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. | ||
2 | 6 | ||
3 | Linux blkfront expects both "discard-granularity" and | 7 | In practical terms, the offsets will be so high that we won't actually |
4 | "discard-alignment" present on xenbus in order to properly enable the | 8 | free any allocated clusters, but just run into an error, but in theory |
5 | feature, not exposing "discard-alignment" left some Linux blkfront | 9 | this can cause image corruption. |
6 | versions with a broken discard setup. This has also been addressed in | ||
7 | Linux with: | ||
8 | 10 | ||
9 | https://lore.kernel.org/lkml/20210118151528.81668-1-roger.pau@citrix.com/T/#u | 11 | Cc: qemu-stable@nongnu.org |
10 | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | |
11 | Fix QEMU to report a "discard-alignment" of 0, in order for it to work | 13 | Message-Id: <20230112191454.169353-2-kwolf@redhat.com> |
12 | with older Linux frontends. | 14 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> |
13 | 15 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | |
14 | Reported-by: Arthur Borsboom <arthurborsboom@gmail.com> | ||
15 | Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> | ||
16 | Message-Id: <20210118153330.82324-1-roger.pau@citrix.com> | ||
17 | Reviewed-by: Paul Durrant <paul@xen.org> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
19 | --- | 17 | --- |
20 | hw/block/xen-block.c | 1 + | 18 | block/qcow2-bitmap.c | 5 +++-- |
21 | 1 file changed, 1 insertion(+) | 19 | 1 file changed, 3 insertions(+), 2 deletions(-) |
22 | 20 | ||
23 | diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c | 21 | diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c |
24 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/hw/block/xen-block.c | 23 | --- a/block/qcow2-bitmap.c |
26 | +++ b/hw/block/xen-block.c | 24 | +++ b/block/qcow2-bitmap.c |
27 | @@ -XXX,XX +XXX,XX @@ static void xen_block_realize(XenDevice *xendev, Error **errp) | 25 | @@ -XXX,XX +XXX,XX @@ static int update_header_sync(BlockDriverState *bs) |
28 | xen_device_backend_printf(xendev, "feature-discard", "%u", 1); | 26 | return bdrv_flush(bs->file->bs); |
29 | xen_device_backend_printf(xendev, "discard-granularity", "%u", | 27 | } |
30 | conf->discard_granularity); | 28 | |
31 | + xen_device_backend_printf(xendev, "discard-alignment", "%u", 0); | 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; | ||
32 | } | 36 | } |
33 | 37 | ||
34 | xen_device_backend_printf(xendev, "feature-flush-cache", "%u", 1); | 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; | ||
35 | -- | 46 | -- |
36 | 2.29.2 | 47 | 2.38.1 |
37 | 48 | ||
38 | 49 | 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 commit' 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 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | Message-Id: <20230112191454.169353-3-kwolf@redhat.com> | ||
13 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | --- | ||
16 | qemu-img.c | 13 +++++++++++++ | ||
17 | 1 file changed, 13 insertions(+) | ||
18 | |||
19 | diff --git a/qemu-img.c b/qemu-img.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/qemu-img.c | ||
22 | +++ b/qemu-img.c | ||
23 | @@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open(bool image_opts, | ||
24 | blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet, | ||
25 | force_share); | ||
26 | } | ||
27 | + | ||
28 | + if (blk) { | ||
29 | + blk_set_force_allow_inactivate(blk); | ||
30 | + } | ||
31 | + | ||
32 | return blk; | ||
33 | } | ||
34 | |||
35 | @@ -XXX,XX +XXX,XX @@ unref_backing: | ||
36 | done: | ||
37 | qemu_progress_end(); | ||
38 | |||
39 | + /* | ||
40 | + * Manually inactivate the image first because this way we can know whether | ||
41 | + * an error occurred. blk_unref() doesn't tell us about failures. | ||
42 | + */ | ||
43 | + ret = bdrv_inactivate_all(); | ||
44 | + if (ret < 0 && !local_err) { | ||
45 | + error_setg_errno(&local_err, -ret, "Error while closing the image"); | ||
46 | + } | ||
47 | blk_unref(blk); | ||
48 | |||
49 | if (local_err) { | ||
50 | -- | ||
51 | 2.38.1 | diff view generated by jsdifflib |
1 | Commit 357bda95 already tried to fix the order in monitor_cleanup() by | 1 | blk_unref() can't report any errors that happen while closing the image. |
---|---|---|---|
2 | moving shutdown of the dispatcher coroutine further to the start. | 2 | For example, if qcow2 hits an -ENOSPC error while writing out dirty |
3 | However, it didn't go far enough: | 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. | ||
4 | 6 | ||
5 | iothread_stop() makes sure that all pending work (bottom halves) in the | 7 | In order to fix this, manually inactivate the image first before calling |
6 | AioContext of the monitor iothread is completed. iothread_destroy() | 8 | blk_unref(). This already performs the operations that would be most |
7 | depends on this and fails an assertion if there is still a pending BH. | 9 | likely to fail while closing the image, but it can still return errors. |
8 | 10 | ||
9 | While the dispatcher coroutine is running, it will try to resume the | 11 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1330 |
10 | monitor after taking a request out of the queue, which involves a BH. | ||
11 | The dispatcher is run until it terminates in the AIO_WAIT_WHILE() loop. | ||
12 | However, adding new BHs between iothread_stop() and iothread_destroy() | ||
13 | is forbidden. | ||
14 | |||
15 | Fix this by stopping the dispatcher first before shutting down the other | ||
16 | parts of the monitor. This means we can now receive requests that aren't | ||
17 | handled any more when QEMU is shutting down, but this is unlikely to be | ||
18 | a problem for QMP clients. | ||
19 | |||
20 | Fixes: 357bda9590784ff75803d52de43150d4107ed98e | ||
21 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
22 | Message-Id: <20210212172028.288825-2-kwolf@redhat.com> | 13 | Message-Id: <20230112191454.169353-4-kwolf@redhat.com> |
23 | Tested-by: Markus Armbruster <armbru@redhat.com> | 14 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> |
24 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | 15 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
26 | --- | 17 | --- |
27 | monitor/monitor.c | 25 +++++++++++++++---------- | 18 | qemu-img.c | 11 +++++++++++ |
28 | 1 file changed, 15 insertions(+), 10 deletions(-) | 19 | 1 file changed, 11 insertions(+) |
29 | 20 | ||
30 | diff --git a/monitor/monitor.c b/monitor/monitor.c | 21 | diff --git a/qemu-img.c b/qemu-img.c |
31 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/monitor/monitor.c | 23 | --- a/qemu-img.c |
33 | +++ b/monitor/monitor.c | 24 | +++ b/qemu-img.c |
34 | @@ -XXX,XX +XXX,XX @@ void monitor_data_destroy(Monitor *mon) | 25 | @@ -XXX,XX +XXX,XX @@ static int img_bitmap(int argc, char **argv) |
35 | 26 | QSIMPLEQ_HEAD(, ImgBitmapAction) actions; | |
36 | void monitor_cleanup(void) | 27 | ImgBitmapAction *act, *act_next; |
37 | { | 28 | const char *op; |
38 | - /* | 29 | + int inactivate_ret; |
39 | - * We need to explicitly stop the I/O thread (but not destroy it), | 30 | |
40 | - * clean up the monitor resources, then destroy the I/O thread since | 31 | QSIMPLEQ_INIT(&actions); |
41 | - * we need to unregister from chardev below in | 32 | |
42 | - * monitor_data_destroy(), and chardev is not thread-safe yet | 33 | @@ -XXX,XX +XXX,XX @@ static int img_bitmap(int argc, char **argv) |
43 | - */ | 34 | ret = 0; |
44 | - if (mon_iothread) { | 35 | |
45 | - iothread_stop(mon_iothread); | 36 | out: |
46 | - } | ||
47 | - | ||
48 | /* | ||
49 | * The dispatcher needs to stop before destroying the monitor and | ||
50 | * the I/O thread. | ||
51 | @@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void) | ||
52 | * eventually terminates. qemu_aio_context is automatically | ||
53 | * polled by calling AIO_WAIT_WHILE on it, but we must poll | ||
54 | * iohandler_ctx manually. | ||
55 | + * | ||
56 | + * Letting the iothread continue while shutting down the dispatcher | ||
57 | + * means that new requests may still be coming in. This is okay, | ||
58 | + * we'll just leave them in the queue without sending a response | ||
59 | + * and monitor_data_destroy() will free them. | ||
60 | */ | ||
61 | qmp_dispatcher_co_shutdown = true; | ||
62 | if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { | ||
63 | @@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void) | ||
64 | (aio_poll(iohandler_get_aio_context(), false), | ||
65 | qatomic_mb_read(&qmp_dispatcher_co_busy))); | ||
66 | |||
67 | + /* | 37 | + /* |
68 | + * We need to explicitly stop the I/O thread (but not destroy it), | 38 | + * Manually inactivate the images first because this way we can know whether |
69 | + * clean up the monitor resources, then destroy the I/O thread since | 39 | + * an error occurred. blk_unref() doesn't tell us about failures. |
70 | + * we need to unregister from chardev below in | ||
71 | + * monitor_data_destroy(), and chardev is not thread-safe yet | ||
72 | + */ | 40 | + */ |
73 | + if (mon_iothread) { | 41 | + inactivate_ret = bdrv_inactivate_all(); |
74 | + iothread_stop(mon_iothread); | 42 | + if (inactivate_ret < 0) { |
43 | + error_report("Error while closing the image: %s", strerror(-inactivate_ret)); | ||
44 | + ret = 1; | ||
75 | + } | 45 | + } |
76 | + | 46 | + |
77 | /* Flush output buffers and destroy monitors */ | 47 | blk_unref(src); |
78 | qemu_mutex_lock(&monitor_lock); | 48 | blk_unref(blk); |
79 | monitor_destroyed = true; | 49 | qemu_opts_del(opts); |
80 | -- | 50 | -- |
81 | 2.29.2 | 51 | 2.38.1 |
82 | 52 | ||
83 | 53 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | This tests that when an error happens while writing back bitmaps to the | ||
2 | image file in qcow2_inactivate(), 'qemu-img bitmap/commit' actually | ||
3 | return an error value in their exit code instead of making the operation | ||
4 | look successful to scripts. | ||
1 | 5 | ||
6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
7 | Message-Id: <20230112191454.169353-5-kwolf@redhat.com> | ||
8 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | .../qemu-iotests/tests/qemu-img-close-errors | 95 +++++++++++++++++++ | ||
12 | .../tests/qemu-img-close-errors.out | 23 +++++ | ||
13 | 2 files changed, 118 insertions(+) | ||
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 | ||
16 | |||
17 | diff --git a/tests/qemu-iotests/tests/qemu-img-close-errors b/tests/qemu-iotests/tests/qemu-img-close-errors | ||
18 | new file mode 100755 | ||
19 | index XXXXXXX..XXXXXXX | ||
20 | --- /dev/null | ||
21 | +++ b/tests/qemu-iotests/tests/qemu-img-close-errors | ||
22 | @@ -XXX,XX +XXX,XX @@ | ||
23 | +#!/usr/bin/env bash | ||
24 | +# group: rw auto quick | ||
25 | +# | ||
26 | +# Check that errors while closing the image, in particular writing back dirty | ||
27 | +# bitmaps, is correctly reported with a failing qemu-img exit code. | ||
28 | +# | ||
29 | +# Copyright (C) 2023 Red Hat, Inc. | ||
30 | +# | ||
31 | +# This program is free software; you can redistribute it and/or modify | ||
32 | +# it under the terms of the GNU General Public License as published by | ||
33 | +# the Free Software Foundation; either version 2 of the License, or | ||
34 | +# (at your option) any later version. | ||
35 | +# | ||
36 | +# This program is distributed in the hope that it will be useful, | ||
37 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
38 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
39 | +# GNU General Public License for more details. | ||
40 | +# | ||
41 | +# You should have received a copy of the GNU General Public License | ||
42 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
43 | +# | ||
44 | + | ||
45 | +# creator | ||
46 | +owner=kwolf@redhat.com | ||
47 | + | ||
48 | +seq="$(basename $0)" | ||
49 | +echo "QA output created by $seq" | ||
50 | + | ||
51 | +status=1 # failure is the default! | ||
52 | + | ||
53 | +_cleanup() | ||
54 | +{ | ||
55 | + _cleanup_test_img | ||
56 | +} | ||
57 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
58 | + | ||
59 | +# get standard environment, filters and checks | ||
60 | +cd .. | ||
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 | ||
147 | -- | ||
148 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
1 | 2 | ||
3 | Just omit the various 'return' when the return type is void. | ||
4 | |||
5 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
7 | Message-Id: <20230113204212.359076-2-kwolf@redhat.com> | ||
8 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | scripts/block-coroutine-wrapper.py | 20 +++++++++++++++----- | ||
12 | 1 file changed, 15 insertions(+), 5 deletions(-) | ||
13 | |||
14 | diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/scripts/block-coroutine-wrapper.py | ||
17 | +++ b/scripts/block-coroutine-wrapper.py | ||
18 | @@ -XXX,XX +XXX,XX @@ def __init__(self, return_type: str, name: str, args: str, | ||
19 | ctx = 'qemu_get_aio_context()' | ||
20 | self.ctx = ctx | ||
21 | |||
22 | + self.get_result = 's->ret = ' | ||
23 | + self.ret = 'return s.ret;' | ||
24 | + self.co_ret = 'return ' | ||
25 | + self.return_field = self.return_type + " ret;" | ||
26 | + if self.return_type == 'void': | ||
27 | + self.get_result = '' | ||
28 | + self.ret = '' | ||
29 | + self.co_ret = '' | ||
30 | + self.return_field = '' | ||
31 | + | ||
32 | def gen_list(self, format: str) -> str: | ||
33 | return ', '.join(format.format_map(arg.__dict__) for arg in self.args) | ||
34 | |||
35 | @@ -XXX,XX +XXX,XX @@ def create_mixed_wrapper(func: FuncDecl) -> str: | ||
36 | {{ | ||
37 | if (qemu_in_coroutine()) {{ | ||
38 | {graph_assume_lock} | ||
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 | |||
80 | -- | ||
81 | 2.38.1 | diff view generated by jsdifflib |
1 | From: Alexander Bulekov <alxndr@bu.edu> | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | cmd_fis is mapped as DMA_DIRECTION_FROM_DEVICE, however, it is read | 3 | BlockDriver->bdrv_io_plug is categorized as IO callback, and it |
4 | from, and not written to anywhere. Fix the DMA_DIRECTION and mark | 4 | currently doesn't run in a coroutine. We should let it take a graph |
5 | cmd_fis as read-only in the code. | 5 | rdlock since the callback traverses the block nodes graph, which however |
6 | is only possible in a coroutine. | ||
6 | 7 | ||
7 | Signed-off-by: Alexander Bulekov <alxndr@bu.edu> | 8 | The only caller of this function is blk_io_plug(), therefore make |
8 | Message-Id: <20210119164051.89268-1-alxndr@bu.edu> | 9 | blk_io_plug() a co_wrapper, so that we're always running in a coroutine |
10 | where the lock can be taken. | ||
11 | |||
12 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | Message-Id: <20230113204212.359076-3-kwolf@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 | hw/ide/ahci.c | 12 ++++++------ | 18 | include/block/block-io.h | 3 ++- |
12 | 1 file changed, 6 insertions(+), 6 deletions(-) | 19 | include/block/block_int-common.h | 2 +- |
20 | include/sysemu/block-backend-io.h | 4 +++- | ||
21 | block/block-backend.c | 4 ++-- | ||
22 | block/file-posix.c | 10 +++++----- | ||
23 | block/io.c | 8 ++++---- | ||
24 | block/nvme.c | 4 ++-- | ||
25 | 7 files changed, 19 insertions(+), 16 deletions(-) | ||
13 | 26 | ||
14 | diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c | 27 | diff --git a/include/block/block-io.h b/include/block/block-io.h |
15 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/hw/ide/ahci.c | 29 | --- a/include/block/block-io.h |
17 | +++ b/hw/ide/ahci.c | 30 | +++ b/include/block/block-io.h |
18 | @@ -XXX,XX +XXX,XX @@ static void ahci_reset_port(AHCIState *s, int port) | 31 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx); |
32 | |||
33 | AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c); | ||
34 | |||
35 | -void bdrv_io_plug(BlockDriverState *bs); | ||
36 | +void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs); | ||
37 | + | ||
38 | void bdrv_io_unplug(BlockDriverState *bs); | ||
39 | |||
40 | bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, | ||
41 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
42 | index XXXXXXX..XXXXXXX 100644 | ||
43 | --- a/include/block/block_int-common.h | ||
44 | +++ b/include/block/block_int-common.h | ||
45 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
46 | void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event); | ||
47 | |||
48 | /* io queue for linux-aio */ | ||
49 | - void (*bdrv_io_plug)(BlockDriverState *bs); | ||
50 | + void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs); | ||
51 | void (*bdrv_io_unplug)(BlockDriverState *bs); | ||
52 | |||
53 | /** | ||
54 | diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/include/sysemu/block-backend-io.h | ||
57 | +++ b/include/sysemu/block-backend-io.h | ||
58 | @@ -XXX,XX +XXX,XX @@ void blk_iostatus_set_err(BlockBackend *blk, int error); | ||
59 | int blk_get_max_iov(BlockBackend *blk); | ||
60 | int blk_get_max_hw_iov(BlockBackend *blk); | ||
61 | |||
62 | -void blk_io_plug(BlockBackend *blk); | ||
63 | +void coroutine_fn blk_co_io_plug(BlockBackend *blk); | ||
64 | +void co_wrapper blk_io_plug(BlockBackend *blk); | ||
65 | + | ||
66 | void blk_io_unplug(BlockBackend *blk); | ||
67 | AioContext *blk_get_aio_context(BlockBackend *blk); | ||
68 | BlockAcctStats *blk_get_stats(BlockBackend *blk); | ||
69 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
70 | index XXXXXXX..XXXXXXX 100644 | ||
71 | --- a/block/block-backend.c | ||
72 | +++ b/block/block-backend.c | ||
73 | @@ -XXX,XX +XXX,XX @@ void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify) | ||
74 | notifier_list_add(&blk->insert_bs_notifiers, notify); | ||
19 | } | 75 | } |
20 | 76 | ||
21 | /* Buffer pretty output based on a raw FIS structure. */ | 77 | -void blk_io_plug(BlockBackend *blk) |
22 | -static char *ahci_pretty_buffer_fis(uint8_t *fis, int cmd_len) | 78 | +void coroutine_fn blk_co_io_plug(BlockBackend *blk) |
23 | +static char *ahci_pretty_buffer_fis(const uint8_t *fis, int cmd_len) | ||
24 | { | 79 | { |
25 | int i; | 80 | BlockDriverState *bs = blk_bs(blk); |
26 | GString *s = g_string_new("FIS:"); | 81 | IO_CODE(); |
27 | @@ -XXX,XX +XXX,XX @@ static void execute_ncq_command(NCQTransferState *ncq_tfs) | 82 | |
83 | if (bs) { | ||
84 | - bdrv_io_plug(bs); | ||
85 | + bdrv_co_io_plug(bs); | ||
86 | } | ||
28 | } | 87 | } |
29 | 88 | ||
30 | 89 | diff --git a/block/file-posix.c b/block/file-posix.c | |
31 | -static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, | 90 | index XXXXXXX..XXXXXXX 100644 |
32 | +static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, | 91 | --- a/block/file-posix.c |
33 | uint8_t slot) | 92 | +++ b/block/file-posix.c |
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); | ||
95 | } | ||
96 | |||
97 | -static void raw_aio_plug(BlockDriverState *bs) | ||
98 | +static void coroutine_fn raw_co_io_plug(BlockDriverState *bs) | ||
34 | { | 99 | { |
35 | AHCIDevice *ad = &s->dev[port]; | 100 | BDRVRawState __attribute__((unused)) *s = bs->opaque; |
36 | - NCQFrame *ncq_fis = (NCQFrame*)cmd_fis; | 101 | #ifdef CONFIG_LINUX_AIO |
37 | + const NCQFrame *ncq_fis = (NCQFrame *)cmd_fis; | 102 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = { |
38 | uint8_t tag = ncq_fis->tag >> 3; | 103 | .bdrv_co_copy_range_from = raw_co_copy_range_from, |
39 | NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag]; | 104 | .bdrv_co_copy_range_to = raw_co_copy_range_to, |
40 | size_t size; | 105 | .bdrv_refresh_limits = raw_refresh_limits, |
41 | @@ -XXX,XX +XXX,XX @@ static AHCICmdHdr *get_cmd_header(AHCIState *s, uint8_t port, uint8_t slot) | 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 | |||
138 | diff --git a/block/io.c b/block/io.c | ||
139 | index XXXXXXX..XXXXXXX 100644 | ||
140 | --- a/block/io.c | ||
141 | +++ b/block/io.c | ||
142 | @@ -XXX,XX +XXX,XX @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size) | ||
143 | return mem; | ||
42 | } | 144 | } |
43 | 145 | ||
44 | static void handle_reg_h2d_fis(AHCIState *s, int port, | 146 | -void bdrv_io_plug(BlockDriverState *bs) |
45 | - uint8_t slot, uint8_t *cmd_fis) | 147 | +void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs) |
46 | + uint8_t slot, const uint8_t *cmd_fis) | ||
47 | { | 148 | { |
48 | IDEState *ide_state = &s->dev[port].port.ifs[0]; | 149 | BdrvChild *child; |
49 | AHCICmdHdr *cmd = get_cmd_header(s, port, slot); | 150 | IO_CODE(); |
50 | @@ -XXX,XX +XXX,XX @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) | 151 | |
51 | tbl_addr = le64_to_cpu(cmd->tbl_addr); | 152 | QLIST_FOREACH(child, &bs->children, next) { |
52 | cmd_len = 0x80; | 153 | - bdrv_io_plug(child->bs); |
53 | cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len, | 154 | + bdrv_co_io_plug(child->bs); |
54 | - DMA_DIRECTION_FROM_DEVICE); | ||
55 | + DMA_DIRECTION_TO_DEVICE); | ||
56 | if (!cmd_fis) { | ||
57 | trace_handle_cmd_badfis(s, port); | ||
58 | return -1; | ||
59 | @@ -XXX,XX +XXX,XX @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) | ||
60 | } | 155 | } |
61 | 156 | ||
62 | out: | 157 | if (qatomic_fetch_inc(&bs->io_plugged) == 0) { |
63 | - dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE, | 158 | BlockDriver *drv = bs->drv; |
64 | + dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_TO_DEVICE, | 159 | - if (drv && drv->bdrv_io_plug) { |
65 | cmd_len); | 160 | - drv->bdrv_io_plug(bs); |
66 | 161 | + if (drv && drv->bdrv_co_io_plug) { | |
67 | if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { | 162 | + drv->bdrv_co_io_plug(bs); |
163 | } | ||
164 | } | ||
165 | } | ||
166 | diff --git a/block/nvme.c b/block/nvme.c | ||
167 | index XXXXXXX..XXXXXXX 100644 | ||
168 | --- a/block/nvme.c | ||
169 | +++ b/block/nvme.c | ||
170 | @@ -XXX,XX +XXX,XX @@ static void nvme_attach_aio_context(BlockDriverState *bs, | ||
171 | } | ||
172 | } | ||
173 | |||
174 | -static void nvme_aio_plug(BlockDriverState *bs) | ||
175 | +static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs) | ||
176 | { | ||
177 | BDRVNVMeState *s = bs->opaque; | ||
178 | assert(!s->plugged); | ||
179 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = { | ||
180 | .bdrv_detach_aio_context = nvme_detach_aio_context, | ||
181 | .bdrv_attach_aio_context = nvme_attach_aio_context, | ||
182 | |||
183 | - .bdrv_io_plug = nvme_aio_plug, | ||
184 | + .bdrv_co_io_plug = nvme_co_io_plug, | ||
185 | .bdrv_io_unplug = nvme_aio_unplug, | ||
186 | |||
187 | .bdrv_register_buf = nvme_register_buf, | ||
68 | -- | 188 | -- |
69 | 2.29.2 | 189 | 2.38.1 |
70 | |||
71 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | |
2 | |||
3 | BlockDriver->bdrv_io_unplug 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 | 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> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | Message-Id: <20230113204212.359076-4-kwolf@redhat.com> | ||
15 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
17 | --- | ||
18 | include/block/block-io.h | 3 +-- | ||
19 | include/block/block_int-common.h | 2 +- | ||
20 | include/sysemu/block-backend-io.h | 4 +++- | ||
21 | block/blkio.c | 4 ++-- | ||
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(-) | ||
27 | |||
28 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/include/block/block-io.h | ||
31 | +++ b/include/block/block-io.h | ||
32 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx); | ||
33 | AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c); | ||
34 | |||
35 | void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs); | ||
36 | - | ||
37 | -void bdrv_io_unplug(BlockDriverState *bs); | ||
38 | +void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs); | ||
39 | |||
40 | bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, | ||
41 | const char *name, | ||
42 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
43 | index XXXXXXX..XXXXXXX 100644 | ||
44 | --- a/include/block/block_int-common.h | ||
45 | +++ b/include/block/block_int-common.h | ||
46 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
47 | |||
48 | /* io queue for linux-aio */ | ||
49 | void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs); | ||
50 | - void (*bdrv_io_unplug)(BlockDriverState *bs); | ||
51 | + void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs); | ||
52 | |||
53 | /** | ||
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, \ | ||
92 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
93 | index XXXXXXX..XXXXXXX 100644 | ||
94 | --- a/block/block-backend.c | ||
95 | +++ b/block/block-backend.c | ||
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) | ||
102 | { | ||
103 | BlockDriverState *bs = blk_bs(blk); | ||
104 | IO_CODE(); | ||
105 | |||
106 | if (bs) { | ||
107 | - bdrv_io_unplug(bs); | ||
108 | + bdrv_co_io_unplug(bs); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
113 | index XXXXXXX..XXXXXXX 100644 | ||
114 | --- a/block/file-posix.c | ||
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, | ||
161 | diff --git a/block/io.c b/block/io.c | ||
162 | index XXXXXXX..XXXXXXX 100644 | ||
163 | --- a/block/io.c | ||
164 | +++ b/block/io.c | ||
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) | ||
171 | { | ||
172 | BdrvChild *child; | ||
173 | IO_CODE(); | ||
174 | @@ -XXX,XX +XXX,XX @@ void bdrv_io_unplug(BlockDriverState *bs) | ||
175 | assert(bs->io_plugged); | ||
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, | ||
213 | -- | ||
214 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | |
2 | |||
3 | bdrv_is_inserted() 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. | ||
10 | |||
11 | At the same time, add also blk_is_inserted as co_wrapper_mixed, since it | ||
12 | is called in both coroutine and non-coroutine contexts. | ||
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. | ||
20 | |||
21 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
22 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
23 | Message-Id: <20230113204212.359076-5-kwolf@redhat.com> | ||
24 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
26 | --- | ||
27 | include/block/block-io.h | 5 ++++- | ||
28 | include/block/block_int-common.h | 2 +- | ||
29 | include/sysemu/block-backend-io.h | 5 ++++- | ||
30 | block.c | 8 ++++---- | ||
31 | block/block-backend.c | 4 ++-- | ||
32 | block/file-posix.c | 8 ++++---- | ||
33 | block/io.c | 12 ++++++------ | ||
34 | blockdev.c | 8 +++++++- | ||
35 | 8 files changed, 32 insertions(+), 20 deletions(-) | ||
36 | |||
37 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/include/block/block-io.h | ||
40 | +++ b/include/block/block-io.h | ||
41 | @@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs); | ||
42 | bool bdrv_is_writable(BlockDriverState *bs); | ||
43 | bool bdrv_is_sg(BlockDriverState *bs); | ||
44 | int bdrv_get_flags(BlockDriverState *bs); | ||
45 | -bool bdrv_is_inserted(BlockDriverState *bs); | ||
46 | + | ||
47 | +bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs); | ||
48 | +bool co_wrapper bdrv_is_inserted(BlockDriverState *bs); | ||
49 | + | ||
50 | void bdrv_lock_medium(BlockDriverState *bs, bool locked); | ||
51 | void bdrv_eject(BlockDriverState *bs, bool eject_flag); | ||
52 | const char *bdrv_get_format_name(BlockDriverState *bs); | ||
53 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/include/block/block_int-common.h | ||
56 | +++ b/include/block/block_int-common.h | ||
57 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
58 | BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); | ||
59 | |||
60 | /* removable device specific */ | ||
61 | - bool (*bdrv_is_inserted)(BlockDriverState *bs); | ||
62 | + bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs); | ||
63 | void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag); | ||
64 | void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); | ||
65 | |||
66 | diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h | ||
67 | index XXXXXXX..XXXXXXX 100644 | ||
68 | --- a/include/sysemu/block-backend-io.h | ||
69 | +++ b/include/sysemu/block-backend-io.h | ||
70 | @@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, | ||
71 | |||
72 | void blk_inc_in_flight(BlockBackend *blk); | ||
73 | void blk_dec_in_flight(BlockBackend *blk); | ||
74 | -bool blk_is_inserted(BlockBackend *blk); | ||
75 | + | ||
76 | +bool coroutine_fn blk_co_is_inserted(BlockBackend *blk); | ||
77 | +bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk); | ||
78 | + | ||
79 | bool blk_is_available(BlockBackend *blk); | ||
80 | void blk_lock_medium(BlockBackend *blk, bool locked); | ||
81 | void blk_eject(BlockBackend *blk, bool eject_flag); | ||
82 | diff --git a/block.c b/block.c | ||
83 | index XXXXXXX..XXXXXXX 100644 | ||
84 | --- a/block.c | ||
85 | +++ b/block.c | ||
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 | { | ||
93 | BlockDriver *drv = bs->drv; | ||
94 | BdrvChild *child; | ||
95 | @@ -XXX,XX +XXX,XX @@ bool bdrv_is_inserted(BlockDriverState *bs) | ||
96 | if (!drv) { | ||
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 | } | ||
110 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
111 | index XXXXXXX..XXXXXXX 100644 | ||
112 | --- a/block/block-backend.c | ||
113 | +++ b/block/block-backend.c | ||
114 | @@ -XXX,XX +XXX,XX @@ void blk_activate(BlockBackend *blk, Error **errp) | ||
115 | bdrv_activate(bs, errp); | ||
116 | } | ||
117 | |||
118 | -bool blk_is_inserted(BlockBackend *blk) | ||
119 | +bool coroutine_fn blk_co_is_inserted(BlockBackend *blk) | ||
120 | { | ||
121 | BlockDriverState *bs = blk_bs(blk); | ||
122 | IO_CODE(); | ||
123 | |||
124 | - return bs && bdrv_is_inserted(bs); | ||
125 | + return bs && bdrv_co_is_inserted(bs); | ||
126 | } | ||
127 | |||
128 | bool blk_is_available(BlockBackend *blk) | ||
129 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
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; | ||
202 | IO_CODE(); | ||
203 | |||
204 | - if (!bs || !bs->drv || !bdrv_is_inserted(bs)) { | ||
205 | + if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) { | ||
206 | return -ENOMEDIUM; | ||
207 | } | ||
208 | |||
209 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal( | ||
210 | assert(!(read_flags & BDRV_REQ_NO_WAIT)); | ||
211 | assert(!(write_flags & BDRV_REQ_NO_WAIT)); | ||
212 | |||
213 | - if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) { | ||
214 | + if (!dst || !dst->bs || !bdrv_co_is_inserted(dst->bs)) { | ||
215 | return -ENOMEDIUM; | ||
216 | } | ||
217 | ret = bdrv_check_request32(dst_offset, bytes, NULL, 0); | ||
218 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal( | ||
219 | return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags); | ||
220 | } | ||
221 | |||
222 | - if (!src || !src->bs || !bdrv_is_inserted(src->bs)) { | ||
223 | + if (!src || !src->bs || !bdrv_co_is_inserted(src->bs)) { | ||
224 | return -ENOMEDIUM; | ||
225 | } | ||
226 | ret = bdrv_check_request32(src_offset, bytes, NULL, 0); | ||
227 | diff --git a/blockdev.c b/blockdev.c | ||
228 | index XXXXXXX..XXXXXXX 100644 | ||
229 | --- a/blockdev.c | ||
230 | +++ b/blockdev.c | ||
231 | @@ -XXX,XX +XXX,XX @@ fail: | ||
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 | |||
257 | -- | ||
258 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
1 | 2 | ||
3 | The name is not good, not the least because we are going to convert this | ||
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. | ||
8 | |||
9 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | Message-Id: <20230113204212.359076-6-kwolf@redhat.com> | ||
12 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | --- | ||
15 | include/block/block_int-io.h | 2 +- | ||
16 | block.c | 8 ++++---- | ||
17 | block/io.c | 8 +++++--- | ||
18 | 3 files changed, 10 insertions(+), 8 deletions(-) | ||
19 | |||
20 | diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/include/block/block_int-io.h | ||
23 | +++ b/include/block/block_int-io.h | ||
24 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, | ||
25 | BdrvRequestFlags read_flags, | ||
26 | BdrvRequestFlags write_flags); | ||
27 | |||
28 | -int refresh_total_sectors(BlockDriverState *bs, int64_t hint); | ||
29 | +int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint); | ||
30 | |||
31 | BdrvChild *bdrv_cow_child(BlockDriverState *bs); | ||
32 | BdrvChild *bdrv_filter_child(BlockDriverState *bs); | ||
33 | diff --git a/block.c b/block.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/block.c | ||
36 | +++ b/block.c | ||
37 | @@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename, | ||
38 | * Set the current 'total_sectors' value | ||
39 | * Return 0 on success, -errno on error. | ||
40 | */ | ||
41 | -int refresh_total_sectors(BlockDriverState *bs, int64_t hint) | ||
42 | +int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint) | ||
43 | { | ||
44 | BlockDriver *drv = bs->drv; | ||
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"); | ||
73 | diff --git a/block/io.c b/block/io.c | ||
74 | index XXXXXXX..XXXXXXX 100644 | ||
75 | --- a/block/io.c | ||
76 | +++ b/block/io.c | ||
77 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | - ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); | ||
82 | + ret = bdrv_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); | ||
83 | if (ret < 0) { | ||
84 | error_setg_errno(errp, -ret, "Could not refresh total sector count"); | ||
85 | } else { | ||
86 | offset = bs->total_sectors * BDRV_SECTOR_SIZE; | ||
87 | } | ||
88 | - /* It's possible that truncation succeeded but refresh_total_sectors | ||
89 | + /* | ||
90 | + * It's possible that truncation succeeded but bdrv_refresh_total_sectors | ||
91 | * failed, but the latter doesn't affect how we should finish the request. | ||
92 | - * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */ | ||
93 | + * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. | ||
94 | + */ | ||
95 | bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0); | ||
96 | |||
97 | out: | ||
98 | -- | ||
99 | 2.38.1 | diff view generated by jsdifflib |
1 | From: Maxim Levitsky <mlevitsk@redhat.com> | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | This function wraps bdrv_co_delete_file for the common case of removing a file, | 3 | BlockDriver->bdrv_getlength is categorized as IO callback, and it |
4 | which was just created by format driver, on an error condition. | 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 | It hides the -ENOTSUPP error, and reports all other errors otherwise. | 8 | Therefore turn it into a co_wrapper to move the actual function into a |
9 | coroutine where the lock can be taken. | ||
7 | 10 | ||
8 | Use it in luks driver | 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. | ||
9 | 15 | ||
10 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | 16 | This is especially messy when a co_wrapper creates a coroutine and polls |
11 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 17 | in bdrv_open_driver, because this function has so many callers in so |
12 | Message-Id: <20201217170904.946013-3-mlevitsk@redhat.com> | 18 | many context that it can easily lead to deadlocks. Therefore the new |
13 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 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> | ||
29 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
30 | Message-Id: <20230113204212.359076-7-kwolf@redhat.com> | ||
31 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 32 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
15 | --- | 33 | --- |
16 | include/block/block.h | 1 + | 34 | include/block/block-io.h | 8 ++++-- |
17 | block.c | 22 ++++++++++++++++++++++ | 35 | include/block/block_int-common.h | 2 +- |
18 | block/crypto.c | 15 ++------------- | 36 | include/block/block_int-io.h | 5 +++- |
19 | 3 files changed, 25 insertions(+), 13 deletions(-) | 37 | include/sysemu/block-backend-io.h | 10 ++++++-- |
38 | block.c | 32 +++++++++++++++++------ | ||
39 | block/blkdebug.c | 6 ++--- | ||
40 | block/blkio.c | 6 ++--- | ||
41 | block/blklogwrites.c | 6 ++--- | ||
42 | block/blkreplay.c | 6 ++--- | ||
43 | block/blkverify.c | 6 ++--- | ||
44 | block/block-backend.c | 10 +++++--- | ||
45 | block/commit.c | 4 +-- | ||
46 | block/copy-on-read.c | 6 ++--- | ||
47 | block/crypto.c | 6 ++--- | ||
48 | block/curl.c | 10 ++++---- | ||
49 | block/file-posix.c | 42 +++++++++++++++---------------- | ||
50 | block/file-win32.c | 8 +++--- | ||
51 | block/filter-compress.c | 6 ++--- | ||
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(-) | ||
20 | 70 | ||
21 | diff --git a/include/block/block.h b/include/block/block.h | 71 | diff --git a/include/block/block-io.h b/include/block/block-io.h |
22 | index XXXXXXX..XXXXXXX 100644 | 72 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/include/block/block.h | 73 | --- a/include/block/block-io.h |
24 | +++ b/include/block/block.h | 74 | +++ b/include/block/block-io.h |
25 | @@ -XXX,XX +XXX,XX @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, | 75 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, |
26 | Error **errp); | 76 | PreallocMode prealloc, BdrvRequestFlags flags, |
27 | void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); | 77 | Error **errp); |
28 | int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); | 78 | |
29 | +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs); | 79 | -int64_t bdrv_nb_sectors(BlockDriverState *bs); |
30 | 80 | -int64_t bdrv_getlength(BlockDriverState *bs); | |
31 | 81 | +int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs); | |
32 | typedef struct BdrvCheckResult { | 82 | +int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs); |
83 | + | ||
84 | +int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs); | ||
85 | +int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs); | ||
86 | + | ||
87 | int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); | ||
88 | BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, | ||
89 | BlockDriverState *in_bs, Error **errp); | ||
90 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
91 | index XXXXXXX..XXXXXXX 100644 | ||
92 | --- a/include/block/block_int-common.h | ||
93 | +++ b/include/block/block_int-common.h | ||
94 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
95 | int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset, | ||
96 | bool exact, PreallocMode prealloc, | ||
97 | BdrvRequestFlags flags, Error **errp); | ||
98 | - int64_t (*bdrv_getlength)(BlockDriverState *bs); | ||
99 | + int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs); | ||
100 | int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs); | ||
101 | BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs, | ||
102 | Error **errp); | ||
103 | diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h | ||
104 | index XXXXXXX..XXXXXXX 100644 | ||
105 | --- a/include/block/block_int-io.h | ||
106 | +++ b/include/block/block_int-io.h | ||
107 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset, | ||
108 | BdrvRequestFlags read_flags, | ||
109 | BdrvRequestFlags write_flags); | ||
110 | |||
111 | -int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint); | ||
112 | +int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs, | ||
113 | + int64_t hint); | ||
114 | +int co_wrapper_mixed | ||
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); | ||
128 | + | ||
129 | +int64_t coroutine_fn blk_co_getlength(BlockBackend *blk); | ||
130 | +int64_t co_wrapper_mixed blk_getlength(BlockBackend *blk); | ||
131 | + | ||
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); | ||
33 | diff --git a/block.c b/block.c | 141 | diff --git a/block.c b/block.c |
34 | index XXXXXXX..XXXXXXX 100644 | 142 | index XXXXXXX..XXXXXXX 100644 |
35 | --- a/block.c | 143 | --- a/block.c |
36 | +++ b/block.c | 144 | +++ b/block.c |
37 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) | 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) | ||
152 | { | ||
153 | BlockDriver *drv = bs->drv; | ||
154 | IO_CODE(); | ||
155 | @@ -XXX,XX +XXX,XX @@ int bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint) | ||
156 | return -ENOMEDIUM; | ||
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) | ||
213 | { | ||
214 | BlockDriver *drv = bs->drv; | ||
215 | IO_CODE(); | ||
216 | @@ -XXX,XX +XXX,XX @@ int64_t bdrv_nb_sectors(BlockDriverState *bs) | ||
217 | return -ENOMEDIUM; | ||
218 | |||
219 | if (drv->has_variable_length) { | ||
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; | ||
234 | IO_CODE(); | ||
235 | |||
236 | + ret = bdrv_co_nb_sectors(bs); | ||
237 | if (ret < 0) { | ||
238 | return ret; | ||
239 | } | ||
240 | diff --git a/block/blkdebug.c b/block/blkdebug.c | ||
241 | index XXXXXXX..XXXXXXX 100644 | ||
242 | --- a/block/blkdebug.c | ||
243 | +++ b/block/blkdebug.c | ||
244 | @@ -XXX,XX +XXX,XX @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag) | ||
245 | return false; | ||
246 | } | ||
247 | |||
248 | -static int64_t blkdebug_getlength(BlockDriverState *bs) | ||
249 | +static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs) | ||
250 | { | ||
251 | - return bdrv_getlength(bs->file->bs); | ||
252 | + return bdrv_co_getlength(bs->file->bs); | ||
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, \ | ||
296 | diff --git a/block/blklogwrites.c b/block/blklogwrites.c | ||
297 | index XXXXXXX..XXXXXXX 100644 | ||
298 | --- a/block/blklogwrites.c | ||
299 | +++ b/block/blklogwrites.c | ||
300 | @@ -XXX,XX +XXX,XX @@ static void blk_log_writes_close(BlockDriverState *bs) | ||
301 | s->log_file = NULL; | ||
302 | } | ||
303 | |||
304 | -static int64_t blk_log_writes_getlength(BlockDriverState *bs) | ||
305 | +static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs) | ||
306 | { | ||
307 | - return bdrv_getlength(bs->file->bs); | ||
308 | + return bdrv_co_getlength(bs->file->bs); | ||
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 | |||
321 | diff --git a/block/blkreplay.c b/block/blkreplay.c | ||
322 | index XXXXXXX..XXXXXXX 100644 | ||
323 | --- a/block/blkreplay.c | ||
324 | +++ b/block/blkreplay.c | ||
325 | @@ -XXX,XX +XXX,XX @@ fail: | ||
38 | return ret; | 326 | return ret; |
39 | } | 327 | } |
40 | 328 | ||
41 | +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs) | 329 | -static int64_t blkreplay_getlength(BlockDriverState *bs) |
42 | +{ | 330 | +static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs) |
43 | + Error *local_err = NULL; | 331 | { |
44 | + int ret; | 332 | - return bdrv_getlength(bs->file->bs); |
333 | + return bdrv_co_getlength(bs->file->bs); | ||
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, | ||
346 | diff --git a/block/blkverify.c b/block/blkverify.c | ||
347 | index XXXXXXX..XXXXXXX 100644 | ||
348 | --- a/block/blkverify.c | ||
349 | +++ b/block/blkverify.c | ||
350 | @@ -XXX,XX +XXX,XX @@ static void blkverify_close(BlockDriverState *bs) | ||
351 | s->test_file = NULL; | ||
352 | } | ||
353 | |||
354 | -static int64_t blkverify_getlength(BlockDriverState *bs) | ||
355 | +static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs) | ||
356 | { | ||
357 | BDRVBlkverifyState *s = bs->opaque; | ||
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(); | ||
45 | + | 385 | + |
46 | + if (!bs) { | 386 | if (!blk_is_available(blk)) { |
47 | + return; | 387 | return -ENOMEDIUM; |
48 | + } | 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(); | ||
49 | + | 403 | + |
50 | + ret = bdrv_co_delete_file(bs, &local_err); | 404 | if (!blk_is_available(blk)) { |
51 | + /* | 405 | return -ENOMEDIUM; |
52 | + * ENOTSUP will happen if the block driver doesn't support | 406 | } |
53 | + * the 'bdrv_co_delete_file' interface. This is a predictable | 407 | |
54 | + * scenario and shouldn't be reported back to the user. | 408 | - return bdrv_nb_sectors(blk_bs(blk)); |
55 | + */ | 409 | + return bdrv_co_nb_sectors(blk_bs(blk)); |
56 | + if (ret == -ENOTSUP) { | 410 | } |
57 | + error_free(local_err); | 411 | |
58 | + } else if (ret < 0) { | 412 | BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, |
59 | + error_report_err(local_err); | 413 | diff --git a/block/commit.c b/block/commit.c |
60 | + } | 414 | index XXXXXXX..XXXXXXX 100644 |
61 | +} | 415 | --- a/block/commit.c |
62 | + | 416 | +++ b/block/commit.c |
63 | /** | 417 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp) |
64 | * Try to get @bs's logical and physical block size. | 418 | QEMU_AUTO_VFREE void *buf = NULL; |
65 | * On success, store them in @bsz struct and return 0. | 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 | } | ||
433 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | ||
434 | index XXXXXXX..XXXXXXX 100644 | ||
435 | --- a/block/copy-on-read.c | ||
436 | +++ b/block/copy-on-read.c | ||
437 | @@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, | ||
438 | } | ||
439 | |||
440 | |||
441 | -static int64_t cor_getlength(BlockDriverState *bs) | ||
442 | +static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs) | ||
443 | { | ||
444 | - return bdrv_getlength(bs->file->bs); | ||
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, | ||
66 | diff --git a/block/crypto.c b/block/crypto.c | 458 | diff --git a/block/crypto.c b/block/crypto.c |
67 | index XXXXXXX..XXXXXXX 100644 | 459 | index XXXXXXX..XXXXXXX 100644 |
68 | --- a/block/crypto.c | 460 | --- a/block/crypto.c |
69 | +++ b/block/crypto.c | 461 | +++ b/block/crypto.c |
462 | @@ -XXX,XX +XXX,XX @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp) | ||
463 | } | ||
464 | |||
465 | |||
466 | -static int64_t block_crypto_getlength(BlockDriverState *bs) | ||
467 | +static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs) | ||
468 | { | ||
469 | BlockCrypto *crypto = bs->opaque; | ||
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, | ||
717 | diff --git a/block/filter-compress.c b/block/filter-compress.c | ||
718 | index XXXXXXX..XXXXXXX 100644 | ||
719 | --- a/block/filter-compress.c | ||
720 | +++ b/block/filter-compress.c | ||
721 | @@ -XXX,XX +XXX,XX @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags, | ||
722 | } | ||
723 | |||
724 | |||
725 | -static int64_t compress_getlength(BlockDriverState *bs) | ||
726 | +static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs) | ||
727 | { | ||
728 | - return bdrv_getlength(bs->file->bs); | ||
729 | + return bdrv_co_getlength(bs->file->bs); | ||
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, | ||
842 | diff --git a/block/mirror.c b/block/mirror.c | ||
843 | index XXXXXXX..XXXXXXX 100644 | ||
844 | --- a/block/mirror.c | ||
845 | +++ b/block/mirror.c | ||
846 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp) | ||
847 | goto immediate_exit; | ||
848 | } | ||
849 | |||
850 | - s->bdev_length = bdrv_getlength(bs); | ||
851 | + s->bdev_length = bdrv_co_getlength(bs); | ||
852 | if (s->bdev_length < 0) { | ||
853 | ret = s->bdev_length; | ||
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 | ||
70 | @@ -XXX,XX +XXX,XX @@ fail: | 937 | @@ -XXX,XX +XXX,XX @@ fail: |
71 | * If an error occurred, delete 'filename'. Even if the file existed | 938 | return ret; |
72 | * beforehand, it has been truncated and corrupted in the process. | 939 | } |
73 | */ | 940 | |
74 | - if (ret && bs) { | 941 | -static int64_t nvme_getlength(BlockDriverState *bs) |
75 | - Error *local_delete_err = NULL; | 942 | +static int64_t coroutine_fn nvme_co_getlength(BlockDriverState *bs) |
76 | - int r_del = bdrv_co_delete_file(bs, &local_delete_err); | 943 | { |
77 | - /* | 944 | BDRVNVMeState *s = bs->opaque; |
78 | - * ENOTSUP will happen if the block driver doesn't support | 945 | return s->nsze << s->blkshift; |
79 | - * the 'bdrv_co_delete_file' interface. This is a predictable | 946 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn nvme_co_truncate(BlockDriverState *bs, int64_t offset, |
80 | - * scenario and shouldn't be reported back to the user. | 947 | return -ENOTSUP; |
81 | - */ | 948 | } |
82 | - if ((r_del < 0) && (r_del != -ENOTSUP)) { | 949 | |
83 | - error_report_err(local_delete_err); | 950 | - cur_length = nvme_getlength(bs); |
84 | - } else { | 951 | + cur_length = nvme_co_getlength(bs); |
85 | - error_free(local_delete_err); | 952 | if (offset != cur_length && exact) { |
86 | - } | 953 | error_setg(errp, "Cannot resize NVMe devices"); |
87 | + if (ret) { | 954 | return -ENOTSUP; |
88 | + bdrv_co_delete_file_noerr(bs); | 955 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = { |
89 | } | 956 | .bdrv_parse_filename = nvme_parse_filename, |
90 | 957 | .bdrv_file_open = nvme_file_open, | |
91 | bdrv_unref(bs); | 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 | |||
964 | diff --git a/block/preallocate.c b/block/preallocate.c | ||
965 | index XXXXXXX..XXXXXXX 100644 | ||
966 | --- a/block/preallocate.c | ||
967 | +++ b/block/preallocate.c | ||
968 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co_flush(BlockDriverState *bs) | ||
969 | return bdrv_co_flush(bs->file->bs); | ||
970 | } | ||
971 | |||
972 | -static int64_t preallocate_getlength(BlockDriverState *bs) | ||
973 | +static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs) | ||
974 | { | ||
975 | int64_t ret; | ||
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, | ||
1021 | diff --git a/block/quorum.c b/block/quorum.c | ||
1022 | index XXXXXXX..XXXXXXX 100644 | ||
1023 | --- a/block/quorum.c | ||
1024 | +++ b/block/quorum.c | ||
1025 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs, | ||
1026 | flags | BDRV_REQ_ZERO_WRITE); | ||
1027 | } | ||
1028 | |||
1029 | -static int64_t quorum_getlength(BlockDriverState *bs) | ||
1030 | +static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs) | ||
1031 | { | ||
1032 | BDRVQuorumState *s = bs->opaque; | ||
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, | ||
1057 | diff --git a/block/raw-format.c b/block/raw-format.c | ||
1058 | index XXXXXXX..XXXXXXX 100644 | ||
1059 | --- a/block/raw-format.c | ||
1060 | +++ b/block/raw-format.c | ||
1061 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs, | ||
1062 | return bdrv_co_pdiscard(bs->file, offset, bytes); | ||
1063 | } | ||
1064 | |||
1065 | -static int64_t raw_getlength(BlockDriverState *bs) | ||
1066 | +static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||
1067 | { | ||
1068 | int64_t len; | ||
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 | |||
1109 | diff --git a/block/replication.c b/block/replication.c | ||
1110 | index XXXXXXX..XXXXXXX 100644 | ||
1111 | --- a/block/replication.c | ||
1112 | +++ b/block/replication.c | ||
1113 | @@ -XXX,XX +XXX,XX @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, | ||
1114 | return; | ||
1115 | } | ||
1116 | |||
1117 | -static int64_t replication_getlength(BlockDriverState *bs) | ||
1118 | +static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs) | ||
1119 | { | ||
1120 | - return bdrv_getlength(bs->file->bs); | ||
1121 | + return bdrv_co_getlength(bs->file->bs); | ||
1122 | } | ||
1123 | |||
1124 | static int replication_get_io_status(BDRVReplicationState *s) | ||
1125 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_replication = { | ||
1126 | .bdrv_close = replication_close, | ||
1127 | .bdrv_child_perm = replication_child_perm, | ||
1128 | |||
1129 | - .bdrv_getlength = replication_getlength, | ||
1130 | + .bdrv_co_getlength = replication_co_getlength, | ||
1131 | .bdrv_co_readv = replication_co_readv, | ||
1132 | .bdrv_co_writev = replication_co_writev, | ||
1133 | |||
1134 | diff --git a/block/ssh.c b/block/ssh.c | ||
1135 | index XXXXXXX..XXXXXXX 100644 | ||
1136 | --- a/block/ssh.c | ||
1137 | +++ b/block/ssh.c | ||
1138 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs) | ||
1139 | return ret; | ||
1140 | } | ||
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, | ||
1156 | diff --git a/block/throttle.c b/block/throttle.c | ||
1157 | index XXXXXXX..XXXXXXX 100644 | ||
1158 | --- a/block/throttle.c | ||
1159 | +++ b/block/throttle.c | ||
1160 | @@ -XXX,XX +XXX,XX @@ static void throttle_close(BlockDriverState *bs) | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | -static int64_t throttle_getlength(BlockDriverState *bs) | ||
1165 | +static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs) | ||
1166 | { | ||
1167 | - return bdrv_getlength(bs->file->bs); | ||
1168 | + return bdrv_co_getlength(bs->file->bs); | ||
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' | ||
92 | -- | 1228 | -- |
93 | 2.29.2 | 1229 | 2.38.1 |
94 | |||
95 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
1 | 2 | ||
3 | The only difference is that blk_ checks if the block is available, | ||
4 | but this check is already performed above in blk_check_byte_request(). | ||
5 | |||
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 | |||
9 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | Message-Id: <20230113204212.359076-8-kwolf@redhat.com> | ||
12 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | --- | ||
15 | block/block-backend.c | 2 +- | ||
16 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
17 | |||
18 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/block-backend.c | ||
21 | +++ b/block/block-backend.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset, | ||
23 | } | ||
24 | |||
25 | if (!blk->allow_write_beyond_eof) { | ||
26 | - len = blk_getlength(blk); | ||
27 | + len = bdrv_getlength(blk_bs(blk)); | ||
28 | if (len < 0) { | ||
29 | return len; | ||
30 | } | ||
31 | -- | ||
32 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
1 | 2 | ||
3 | In some places we are sure we are always running in a | ||
4 | coroutine, therefore it's useless to call the generated_co_wrapper, | ||
5 | instead call directly the _co_ function. | ||
6 | |||
7 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Message-Id: <20230113204212.359076-9-kwolf@redhat.com> | ||
10 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | --- | ||
13 | block/block-backend.c | 6 +++--- | ||
14 | block/io.c | 4 ++-- | ||
15 | block/preallocate.c | 6 +++--- | ||
16 | block/qed.c | 2 +- | ||
17 | 4 files changed, 9 insertions(+), 9 deletions(-) | ||
18 | |||
19 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/block/block-backend.c | ||
22 | +++ b/block/block-backend.c | ||
23 | @@ -XXX,XX +XXX,XX @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable) | ||
24 | blk->disable_request_queuing = disable; | ||
25 | } | ||
26 | |||
27 | -static int blk_check_byte_request(BlockBackend *blk, int64_t offset, | ||
28 | - int64_t bytes) | ||
29 | +static coroutine_fn int blk_check_byte_request(BlockBackend *blk, | ||
30 | + int64_t offset, int64_t bytes) | ||
31 | { | ||
32 | int64_t len; | ||
33 | |||
34 | @@ -XXX,XX +XXX,XX @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset, | ||
35 | } | ||
36 | |||
37 | if (!blk->allow_write_beyond_eof) { | ||
38 | - len = bdrv_getlength(blk_bs(blk)); | ||
39 | + len = bdrv_co_getlength(blk_bs(blk)); | ||
40 | if (len < 0) { | ||
41 | return len; | ||
42 | } | ||
43 | diff --git a/block/io.c b/block/io.c | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/block/io.c | ||
46 | +++ b/block/io.c | ||
47 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, | ||
48 | if (new_bytes && backing) { | ||
49 | int64_t backing_len; | ||
50 | |||
51 | - backing_len = bdrv_getlength(backing->bs); | ||
52 | + backing_len = bdrv_co_getlength(backing->bs); | ||
53 | if (backing_len < 0) { | ||
54 | ret = backing_len; | ||
55 | error_setg_errno(errp, -ret, "Could not get backing file size"); | ||
56 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, | ||
57 | goto out; | ||
58 | } | ||
59 | |||
60 | - ret = bdrv_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); | ||
61 | + ret = bdrv_co_refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); | ||
62 | if (ret < 0) { | ||
63 | error_setg_errno(errp, -ret, "Could not refresh total sector count"); | ||
64 | } else { | ||
65 | diff --git a/block/preallocate.c b/block/preallocate.c | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/block/preallocate.c | ||
68 | +++ b/block/preallocate.c | ||
69 | @@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset, | ||
70 | } | ||
71 | |||
72 | if (s->data_end < 0) { | ||
73 | - s->data_end = bdrv_getlength(bs->file->bs); | ||
74 | + s->data_end = bdrv_co_getlength(bs->file->bs); | ||
75 | if (s->data_end < 0) { | ||
76 | return false; | ||
77 | } | ||
78 | @@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset, | ||
79 | } | ||
80 | |||
81 | if (s->file_end < 0) { | ||
82 | - s->file_end = bdrv_getlength(bs->file->bs); | ||
83 | + s->file_end = bdrv_co_getlength(bs->file->bs); | ||
84 | if (s->file_end < 0) { | ||
85 | return false; | ||
86 | } | ||
87 | @@ -XXX,XX +XXX,XX @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset, | ||
88 | |||
89 | if (s->data_end >= 0 && offset > s->data_end) { | ||
90 | if (s->file_end < 0) { | ||
91 | - s->file_end = bdrv_getlength(bs->file->bs); | ||
92 | + s->file_end = bdrv_co_getlength(bs->file->bs); | ||
93 | if (s->file_end < 0) { | ||
94 | error_setg(errp, "failed to get file length"); | ||
95 | return s->file_end; | ||
96 | diff --git a/block/qed.c b/block/qed.c | ||
97 | index XXXXXXX..XXXXXXX 100644 | ||
98 | --- a/block/qed.c | ||
99 | +++ b/block/qed.c | ||
100 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options, | ||
101 | } | ||
102 | |||
103 | /* Round down file size to the last cluster */ | ||
104 | - file_size = bdrv_getlength(bs->file->bs); | ||
105 | + file_size = bdrv_co_getlength(bs->file->bs); | ||
106 | if (file_size < 0) { | ||
107 | error_setg(errp, "Failed to get file length"); | ||
108 | return file_size; | ||
109 | -- | ||
110 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
1 | 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> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | Message-Id: <20230113204212.359076-10-kwolf@redhat.com> | ||
14 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
16 | --- | ||
17 | include/block/block-io.h | 4 +++- | ||
18 | include/block/block_int-common.h | 4 +++- | ||
19 | block.c | 12 ++++++------ | ||
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(-) | ||
28 | |||
29 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/include/block/block-io.h | ||
32 | +++ b/include/block/block-io.h | ||
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 | + | ||
41 | BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, | ||
42 | BlockDriverState *in_bs, Error **errp); | ||
43 | void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); | ||
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 | bool exact, PreallocMode prealloc, | ||
50 | BdrvRequestFlags flags, Error **errp); | ||
51 | int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs); | ||
52 | - int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs); | ||
53 | + int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)( | ||
54 | + BlockDriverState *bs); | ||
55 | + | ||
56 | BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs, | ||
57 | Error **errp); | ||
58 | |||
59 | diff --git a/block.c b/block.c | ||
60 | index XXXXXXX..XXXXXXX 100644 | ||
61 | --- a/block.c | ||
62 | +++ b/block.c | ||
63 | @@ -XXX,XX +XXX,XX @@ exit: | ||
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; | ||
89 | IO_CODE(); | ||
90 | @@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs) | ||
91 | if (!drv) { | ||
92 | return -ENOMEDIUM; | ||
93 | } | ||
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, | ||
355 | -- | ||
356 | 2.38.1 | diff view generated by jsdifflib |
1 | From: Maxim Levitsky <mlevitsk@redhat.com> | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | When the underlying block device doesn't support the | 3 | bdrv_get_info() is categorized as an I/O function, and it currently |
4 | bdrv_co_delete_file interface, an 'Error' object was leaked. | 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. | ||
5 | 7 | ||
6 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | 8 | Therefore turn it into a co_wrapper to move the actual function into a |
7 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 9 | coroutine where the lock can be taken. |
8 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 10 | |
9 | Message-Id: <20201217170904.946013-2-mlevitsk@redhat.com> | 11 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | Message-Id: <20230113204212.359076-11-kwolf@redhat.com> | ||
14 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
11 | --- | 16 | --- |
12 | block/crypto.c | 2 ++ | 17 | include/block/block-io.h | 5 ++++- |
13 | 1 file changed, 2 insertions(+) | 18 | include/block/block_int-common.h | 3 ++- |
19 | block.c | 8 ++++---- | ||
20 | block/blkio.c | 5 +++-- | ||
21 | block/crypto.c | 8 ++++---- | ||
22 | block/file-posix.c | 7 ++++--- | ||
23 | block/io.c | 8 ++++---- | ||
24 | block/iscsi.c | 7 ++++--- | ||
25 | block/mirror.c | 2 +- | ||
26 | block/qcow.c | 5 +++-- | ||
27 | block/qcow2.c | 5 +++-- | ||
28 | block/qed.c | 5 +++-- | ||
29 | block/raw-format.c | 7 ++++--- | ||
30 | block/rbd.c | 5 +++-- | ||
31 | block/vdi.c | 7 ++++--- | ||
32 | block/vhdx.c | 5 +++-- | ||
33 | block/vmdk.c | 5 +++-- | ||
34 | block/vpc.c | 5 +++-- | ||
35 | 18 files changed, 59 insertions(+), 43 deletions(-) | ||
14 | 36 | ||
37 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/include/block/block-io.h | ||
40 | +++ b/include/block/block-io.h | ||
41 | @@ -XXX,XX +XXX,XX @@ bool bdrv_supports_compressed_writes(BlockDriverState *bs); | ||
42 | const char *bdrv_get_node_name(const BlockDriverState *bs); | ||
43 | const char *bdrv_get_device_name(const BlockDriverState *bs); | ||
44 | const char *bdrv_get_device_or_node_name(const BlockDriverState *bs); | ||
45 | -int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); | ||
46 | + | ||
47 | +int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); | ||
48 | +int co_wrapper_mixed bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); | ||
49 | + | ||
50 | ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs, | ||
51 | Error **errp); | ||
52 | BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs); | ||
53 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/include/block/block_int-common.h | ||
56 | +++ b/include/block/block_int-common.h | ||
57 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
58 | int64_t offset, int64_t bytes, QEMUIOVector *qiov, | ||
59 | size_t qiov_offset); | ||
60 | |||
61 | - int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); | ||
62 | + int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs, | ||
63 | + BlockDriverInfo *bdi); | ||
64 | |||
65 | ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs, | ||
66 | Error **errp); | ||
67 | diff --git a/block.c b/block.c | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/block.c | ||
70 | +++ b/block.c | ||
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 | { | ||
78 | int ret; | ||
79 | BlockDriver *drv = bs->drv; | ||
80 | @@ -XXX,XX +XXX,XX @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
81 | if (!drv) { | ||
82 | return -ENOMEDIUM; | ||
83 | } | ||
84 | - if (!drv->bdrv_get_info) { | ||
85 | + if (!drv->bdrv_co_get_info) { | ||
86 | BlockDriverState *filtered = bdrv_filter_bs(bs); | ||
87 | if (filtered) { | ||
88 | - return bdrv_get_info(filtered, bdi); | ||
89 | + return bdrv_co_get_info(filtered, bdi); | ||
90 | } | ||
91 | return -ENOTSUP; | ||
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, \ | ||
15 | diff --git a/block/crypto.c b/block/crypto.c | 122 | diff --git a/block/crypto.c b/block/crypto.c |
16 | index XXXXXXX..XXXXXXX 100644 | 123 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/block/crypto.c | 124 | --- a/block/crypto.c |
18 | +++ b/block/crypto.c | 125 | +++ b/block/crypto.c |
19 | @@ -XXX,XX +XXX,XX @@ fail: | 126 | @@ -XXX,XX +XXX,XX @@ fail: |
20 | */ | 127 | return ret; |
21 | if ((r_del < 0) && (r_del != -ENOTSUP)) { | 128 | } |
22 | error_report_err(local_delete_err); | 129 | |
23 | + } else { | 130 | -static int block_crypto_get_info_luks(BlockDriverState *bs, |
24 | + error_free(local_delete_err); | 131 | - BlockDriverInfo *bdi) |
25 | } | 132 | +static int coroutine_fn |
133 | +block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
134 | { | ||
135 | BlockDriverInfo subbdi; | ||
136 | int ret; | ||
137 | |||
138 | - ret = bdrv_get_info(bs->file->bs, &subbdi); | ||
139 | + ret = bdrv_co_get_info(bs->file->bs, &subbdi); | ||
140 | if (ret != 0) { | ||
141 | return ret; | ||
26 | } | 142 | } |
27 | 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, | ||
152 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
153 | index XXXXXXX..XXXXXXX 100644 | ||
154 | --- a/block/file-posix.c | ||
155 | +++ b/block/file-posix.c | ||
156 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwrite_zeroes( | ||
157 | return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false); | ||
158 | } | ||
159 | |||
160 | -static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
161 | +static int coroutine_fn | ||
162 | +raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
163 | { | ||
164 | return 0; | ||
165 | } | ||
166 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = { | ||
167 | |||
168 | .bdrv_co_truncate = raw_co_truncate, | ||
169 | .bdrv_co_getlength = raw_co_getlength, | ||
170 | - .bdrv_get_info = raw_get_info, | ||
171 | + .bdrv_co_get_info = raw_co_get_info, | ||
172 | .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, | ||
173 | .bdrv_get_specific_stats = raw_get_specific_stats, | ||
174 | .bdrv_check_perm = raw_check_perm, | ||
175 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = { | ||
176 | |||
177 | .bdrv_co_truncate = raw_co_truncate, | ||
178 | .bdrv_co_getlength = raw_co_getlength, | ||
179 | - .bdrv_get_info = raw_get_info, | ||
180 | + .bdrv_co_get_info = raw_co_get_info, | ||
181 | .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, | ||
182 | .bdrv_get_specific_stats = hdev_get_specific_stats, | ||
183 | .bdrv_check_perm = raw_check_perm, | ||
184 | diff --git a/block/io.c b/block/io.c | ||
185 | index XXXXXXX..XXXXXXX 100644 | ||
186 | --- a/block/io.c | ||
187 | +++ b/block/io.c | ||
188 | @@ -XXX,XX +XXX,XX @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs) | ||
189 | /** | ||
190 | * Round a region to cluster boundaries | ||
191 | */ | ||
192 | -void bdrv_round_to_clusters(BlockDriverState *bs, | ||
193 | +void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs, | ||
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; | ||
265 | diff --git a/block/qcow.c b/block/qcow.c | ||
266 | index XXXXXXX..XXXXXXX 100644 | ||
267 | --- a/block/qcow.c | ||
268 | +++ b/block/qcow.c | ||
269 | @@ -XXX,XX +XXX,XX @@ fail: | ||
270 | return ret; | ||
271 | } | ||
272 | |||
273 | -static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
274 | +static int coroutine_fn | ||
275 | +qcow_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
276 | { | ||
277 | BDRVQcowState *s = bs->opaque; | ||
278 | bdi->cluster_size = s->cluster_size; | ||
279 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = { | ||
280 | |||
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, | ||
288 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
289 | index XXXXXXX..XXXXXXX 100644 | ||
290 | --- a/block/qcow2.c | ||
291 | +++ b/block/qcow2.c | ||
292 | @@ -XXX,XX +XXX,XX @@ err: | ||
293 | return NULL; | ||
294 | } | ||
295 | |||
296 | -static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
297 | +static int coroutine_fn | ||
298 | +qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
299 | { | ||
300 | BDRVQcow2State *s = bs->opaque; | ||
301 | bdi->cluster_size = s->cluster_size; | ||
302 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = { | ||
303 | .bdrv_snapshot_list = qcow2_snapshot_list, | ||
304 | .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, | ||
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, | ||
311 | diff --git a/block/qed.c b/block/qed.c | ||
312 | index XXXXXXX..XXXXXXX 100644 | ||
313 | --- a/block/qed.c | ||
314 | +++ b/block/qed.c | ||
315 | @@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs) | ||
316 | return s->header.image_size; | ||
317 | } | ||
318 | |||
319 | -static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
320 | +static int coroutine_fn | ||
321 | +bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
322 | { | ||
323 | BDRVQEDState *s = bs->opaque; | ||
324 | |||
325 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = { | ||
326 | .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes, | ||
327 | .bdrv_co_truncate = bdrv_qed_co_truncate, | ||
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, | ||
334 | diff --git a/block/raw-format.c b/block/raw-format.c | ||
335 | index XXXXXXX..XXXXXXX 100644 | ||
336 | --- a/block/raw-format.c | ||
337 | +++ b/block/raw-format.c | ||
338 | @@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs, | ||
339 | return info; | ||
340 | } | ||
341 | |||
342 | -static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
343 | +static int coroutine_fn | ||
344 | +raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
345 | { | ||
346 | - return bdrv_get_info(bs->file->bs, bdi); | ||
347 | + return bdrv_co_get_info(bs->file->bs, bdi); | ||
348 | } | ||
349 | |||
350 | static void raw_refresh_limits(BlockDriverState *bs, Error **errp) | ||
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, | ||
383 | diff --git a/block/vdi.c b/block/vdi.c | ||
384 | index XXXXXXX..XXXXXXX 100644 | ||
385 | --- a/block/vdi.c | ||
386 | +++ b/block/vdi.c | ||
387 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res, | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | -static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
392 | +static int coroutine_fn | ||
393 | +vdi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
394 | { | ||
395 | - /* TODO: vdi_get_info would be needed for machine snapshots. | ||
396 | + /* TODO: vdi_co_get_info would be needed for machine snapshots. | ||
397 | vm_state_offset is still missing. */ | ||
398 | BDRVVdiState *s = (BDRVVdiState *)bs->opaque; | ||
399 | logout("\n"); | ||
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, | ||
409 | diff --git a/block/vhdx.c b/block/vhdx.c | ||
410 | index XXXXXXX..XXXXXXX 100644 | ||
411 | --- a/block/vhdx.c | ||
412 | +++ b/block/vhdx.c | ||
413 | @@ -XXX,XX +XXX,XX @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num, | ||
414 | } | ||
415 | |||
416 | |||
417 | -static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
418 | +static int coroutine_fn | ||
419 | +vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
420 | { | ||
421 | BDRVVHDXState *s = bs->opaque; | ||
422 | |||
423 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = { | ||
424 | .bdrv_co_writev = vhdx_co_writev, | ||
425 | .bdrv_co_create = vhdx_co_create, | ||
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 | |||
432 | diff --git a/block/vmdk.c b/block/vmdk.c | ||
433 | index XXXXXXX..XXXXXXX 100644 | ||
434 | --- a/block/vmdk.c | ||
435 | +++ b/block/vmdk.c | ||
436 | @@ -XXX,XX +XXX,XX @@ static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b) | ||
437 | (a->flat || a->cluster_sectors == b->cluster_sectors); | ||
438 | } | ||
439 | |||
440 | -static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
441 | +static int coroutine_fn | ||
442 | +vmdk_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
443 | { | ||
444 | int i; | ||
445 | BDRVVmdkState *s = bs->opaque; | ||
446 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = { | ||
447 | .bdrv_has_zero_init = vmdk_has_zero_init, | ||
448 | .bdrv_get_specific_info = vmdk_get_specific_info, | ||
449 | .bdrv_refresh_limits = vmdk_refresh_limits, | ||
450 | - .bdrv_get_info = vmdk_get_info, | ||
451 | + .bdrv_co_get_info = vmdk_co_get_info, | ||
452 | .bdrv_gather_child_options = vmdk_gather_child_options, | ||
453 | |||
454 | .is_format = true, | ||
455 | diff --git a/block/vpc.c b/block/vpc.c | ||
456 | index XXXXXXX..XXXXXXX 100644 | ||
457 | --- a/block/vpc.c | ||
458 | +++ b/block/vpc.c | ||
459 | @@ -XXX,XX +XXX,XX @@ fail: | ||
460 | return ret; | ||
461 | } | ||
462 | |||
463 | -static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
464 | +static int coroutine_fn | ||
465 | +vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
466 | { | ||
467 | BDRVVPCState *s = (BDRVVPCState *)bs->opaque; | ||
468 | |||
469 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = { | ||
470 | .bdrv_co_pwritev = vpc_co_pwritev, | ||
471 | .bdrv_co_block_status = vpc_co_block_status, | ||
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, | ||
28 | -- | 478 | -- |
29 | 2.29.2 | 479 | 2.38.1 |
30 | |||
31 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | |
2 | |||
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. | ||
11 | |||
12 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | Message-Id: <20230113204212.359076-12-kwolf@redhat.com> | ||
15 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
17 | --- | ||
18 | include/block/block-io.h | 3 ++- | ||
19 | include/block/block_int-common.h | 2 +- | ||
20 | include/sysemu/block-backend-io.h | 4 +++- | ||
21 | block.c | 6 +++--- | ||
22 | block/block-backend.c | 4 ++-- | ||
23 | block/copy-on-read.c | 6 +++--- | ||
24 | block/file-posix.c | 8 ++++---- | ||
25 | block/filter-compress.c | 7 ++++--- | ||
26 | block/raw-format.c | 6 +++--- | ||
27 | 9 files changed, 25 insertions(+), 21 deletions(-) | ||
28 | |||
29 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/include/block/block-io.h | ||
32 | +++ b/include/block/block-io.h | ||
33 | @@ -XXX,XX +XXX,XX @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs); | ||
34 | bool co_wrapper bdrv_is_inserted(BlockDriverState *bs); | ||
35 | |||
36 | void bdrv_lock_medium(BlockDriverState *bs, bool locked); | ||
37 | -void bdrv_eject(BlockDriverState *bs, bool eject_flag); | ||
38 | +void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag); | ||
39 | + | ||
40 | const char *bdrv_get_format_name(BlockDriverState *bs); | ||
41 | |||
42 | bool bdrv_supports_compressed_writes(BlockDriverState *bs); | ||
43 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/include/block/block_int-common.h | ||
46 | +++ b/include/block/block_int-common.h | ||
47 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
48 | |||
49 | /* removable device specific */ | ||
50 | bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs); | ||
51 | - void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag); | ||
52 | + void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag); | ||
53 | void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); | ||
54 | |||
55 | /* to control generic scsi devices */ | ||
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); | ||
71 | diff --git a/block.c b/block.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/block.c | ||
74 | +++ b/block.c | ||
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) | ||
81 | { | ||
82 | BlockDriver *drv = bs->drv; | ||
83 | IO_CODE(); | ||
84 | |||
85 | - if (drv && drv->bdrv_eject) { | ||
86 | - drv->bdrv_eject(bs, eject_flag); | ||
87 | + if (drv && drv->bdrv_co_eject) { | ||
88 | + drv->bdrv_co_eject(bs, eject_flag); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
93 | index XXXXXXX..XXXXXXX 100644 | ||
94 | --- a/block/block-backend.c | ||
95 | +++ b/block/block-backend.c | ||
96 | @@ -XXX,XX +XXX,XX @@ void blk_lock_medium(BlockBackend *blk, bool locked) | ||
97 | } | ||
98 | } | ||
99 | |||
100 | -void blk_eject(BlockBackend *blk, bool eject_flag) | ||
101 | +void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag) | ||
102 | { | ||
103 | BlockDriverState *bs = blk_bs(blk); | ||
104 | char *id; | ||
105 | IO_CODE(); | ||
106 | |||
107 | if (bs) { | ||
108 | - bdrv_eject(bs, eject_flag); | ||
109 | + bdrv_co_eject(bs, eject_flag); | ||
110 | } | ||
111 | |||
112 | /* Whether or not we ejected on the backend, | ||
113 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | ||
114 | index XXXXXXX..XXXXXXX 100644 | ||
115 | --- a/block/copy-on-read.c | ||
116 | +++ b/block/copy-on-read.c | ||
117 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs, | ||
118 | } | ||
119 | |||
120 | |||
121 | -static void cor_eject(BlockDriverState *bs, bool eject_flag) | ||
122 | +static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag) | ||
123 | { | ||
124 | - bdrv_eject(bs->file->bs, eject_flag); | ||
125 | + bdrv_co_eject(bs->file->bs, eject_flag); | ||
126 | } | ||
127 | |||
128 | |||
129 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = { | ||
130 | .bdrv_co_pdiscard = cor_co_pdiscard, | ||
131 | .bdrv_co_pwritev_compressed = cor_co_pwritev_compressed, | ||
132 | |||
133 | - .bdrv_eject = cor_eject, | ||
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__ */ | ||
178 | diff --git a/block/filter-compress.c b/block/filter-compress.c | ||
179 | index XXXXXXX..XXXXXXX 100644 | ||
180 | --- a/block/filter-compress.c | ||
181 | +++ b/block/filter-compress.c | ||
182 | @@ -XXX,XX +XXX,XX @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp) | ||
183 | } | ||
184 | |||
185 | |||
186 | -static void compress_eject(BlockDriverState *bs, bool eject_flag) | ||
187 | +static void coroutine_fn | ||
188 | +compress_co_eject(BlockDriverState *bs, bool eject_flag) | ||
189 | { | ||
190 | - bdrv_eject(bs->file->bs, eject_flag); | ||
191 | + bdrv_co_eject(bs->file->bs, eject_flag); | ||
192 | } | ||
193 | |||
194 | |||
195 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = { | ||
196 | .bdrv_co_pdiscard = compress_co_pdiscard, | ||
197 | .bdrv_refresh_limits = compress_refresh_limits, | ||
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, | ||
204 | diff --git a/block/raw-format.c b/block/raw-format.c | ||
205 | index XXXXXXX..XXXXXXX 100644 | ||
206 | --- a/block/raw-format.c | ||
207 | +++ b/block/raw-format.c | ||
208 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, | ||
209 | return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); | ||
210 | } | ||
211 | |||
212 | -static void raw_eject(BlockDriverState *bs, bool eject_flag) | ||
213 | +static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag) | ||
214 | { | ||
215 | - bdrv_eject(bs->file->bs, eject_flag); | ||
216 | + bdrv_co_eject(bs->file->bs, eject_flag); | ||
217 | } | ||
218 | |||
219 | static void raw_lock_medium(BlockDriverState *bs, bool locked) | ||
220 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = { | ||
221 | .bdrv_refresh_limits = &raw_refresh_limits, | ||
222 | .bdrv_probe_blocksizes = &raw_probe_blocksizes, | ||
223 | .bdrv_probe_geometry = &raw_probe_geometry, | ||
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, | ||
229 | -- | ||
230 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | |
2 | |||
3 | bdrv_lock_medium() 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_lock_medium(). Therefore make | ||
9 | blk_lock_medium() a co_wrapper, so that it always creates a new | ||
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> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | Message-Id: <20230113204212.359076-13-kwolf@redhat.com> | ||
16 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
17 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
18 | --- | ||
19 | include/block/block-io.h | 2 +- | ||
20 | include/block/block_int-common.h | 2 +- | ||
21 | include/sysemu/block-backend-io.h | 4 +++- | ||
22 | block.c | 6 +++--- | ||
23 | block/block-backend.c | 4 ++-- | ||
24 | block/copy-on-read.c | 6 +++--- | ||
25 | block/file-posix.c | 8 ++++---- | ||
26 | block/filter-compress.c | 7 ++++--- | ||
27 | block/raw-format.c | 6 +++--- | ||
28 | 9 files changed, 24 insertions(+), 21 deletions(-) | ||
29 | |||
30 | diff --git a/include/block/block-io.h b/include/block/block-io.h | ||
31 | index XXXXXXX..XXXXXXX 100644 | ||
32 | --- a/include/block/block-io.h | ||
33 | +++ b/include/block/block-io.h | ||
34 | @@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs); | ||
35 | bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs); | ||
36 | bool co_wrapper bdrv_is_inserted(BlockDriverState *bs); | ||
37 | |||
38 | -void bdrv_lock_medium(BlockDriverState *bs, bool locked); | ||
39 | +void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked); | ||
40 | void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag); | ||
41 | |||
42 | 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 | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/include/block/block_int-common.h | ||
46 | +++ b/include/block/block_int-common.h | ||
47 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
48 | /* removable device specific */ | ||
49 | bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs); | ||
50 | void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag); | ||
51 | - void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); | ||
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); | ||
65 | + | ||
66 | +void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked); | ||
67 | +void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked); | ||
68 | |||
69 | void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag); | ||
70 | void co_wrapper blk_eject(BlockBackend *blk, bool eject_flag); | ||
71 | diff --git a/block.c b/block.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/block.c | ||
74 | +++ b/block.c | ||
75 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag) | ||
76 | * Lock or unlock the media (if it is locked, the user won't be able | ||
77 | * to eject it manually). | ||
78 | */ | ||
79 | -void bdrv_lock_medium(BlockDriverState *bs, bool locked) | ||
80 | +void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked) | ||
81 | { | ||
82 | BlockDriver *drv = bs->drv; | ||
83 | IO_CODE(); | ||
84 | trace_bdrv_lock_medium(bs, locked); | ||
85 | |||
86 | - if (drv && drv->bdrv_lock_medium) { | ||
87 | - drv->bdrv_lock_medium(bs, locked); | ||
88 | + if (drv && drv->bdrv_co_lock_medium) { | ||
89 | + drv->bdrv_co_lock_medium(bs, locked); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
94 | index XXXXXXX..XXXXXXX 100644 | ||
95 | --- a/block/block-backend.c | ||
96 | +++ b/block/block-backend.c | ||
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); | ||
105 | IO_CODE(); | ||
106 | |||
107 | if (bs) { | ||
108 | - bdrv_lock_medium(bs, locked); | ||
109 | + bdrv_co_lock_medium(bs, locked); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | ||
114 | index XXXXXXX..XXXXXXX 100644 | ||
115 | --- a/block/copy-on-read.c | ||
116 | +++ b/block/copy-on-read.c | ||
117 | @@ -XXX,XX +XXX,XX @@ static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag) | ||
118 | } | ||
119 | |||
120 | |||
121 | -static void cor_lock_medium(BlockDriverState *bs, bool locked) | ||
122 | +static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked) | ||
123 | { | ||
124 | - bdrv_lock_medium(bs->file->bs, locked); | ||
125 | + bdrv_co_lock_medium(bs->file->bs, locked); | ||
126 | } | ||
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 | |||
178 | diff --git a/block/filter-compress.c b/block/filter-compress.c | ||
179 | index XXXXXXX..XXXXXXX 100644 | ||
180 | --- a/block/filter-compress.c | ||
181 | +++ b/block/filter-compress.c | ||
182 | @@ -XXX,XX +XXX,XX @@ compress_co_eject(BlockDriverState *bs, bool eject_flag) | ||
183 | } | ||
184 | |||
185 | |||
186 | -static void compress_lock_medium(BlockDriverState *bs, bool locked) | ||
187 | +static void coroutine_fn | ||
188 | +compress_co_lock_medium(BlockDriverState *bs, bool locked) | ||
189 | { | ||
190 | - bdrv_lock_medium(bs->file->bs, locked); | ||
191 | + bdrv_co_lock_medium(bs->file->bs, locked); | ||
192 | } | ||
193 | |||
194 | |||
195 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = { | ||
196 | .bdrv_refresh_limits = compress_refresh_limits, | ||
197 | |||
198 | .bdrv_co_eject = compress_co_eject, | ||
199 | - .bdrv_lock_medium = compress_lock_medium, | ||
200 | + .bdrv_co_lock_medium = compress_co_lock_medium, | ||
201 | |||
202 | .has_variable_length = true, | ||
203 | .is_filter = true, | ||
204 | diff --git a/block/raw-format.c b/block/raw-format.c | ||
205 | index XXXXXXX..XXXXXXX 100644 | ||
206 | --- a/block/raw-format.c | ||
207 | +++ b/block/raw-format.c | ||
208 | @@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag) | ||
209 | bdrv_co_eject(bs->file->bs, eject_flag); | ||
210 | } | ||
211 | |||
212 | -static void raw_lock_medium(BlockDriverState *bs, bool locked) | ||
213 | +static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked) | ||
214 | { | ||
215 | - bdrv_lock_medium(bs->file->bs, locked); | ||
216 | + bdrv_co_lock_medium(bs->file->bs, locked); | ||
217 | } | ||
218 | |||
219 | static int coroutine_fn raw_co_ioctl(BlockDriverState *bs, | ||
220 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = { | ||
221 | .bdrv_probe_blocksizes = &raw_probe_blocksizes, | ||
222 | .bdrv_probe_geometry = &raw_probe_geometry, | ||
223 | .bdrv_co_eject = &raw_co_eject, | ||
224 | - .bdrv_lock_medium = &raw_lock_medium, | ||
225 | + .bdrv_co_lock_medium = &raw_co_lock_medium, | ||
226 | .bdrv_co_ioctl = &raw_co_ioctl, | ||
227 | .create_opts = &raw_create_opts, | ||
228 | .bdrv_has_zero_init = &raw_has_zero_init, | ||
229 | -- | ||
230 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
1 | 2 | ||
3 | bdrv_debug_event() 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_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> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | Message-Id: <20230113204212.359076-14-kwolf@redhat.com> | ||
14 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> | ||
15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
16 | --- | ||
17 | include/block/block-io.h | 5 ++++- | ||
18 | include/block/block_int-common.h | 3 ++- | ||
19 | block.c | 6 +++--- | ||
20 | block/blkdebug.c | 5 +++-- | ||
21 | block/io.c | 22 +++++++++++----------- | ||
22 | 5 files changed, 23 insertions(+), 18 deletions(-) | ||
23 | |||
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 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size); | ||
29 | void bdrv_enable_copy_on_read(BlockDriverState *bs); | ||
30 | void bdrv_disable_copy_on_read(BlockDriverState *bs); | ||
31 | |||
32 | -void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event); | ||
33 | +void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, | ||
34 | + BlkdebugEvent event); | ||
35 | +void co_wrapper_mixed bdrv_debug_event(BlockDriverState *bs, | ||
36 | + BlkdebugEvent event); | ||
37 | |||
38 | #define BLKDBG_EVENT(child, evt) \ | ||
39 | do { \ | ||
40 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/include/block/block_int-common.h | ||
43 | +++ b/include/block/block_int-common.h | ||
44 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
45 | int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_check)( | ||
46 | BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix); | ||
47 | |||
48 | - void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event); | ||
49 | + void coroutine_fn (*bdrv_co_debug_event)(BlockDriverState *bs, | ||
50 | + BlkdebugEvent event); | ||
51 | |||
52 | /* io queue for linux-aio */ | ||
53 | void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs); | ||
54 | diff --git a/block.c b/block.c | ||
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) | ||
76 | diff --git a/block/blkdebug.c b/block/blkdebug.c | ||
77 | index XXXXXXX..XXXXXXX 100644 | ||
78 | --- a/block/blkdebug.c | ||
79 | +++ b/block/blkdebug.c | ||
80 | @@ -XXX,XX +XXX,XX @@ static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, | ||
81 | } | ||
82 | } | ||
83 | |||
84 | -static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event) | ||
85 | +static void coroutine_fn | ||
86 | +blkdebug_co_debug_event(BlockDriverState *bs, BlkdebugEvent event) | ||
87 | { | ||
88 | BDRVBlkdebugState *s = bs->opaque; | ||
89 | struct BlkdebugRule *rule, *next; | ||
90 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = { | ||
91 | .bdrv_co_pdiscard = blkdebug_co_pdiscard, | ||
92 | .bdrv_co_block_status = blkdebug_co_block_status, | ||
93 | |||
94 | - .bdrv_debug_event = blkdebug_debug_event, | ||
95 | + .bdrv_co_debug_event = blkdebug_co_debug_event, | ||
96 | .bdrv_debug_breakpoint = blkdebug_debug_breakpoint, | ||
97 | .bdrv_debug_remove_breakpoint | ||
98 | = blkdebug_debug_remove_breakpoint, | ||
99 | diff --git a/block/io.c b/block/io.c | ||
100 | index XXXXXXX..XXXXXXX 100644 | ||
101 | --- a/block/io.c | ||
102 | +++ b/block/io.c | ||
103 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, | ||
104 | goto err; | ||
105 | } | ||
106 | |||
107 | - bdrv_debug_event(bs, BLKDBG_COR_WRITE); | ||
108 | + bdrv_co_debug_event(bs, BLKDBG_COR_WRITE); | ||
109 | if (drv->bdrv_co_pwrite_zeroes && | ||
110 | buffer_is_zero(bounce_buffer, pnum)) { | ||
111 | /* FIXME: Should we (perhaps conditionally) be setting | ||
112 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child, | ||
113 | qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); | ||
114 | |||
115 | if (pad->head) { | ||
116 | - bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); | ||
117 | + bdrv_co_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); | ||
118 | } | ||
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: | ||
156 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, | ||
157 | if (ret < 0) { | ||
158 | /* Do nothing, write notifier decided to fail this request */ | ||
159 | } else if (flags & BDRV_REQ_ZERO_WRITE) { | ||
160 | - bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO); | ||
161 | + bdrv_co_debug_event(bs, BLKDBG_PWRITEV_ZERO); | ||
162 | ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags); | ||
163 | } else if (flags & BDRV_REQ_WRITE_COMPRESSED) { | ||
164 | ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, | ||
165 | qiov, qiov_offset); | ||
166 | } else if (bytes <= max_transfer) { | ||
167 | - bdrv_debug_event(bs, BLKDBG_PWRITEV); | ||
168 | + bdrv_co_debug_event(bs, BLKDBG_PWRITEV); | ||
169 | ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags); | ||
170 | } else { | ||
171 | - bdrv_debug_event(bs, BLKDBG_PWRITEV); | ||
172 | + bdrv_co_debug_event(bs, BLKDBG_PWRITEV); | ||
173 | while (bytes_remaining) { | ||
174 | int num = MIN(bytes_remaining, max_transfer); | ||
175 | int local_flags = flags; | ||
176 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, | ||
177 | bytes_remaining -= num; | ||
178 | } | ||
179 | } | ||
180 | - bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE); | ||
181 | + bdrv_co_debug_event(bs, BLKDBG_PWRITEV_DONE); | ||
182 | |||
183 | if (ret >= 0) { | ||
184 | ret = 0; | ||
185 | -- | ||
186 | 2.38.1 | diff view generated by jsdifflib |
1 | From: Maxim Levitsky <mlevitsk@redhat.com> | 1 | From: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | If the qcow initialization fails, we should remove the file if it was | 3 | Since these functions always run in coroutine context, adjust |
4 | already created, to avoid leaving stale files around. | 4 | their name to include "_co_", just like all other BlockDriver callbacks. |
5 | 5 | ||
6 | We already do this for luks raw images. | 6 | No functional change intended. |
7 | 7 | ||
8 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | 8 | Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
9 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
10 | Message-Id: <20201217170904.946013-4-mlevitsk@redhat.com> | 10 | Message-Id: <20230113204212.359076-15-kwolf@redhat.com> |
11 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 11 | Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com> |
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
13 | --- | 13 | --- |
14 | block/qcow2.c | 8 +++++--- | 14 | include/block/block_int-common.h | 4 ++-- |
15 | 1 file changed, 5 insertions(+), 3 deletions(-) | 15 | block/io.c | 8 ++++---- |
16 | block/qcow2.c | 12 ++++++------ | ||
17 | 3 files changed, 12 insertions(+), 12 deletions(-) | ||
16 | 18 | ||
19 | diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/include/block/block_int-common.h | ||
22 | +++ b/include/block/block_int-common.h | ||
23 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
24 | Error **errp); | ||
25 | BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs); | ||
26 | |||
27 | - int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_save_vmstate)( | ||
28 | + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_save_vmstate)( | ||
29 | BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); | ||
30 | |||
31 | - int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_load_vmstate)( | ||
32 | + int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_load_vmstate)( | ||
33 | BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); | ||
34 | |||
35 | /* removable device specific */ | ||
36 | diff --git a/block/io.c b/block/io.c | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/block/io.c | ||
39 | +++ b/block/io.c | ||
40 | @@ -XXX,XX +XXX,XX @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) | ||
41 | |||
42 | bdrv_inc_in_flight(bs); | ||
43 | |||
44 | - if (drv->bdrv_load_vmstate) { | ||
45 | - ret = drv->bdrv_load_vmstate(bs, qiov, pos); | ||
46 | + if (drv->bdrv_co_load_vmstate) { | ||
47 | + ret = drv->bdrv_co_load_vmstate(bs, qiov, pos); | ||
48 | } else if (child_bs) { | ||
49 | ret = bdrv_co_readv_vmstate(child_bs, qiov, pos); | ||
50 | } else { | ||
51 | @@ -XXX,XX +XXX,XX @@ bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) | ||
52 | |||
53 | bdrv_inc_in_flight(bs); | ||
54 | |||
55 | - if (drv->bdrv_save_vmstate) { | ||
56 | - ret = drv->bdrv_save_vmstate(bs, qiov, pos); | ||
57 | + if (drv->bdrv_co_save_vmstate) { | ||
58 | + ret = drv->bdrv_co_save_vmstate(bs, qiov, pos); | ||
59 | } else if (child_bs) { | ||
60 | ret = bdrv_co_writev_vmstate(child_bs, qiov, pos); | ||
61 | } else { | ||
17 | diff --git a/block/qcow2.c b/block/qcow2.c | 62 | diff --git a/block/qcow2.c b/block/qcow2.c |
18 | index XXXXXXX..XXXXXXX 100644 | 63 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/block/qcow2.c | 64 | --- a/block/qcow2.c |
20 | +++ b/block/qcow2.c | 65 | +++ b/block/qcow2.c |
21 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, | 66 | @@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs, |
22 | 67 | return pos; | |
23 | /* Create the qcow2 image (format layer) */ | 68 | } |
24 | ret = qcow2_co_create(create_options, errp); | 69 | |
25 | +finish: | 70 | -static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs, |
26 | if (ret < 0) { | 71 | - QEMUIOVector *qiov, int64_t pos) |
27 | - goto finish; | 72 | +static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs, |
28 | + bdrv_co_delete_file_noerr(bs); | 73 | + QEMUIOVector *qiov, int64_t pos) |
29 | + bdrv_co_delete_file_noerr(data_bs); | 74 | { |
30 | + } else { | 75 | int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos); |
31 | + ret = 0; | 76 | if (offset < 0) { |
32 | } | 77 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs, |
33 | 78 | return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0); | |
34 | - ret = 0; | 79 | } |
35 | -finish: | 80 | |
36 | qobject_unref(qdict); | 81 | -static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs, |
37 | bdrv_unref(bs); | 82 | - QEMUIOVector *qiov, int64_t pos) |
38 | bdrv_unref(data_bs); | 83 | +static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs, |
84 | + QEMUIOVector *qiov, int64_t pos) | ||
85 | { | ||
86 | int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos); | ||
87 | if (offset < 0) { | ||
88 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = { | ||
89 | .bdrv_co_get_info = qcow2_co_get_info, | ||
90 | .bdrv_get_specific_info = qcow2_get_specific_info, | ||
91 | |||
92 | - .bdrv_save_vmstate = qcow2_save_vmstate, | ||
93 | - .bdrv_load_vmstate = qcow2_load_vmstate, | ||
94 | + .bdrv_co_save_vmstate = qcow2_co_save_vmstate, | ||
95 | + .bdrv_co_load_vmstate = qcow2_co_load_vmstate, | ||
96 | |||
97 | .is_format = true, | ||
98 | .supports_backing = true, | ||
39 | -- | 99 | -- |
40 | 2.29.2 | 100 | 2.38.1 |
41 | |||
42 | diff view generated by jsdifflib |
1 | As we don't have a fully QAPIfied version of object-add yet and it still | 1 | From: Philippe Mathieu-Daudé <philmd@linaro.org> |
---|---|---|---|
2 | has 'gen': false in the schema, it needs to be registered explicitly in | ||
3 | init_qmp_commands() to be available for users. | ||
4 | 2 | ||
5 | Fixes: 2af282ec51a27116d0402cab237b8970800f870c | 3 | The inlined nbd_readXX() functions call beXX_to_cpu(), themselves |
6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 4 | declared in <qemu/bswap.h>. This fixes when refactoring: |
7 | Message-Id: <20210204072137.19663-1-kwolf@redhat.com> | 5 | |
8 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | 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> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 19 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
10 | --- | 20 | --- |
11 | storage-daemon/qemu-storage-daemon.c | 2 ++ | 21 | include/block/nbd.h | 1 + |
12 | 1 file changed, 2 insertions(+) | 22 | 1 file changed, 1 insertion(+) |
13 | 23 | ||
14 | diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c | 24 | diff --git a/include/block/nbd.h b/include/block/nbd.h |
15 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/storage-daemon/qemu-storage-daemon.c | 26 | --- a/include/block/nbd.h |
17 | +++ b/storage-daemon/qemu-storage-daemon.c | 27 | +++ b/include/block/nbd.h |
18 | @@ -XXX,XX +XXX,XX @@ static void init_qmp_commands(void) | 28 | @@ -XXX,XX +XXX,XX @@ |
19 | qmp_init_marshal(&qmp_commands); | 29 | #include "io/channel-socket.h" |
20 | qmp_register_command(&qmp_commands, "query-qmp-schema", | 30 | #include "crypto/tlscreds.h" |
21 | qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); | 31 | #include "qapi/error.h" |
22 | + qmp_register_command(&qmp_commands, "object-add", qmp_object_add, | 32 | +#include "qemu/bswap.h" |
23 | + QCO_NO_OPTIONS); | 33 | |
24 | 34 | extern const BlockExportDriver blk_exp_nbd; | |
25 | QTAILQ_INIT(&qmp_cap_negotiation_commands); | 35 | |
26 | qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", | ||
27 | -- | 36 | -- |
28 | 2.29.2 | 37 | 2.38.1 |
29 | 38 | ||
30 | 39 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | When a block driver supports obtaining format-specific information, but | ||
4 | that object only contains optional fields, it is possible that none of | ||
5 | them are present, so that dump_qobject() (called by | ||
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> | ||
17 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
18 | --- | ||
19 | include/block/qapi.h | 3 ++- | ||
20 | block/qapi.c | 41 +++++++++++++++++++++++++++++++++++++---- | ||
21 | qemu-io-cmds.c | 4 ++-- | ||
22 | 3 files changed, 41 insertions(+), 7 deletions(-) | ||
23 | |||
24 | diff --git a/include/block/qapi.h b/include/block/qapi.h | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/include/block/qapi.h | ||
27 | +++ b/include/block/qapi.h | ||
28 | @@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs, | ||
29 | Error **errp); | ||
30 | |||
31 | void bdrv_snapshot_dump(QEMUSnapshotInfo *sn); | ||
32 | -void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec); | ||
33 | +void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec, | ||
34 | + const char *prefix); | ||
35 | void bdrv_image_info_dump(ImageInfo *info); | ||
36 | #endif | ||
37 | diff --git a/block/qapi.c b/block/qapi.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/block/qapi.c | ||
40 | +++ b/block/qapi.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static void dump_qdict(int indentation, QDict *dict) | ||
42 | } | ||
43 | } | ||
44 | |||
45 | -void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec) | ||
46 | +/* | ||
47 | + * Return whether dumping the given QObject with dump_qobject() would | ||
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) | ||
75 | { | ||
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 | } | ||
116 | |||
117 | -- | ||
118 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | Add some (optional) information that the file driver can provide for | ||
4 | image files, namely the extent size hint. | ||
5 | |||
6 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||
7 | Message-Id: <20220620162704.80987-3-hreitz@redhat.com> | ||
8 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | qapi/block-core.json | 26 ++++++++++++++++++++++++-- | ||
12 | block/file-posix.c | 30 ++++++++++++++++++++++++++++++ | ||
13 | 2 files changed, 54 insertions(+), 2 deletions(-) | ||
14 | |||
15 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/qapi/block-core.json | ||
18 | +++ b/qapi/block-core.json | ||
19 | @@ -XXX,XX +XXX,XX @@ | ||
20 | '*encryption-format': 'RbdImageEncryptionFormat' | ||
21 | } } | ||
22 | |||
23 | +## | ||
24 | +# @ImageInfoSpecificFile: | ||
25 | +# | ||
26 | +# @extent-size-hint: Extent size hint (if available) | ||
27 | +# | ||
28 | +# Since: 8.0 | ||
29 | +## | ||
30 | +{ 'struct': 'ImageInfoSpecificFile', | ||
31 | + 'data': { | ||
32 | + '*extent-size-hint': 'size' | ||
33 | + } } | ||
34 | + | ||
35 | ## | ||
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: | ||
64 | # | ||
65 | @@ -XXX,XX +XXX,XX @@ | ||
66 | 'qcow2': 'ImageInfoSpecificQCow2Wrapper', | ||
67 | 'vmdk': 'ImageInfoSpecificVmdkWrapper', | ||
68 | 'luks': 'ImageInfoSpecificLUKSWrapper', | ||
69 | - 'rbd': 'ImageInfoSpecificRbdWrapper' | ||
70 | + 'rbd': 'ImageInfoSpecificRbdWrapper', | ||
71 | + 'file': 'ImageInfoSpecificFileWrapper' | ||
72 | } } | ||
73 | |||
74 | ## | ||
75 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
76 | index XXXXXXX..XXXXXXX 100644 | ||
77 | --- a/block/file-posix.c | ||
78 | +++ b/block/file-posix.c | ||
79 | @@ -XXX,XX +XXX,XX @@ raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | +static ImageInfoSpecific *raw_get_specific_info(BlockDriverState *bs, | ||
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 | + } | ||
106 | +#endif | ||
107 | + | ||
108 | + return spec_info; | ||
109 | +} | ||
110 | + | ||
111 | static BlockStatsSpecificFile get_blockstats_specific_file(BlockDriverState *bs) | ||
112 | { | ||
113 | BDRVRawState *s = bs->opaque; | ||
114 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = { | ||
115 | .bdrv_co_truncate = raw_co_truncate, | ||
116 | .bdrv_co_getlength = raw_co_getlength, | ||
117 | .bdrv_co_get_info = raw_co_get_info, | ||
118 | + .bdrv_get_specific_info = raw_get_specific_info, | ||
119 | .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, | ||
120 | .bdrv_get_specific_stats = raw_get_specific_stats, | ||
121 | .bdrv_check_perm = raw_check_perm, | ||
122 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = { | ||
123 | .bdrv_co_truncate = raw_co_truncate, | ||
124 | .bdrv_co_getlength = raw_co_getlength, | ||
125 | .bdrv_co_get_info = raw_co_get_info, | ||
126 | + .bdrv_get_specific_info = raw_get_specific_info, | ||
127 | .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, | ||
128 | .bdrv_get_specific_stats = hdev_get_specific_stats, | ||
129 | .bdrv_check_perm = raw_check_perm, | ||
130 | -- | ||
131 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | VMDK's implementation of .bdrv_get_specific_info() returns information | ||
4 | about its extent files, ostensibly in the form of ImageInfo objects. | ||
5 | However, it does not get this information through | ||
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 | |||
9 | For example, @format, which is supposed to be a block driver name, is | ||
10 | filled with the extent type, e.g. SPARSE or FLAT. | ||
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> | ||
37 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
38 | --- | ||
39 | qapi/block-core.json | 38 +++++++++++++++++++++++++++++++++++++- | ||
40 | block/vmdk.c | 8 ++++---- | ||
41 | 2 files changed, 41 insertions(+), 5 deletions(-) | ||
42 | |||
43 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/qapi/block-core.json | ||
46 | +++ b/qapi/block-core.json | ||
47 | @@ -XXX,XX +XXX,XX @@ | ||
48 | 'create-type': 'str', | ||
49 | 'cid': 'int', | ||
50 | 'parent-cid': 'int', | ||
51 | - 'extents': ['ImageInfo'] | ||
52 | + 'extents': ['VmdkExtentInfo'] | ||
53 | + } } | ||
54 | + | ||
55 | +## | ||
56 | +# @VmdkExtentInfo: | ||
57 | +# | ||
58 | +# Information about a VMDK extent file | ||
59 | +# | ||
60 | +# @filename: Name of the extent file | ||
61 | +# | ||
62 | +# @format: Extent type (e.g. FLAT or SPARSE) | ||
63 | +# | ||
64 | +# @virtual-size: Number of bytes covered by this extent | ||
65 | +# | ||
66 | +# @cluster-size: Cluster size in bytes (for non-flat extents) | ||
67 | +# | ||
68 | +# @compressed: Whether this extent contains compressed data | ||
69 | +# | ||
70 | +# Since: 8.0 | ||
71 | +## | ||
72 | +{ 'struct': 'VmdkExtentInfo', | ||
73 | + 'data': { | ||
74 | + 'filename': 'str', | ||
75 | + 'format': 'str', | ||
76 | + 'virtual-size': 'int', | ||
77 | + '*cluster-size': 'int', | ||
78 | + '*compressed': 'bool' | ||
79 | } } | ||
80 | |||
81 | ## | ||
82 | @@ -XXX,XX +XXX,XX @@ | ||
83 | 'data': { 'device': 'str', '*id': 'str', '*name': 'str'}, | ||
84 | 'returns': 'SnapshotInfo', | ||
85 | 'allow-preconfig': true } | ||
86 | + | ||
87 | +## | ||
88 | +# @DummyBlockCoreForceArrays: | ||
89 | +# | ||
90 | +# Not used by QMP; hack to let us use ImageInfoList internally | ||
91 | +# | ||
92 | +# Since: 8.0 | ||
93 | +## | ||
94 | +{ 'struct': 'DummyBlockCoreForceArrays', | ||
95 | + 'data': { 'unused-image-info': ['ImageInfo'] } } | ||
96 | diff --git a/block/vmdk.c b/block/vmdk.c | ||
97 | index XXXXXXX..XXXXXXX 100644 | ||
98 | --- a/block/vmdk.c | ||
99 | +++ b/block/vmdk.c | ||
100 | @@ -XXX,XX +XXX,XX @@ static int vmdk_has_zero_init(BlockDriverState *bs) | ||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | -static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent) | ||
105 | +static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent) | ||
106 | { | ||
107 | - ImageInfo *info = g_new0(ImageInfo, 1); | ||
108 | + VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1); | ||
109 | |||
110 | bdrv_refresh_filename(extent->file->bs); | ||
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, | ||
125 | -- | ||
126 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Hanna Reitz <hreitz@redhat.com> | |
2 | |||
3 | ImageInfo sometimes contains flat information, and sometimes it does | ||
4 | not. Split off a BlockNodeInfo struct, which only contains information | ||
5 | about a single node and has no link to the backing image. | ||
6 | |||
7 | We do this so we can extend BlockNodeInfo to a BlockGraphInfo struct, | ||
8 | which has links to all child nodes, not just the backing node. It would | ||
9 | be strange to base BlockGraphInfo on ImageInfo, because then this | ||
10 | extended struct would have two links to the backing node (one in | ||
11 | BlockGraphInfo as one of all the child links, and one in ImageInfo). | ||
12 | |||
13 | Furthermore, it is quite common to ignore the backing-image field | ||
14 | altogether: bdrv_query_image_info() does not set it, and | ||
15 | bdrv_image_info_dump() does not evaluate it. That signals that we | ||
16 | should have different structs for describing a single node and one that | ||
17 | has a link to the backing image. | ||
18 | |||
19 | Still, bdrv_query_image_info() and bdrv_image_info_dump() are not | ||
20 | changed too much in this patch. Follow-up patches will handle them. | ||
21 | |||
22 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||
23 | Message-Id: <20220620162704.80987-5-hreitz@redhat.com> | ||
24 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
26 | --- | ||
27 | qapi/block-core.json | 24 +++++++++---- | ||
28 | include/block/qapi.h | 3 ++ | ||
29 | block/qapi.c | 86 ++++++++++++++++++++++++++++++++------------ | ||
30 | 3 files changed, 85 insertions(+), 28 deletions(-) | ||
31 | |||
32 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/qapi/block-core.json | ||
35 | +++ b/qapi/block-core.json | ||
36 | @@ -XXX,XX +XXX,XX @@ | ||
37 | } } | ||
38 | |||
39 | ## | ||
40 | -# @ImageInfo: | ||
41 | +# @BlockNodeInfo: | ||
42 | # | ||
43 | # Information about a QEMU image file | ||
44 | # | ||
45 | @@ -XXX,XX +XXX,XX @@ | ||
46 | # | ||
47 | # @snapshots: list of VM snapshots | ||
48 | # | ||
49 | -# @backing-image: info of the backing image (since 1.6) | ||
50 | -# | ||
51 | # @format-specific: structure supplying additional format-specific | ||
52 | # information (since 1.7) | ||
53 | # | ||
54 | -# Since: 1.3 | ||
55 | +# Since: 8.0 | ||
56 | ## | ||
57 | -{ 'struct': 'ImageInfo', | ||
58 | +{ 'struct': 'BlockNodeInfo', | ||
59 | 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool', | ||
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 | ||
86 | index XXXXXXX..XXXXXXX 100644 | ||
87 | --- a/include/block/qapi.h | ||
88 | +++ b/include/block/qapi.h | ||
89 | @@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, | ||
90 | int bdrv_query_snapshot_info_list(BlockDriverState *bs, | ||
91 | SnapshotInfoList **p_list, | ||
92 | Error **errp); | ||
93 | +void bdrv_query_block_node_info(BlockDriverState *bs, | ||
94 | + BlockNodeInfo **p_info, | ||
95 | + Error **errp); | ||
96 | void bdrv_query_image_info(BlockDriverState *bs, | ||
97 | ImageInfo **p_info, | ||
98 | Error **errp); | ||
99 | diff --git a/block/qapi.c b/block/qapi.c | ||
100 | index XXXXXXX..XXXXXXX 100644 | ||
101 | --- a/block/qapi.c | ||
102 | +++ b/block/qapi.c | ||
103 | @@ -XXX,XX +XXX,XX @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, | ||
104 | } | ||
105 | |||
106 | /** | ||
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; | ||
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)); | ||
167 | } | ||
168 | |||
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) | ||
182 | +{ | ||
183 | + BlockNodeInfo *info; | ||
184 | + ERRP_GUARD(); | ||
185 | + | ||
186 | + info = g_new0(BlockNodeInfo, 1); | ||
187 | + bdrv_do_query_node_info(bs, info, errp); | ||
188 | + if (*errp) { | ||
189 | + qapi_free_BlockNodeInfo(info); | ||
190 | + return; | ||
191 | + } | ||
192 | + | ||
193 | + *p_info = info; | ||
194 | +} | ||
195 | + | ||
196 | +/** | ||
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) | ||
214 | +{ | ||
215 | + ImageInfo *info; | ||
216 | + ERRP_GUARD(); | ||
217 | + | ||
218 | + info = g_new0(ImageInfo, 1); | ||
219 | + bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp); | ||
220 | + if (*errp) { | ||
221 | + qapi_free_ImageInfo(info); | ||
222 | + return; | ||
223 | + } | ||
224 | + | ||
225 | + *p_info = info; | ||
226 | +} | ||
227 | + | ||
228 | /* @p_info will be set only on success. */ | ||
229 | static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, | ||
230 | Error **errp) | ||
231 | -- | ||
232 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Hanna Reitz <hreitz@redhat.com> | |
2 | |||
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> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
19 | --- | ||
20 | qapi/block-core.json | 4 +-- | ||
21 | include/block/qapi.h | 2 +- | ||
22 | block/monitor/block-hmp-cmds.c | 2 +- | ||
23 | block/qapi.c | 2 +- | ||
24 | qemu-img.c | 48 +++++++++++++++++----------------- | ||
25 | 5 files changed, 29 insertions(+), 29 deletions(-) | ||
26 | |||
27 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/qapi/block-core.json | ||
30 | +++ b/qapi/block-core.json | ||
31 | @@ -XXX,XX +XXX,XX @@ | ||
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. | ||
155 | */ | ||
156 | -static ImageInfoList *collect_image_info_list(bool image_opts, | ||
157 | - const char *filename, | ||
158 | - const char *fmt, | ||
159 | - bool chain, bool force_share) | ||
160 | +static BlockNodeInfoList *collect_image_info_list(bool image_opts, | ||
161 | + const char *filename, | ||
162 | + const char *fmt, | ||
163 | + bool chain, bool force_share) | ||
164 | { | ||
165 | - ImageInfoList *head = NULL; | ||
166 | - ImageInfoList **tail = &head; | ||
167 | + BlockNodeInfoList *head = NULL; | ||
168 | + BlockNodeInfoList **tail = &head; | ||
169 | GHashTable *filenames; | ||
170 | Error *err = NULL; | ||
171 | |||
172 | @@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts, | ||
173 | while (filename) { | ||
174 | BlockBackend *blk; | ||
175 | BlockDriverState *bs; | ||
176 | - ImageInfo *info; | ||
177 | + BlockNodeInfo *info; | ||
178 | |||
179 | if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) { | ||
180 | error_report("Backing file '%s' creates an infinite loop.", | ||
181 | @@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts, | ||
182 | } | ||
183 | bs = blk_bs(blk); | ||
184 | |||
185 | - bdrv_query_image_info(bs, &info, &err); | ||
186 | + bdrv_query_block_node_info(bs, &info, &err); | ||
187 | if (err) { | ||
188 | error_report_err(err); | ||
189 | blk_unref(blk); | ||
190 | @@ -XXX,XX +XXX,XX @@ static ImageInfoList *collect_image_info_list(bool image_opts, | ||
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); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | -- | ||
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 |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | Introduce a new QAPI type BlockGraphInfo and an associated | ||
4 | bdrv_query_block_graph_info() function that recursively gathers | ||
5 | BlockNodeInfo objects through a block graph. | ||
6 | |||
7 | A follow-up patch is going to make "qemu-img info" use this to print | ||
8 | information about all nodes that are (usually implicitly) opened for a | ||
9 | given image file. | ||
10 | |||
11 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||
12 | Message-Id: <20220620162704.80987-8-hreitz@redhat.com> | ||
13 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | --- | ||
16 | qapi/block-core.json | 35 ++++++++++++++++++++++++++++++++ | ||
17 | include/block/qapi.h | 3 +++ | ||
18 | block/qapi.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ | ||
19 | 3 files changed, 86 insertions(+) | ||
20 | |||
21 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/qapi/block-core.json | ||
24 | +++ b/qapi/block-core.json | ||
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 | + | ||
64 | ## | ||
65 | # @ImageCheck: | ||
66 | # | ||
67 | diff --git a/include/block/qapi.h b/include/block/qapi.h | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/include/block/qapi.h | ||
70 | +++ b/include/block/qapi.h | ||
71 | @@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs, | ||
72 | bool flat, | ||
73 | bool skip_implicit_filters, | ||
74 | Error **errp); | ||
75 | +void bdrv_query_block_graph_info(BlockDriverState *bs, | ||
76 | + BlockGraphInfo **p_info, | ||
77 | + Error **errp); | ||
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(); | ||
107 | + | ||
108 | + info = g_new0(BlockGraphInfo, 1); | ||
109 | + bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp); | ||
110 | + if (*errp) { | ||
111 | + goto fail; | ||
112 | + } | ||
113 | + | ||
114 | + children_list_tail = &info->children; | ||
115 | + | ||
116 | + QLIST_FOREACH(c, &bs->children, next) { | ||
117 | + BlockChildInfo *c_info; | ||
118 | + | ||
119 | + c_info = g_new0(BlockChildInfo, 1); | ||
120 | + QAPI_LIST_APPEND(children_list_tail, c_info); | ||
121 | + | ||
122 | + c_info->name = g_strdup(c->name); | ||
123 | + bdrv_query_block_graph_info(c->bs, &c_info->info, errp); | ||
124 | + if (*errp) { | ||
125 | + goto fail; | ||
126 | + } | ||
127 | + } | ||
128 | + | ||
129 | + *p_info = info; | ||
130 | + return; | ||
131 | + | ||
132 | +fail: | ||
133 | + assert(*errp != NULL); | ||
134 | + qapi_free_BlockGraphInfo(info); | ||
135 | +} | ||
136 | + | ||
137 | /* @p_info will be set only on success. */ | ||
138 | static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, | ||
139 | Error **errp) | ||
140 | -- | ||
141 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | In order to let qemu-img info present a block graph, add a parameter to | ||
4 | bdrv_node_info_dump() and bdrv_image_info_specific_dump() so that the | ||
5 | information of nodes below the root level can be given an indentation. | ||
6 | |||
7 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||
8 | Message-Id: <20220620162704.80987-9-hreitz@redhat.com> | ||
9 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | --- | ||
12 | include/block/qapi.h | 5 ++-- | ||
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(-) | ||
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_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) | ||
57 | { | ||
58 | QObject *obj, *data; | ||
59 | Visitor *v = qobject_output_visitor_new(&obj); | ||
60 | @@ -XXX,XX +XXX,XX @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec, | ||
61 | data = qdict_get(qobject_to(QDict, obj), "data"); | ||
62 | if (!qobject_is_empty_dump(data)) { | ||
63 | if (prefix) { | ||
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); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | if (info->has_snapshots) { | ||
139 | SnapshotInfoList *elem; | ||
140 | |||
141 | - qemu_printf("Snapshot list:\n"); | ||
142 | + qemu_printf("%sSnapshot list:\n", ind_s); | ||
143 | + qemu_printf("%s", ind_s); | ||
144 | bdrv_snapshot_dump(NULL); | ||
145 | qemu_printf("\n"); | ||
146 | |||
147 | @@ -XXX,XX +XXX,XX @@ void bdrv_node_info_dump(BlockNodeInfo *info) | ||
148 | |||
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); | ||
162 | } | ||
163 | } | ||
164 | diff --git a/qemu-img.c b/qemu-img.c | ||
165 | index XXXXXXX..XXXXXXX 100644 | ||
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 | |||
191 | -- | ||
192 | 2.38.1 | diff view generated by jsdifflib |
1 | From: Max Reitz <mreitz@redhat.com> | 1 | From: Hanna Reitz <hreitz@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | To disallow certain refcount_bits values, some _unsupported_imgopts | 3 | Before we let qemu-img info print child node information, have |
4 | invocations look like "refcount_bits=1[^0-9]", i.e. they match an | 4 | common.filter, common.rc, and iotests.py filter it from the test output |
5 | integer boundary with [^0-9]. This expression does not match the end of | 5 | so we get as few reference output changes as possible. |
6 | the string, though, so it breaks down when refcount_bits is the last | ||
7 | option (which it tends to be after the rewrite of the check script in | ||
8 | Python). | ||
9 | 6 | ||
10 | Those invocations could use \b or \> instead, but those are not | 7 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> |
11 | portable. They could use something like \([^0-9]\|$\), but that would | 8 | Message-Id: <20220620162704.80987-10-hreitz@redhat.com> |
12 | be cumbersome. To make it simple and keep the existing invocations | 9 | Tested-by: Kevin Wolf <kwolf@redhat.com> |
13 | working, just let _unsupported_imgopts match the regex against $IMGOPTS | ||
14 | plus a trailing space. | ||
15 | |||
16 | Suggested-by: Eric Blake <eblake@redhat.com> | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
18 | Message-Id: <20210210095128.22732-1-mreitz@redhat.com> | ||
19 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
20 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
21 | --- | 11 | --- |
22 | tests/qemu-iotests/common.rc | 4 +++- | 12 | tests/qemu-iotests/iotests.py | 18 +++++++++++++++--- |
23 | 1 file changed, 3 insertions(+), 1 deletion(-) | 13 | tests/qemu-iotests/common.filter | 22 ++++++++++++++-------- |
14 | tests/qemu-iotests/common.rc | 22 ++++++++++++++-------- | ||
15 | 3 files changed, 43 insertions(+), 19 deletions(-) | ||
24 | 16 | ||
17 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/tests/qemu-iotests/iotests.py | ||
20 | +++ b/tests/qemu-iotests/iotests.py | ||
21 | @@ -XXX,XX +XXX,XX @@ def qemu_img_log(*args: str, check: bool = True | ||
22 | |||
23 | def img_info_log(filename: str, filter_path: Optional[str] = None, | ||
24 | use_image_opts: bool = False, extra_args: Sequence[str] = (), | ||
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 | ||
51 | + | ||
52 | + # Drop child node info | ||
53 | + if drop_indented: | ||
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 | ||
60 | + | ||
61 | line = line.replace(filename, 'TEST_IMG') | ||
62 | line = filter_testfiles(line) | ||
63 | line = line.replace(imgfmt, 'IMGFMT') | ||
64 | diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter | ||
65 | index XXXXXXX..XXXXXXX 100644 | ||
66 | --- a/tests/qemu-iotests/common.filter | ||
67 | +++ b/tests/qemu-iotests/common.filter | ||
68 | @@ -XXX,XX +XXX,XX @@ _filter_img_info() | ||
69 | |||
70 | discard=0 | ||
71 | regex_json_spec_start='^ *"format-specific": \{' | ||
72 | + regex_json_child_start='^ *"children": \[' | ||
73 | gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ | ||
74 | -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ | ||
75 | -e "s#$TEST_DIR#TEST_DIR#g" \ | ||
76 | @@ -XXX,XX +XXX,XX @@ _filter_img_info() | ||
77 | -e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \ | ||
78 | -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \ | ||
79 | while IFS='' read -r line; do | ||
80 | - if [[ $format_specific == 1 ]]; then | ||
81 | - discard=0 | ||
82 | - elif [[ $line == "Format specific information:" ]]; then | ||
83 | - discard=1 | ||
84 | - elif [[ $line =~ $regex_json_spec_start ]]; then | ||
85 | - discard=2 | ||
86 | - regex_json_spec_end="^${line%%[^ ]*}\\},? *$" | ||
87 | + if [[ $discard == 0 ]]; then | ||
88 | + if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then | ||
89 | + discard=1 | ||
90 | + elif [[ $line =~ "Child node '/" ]]; then | ||
91 | + discard=1 | ||
92 | + elif [[ $line =~ $regex_json_spec_start ]]; then | ||
93 | + discard=2 | ||
94 | + regex_json_end="^${line%%[^ ]*}\\},? *$" | ||
95 | + elif [[ $line =~ $regex_json_child_start ]]; then | ||
96 | + discard=2 | ||
97 | + regex_json_end="^${line%%[^ ]*}\\],? *$" | ||
98 | + fi | ||
99 | fi | ||
100 | if [[ $discard == 0 ]]; then | ||
101 | echo "$line" | ||
102 | elif [[ $discard == 1 && ! $line ]]; then | ||
103 | echo | ||
104 | discard=0 | ||
105 | - elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then | ||
106 | + elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then | ||
107 | discard=0 | ||
108 | fi | ||
109 | done | ||
25 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | 110 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc |
26 | index XXXXXXX..XXXXXXX 100644 | 111 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/tests/qemu-iotests/common.rc | 112 | --- a/tests/qemu-iotests/common.rc |
28 | +++ b/tests/qemu-iotests/common.rc | 113 | +++ b/tests/qemu-iotests/common.rc |
29 | @@ -XXX,XX +XXX,XX @@ _unsupported_imgopts() | 114 | @@ -XXX,XX +XXX,XX @@ _img_info() |
30 | { | 115 | |
31 | for bad_opt | 116 | discard=0 |
32 | do | 117 | regex_json_spec_start='^ *"format-specific": \{' |
33 | - if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt" | 118 | + regex_json_child_start='^ *"children": \[' |
34 | + # Add a space so tests can match for whitespace that marks the | 119 | $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ |
35 | + # end of an option (\b or \> are not portable) | 120 | sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ |
36 | + if echo "$IMGOPTS " | grep -q 2>/dev/null "$bad_opt" | 121 | -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ |
37 | then | 122 | @@ -XXX,XX +XXX,XX @@ _img_info() |
38 | _notrun "not suitable for image option: $bad_opt" | 123 | -e "/^disk size:/ D" \ |
39 | fi | 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 | ||
40 | -- | 156 | -- |
41 | 2.29.2 | 157 | 2.38.1 |
42 | |||
43 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | These tests read size information (sometimes disk size, sometimes | ||
4 | virtual size) from qemu-img info's output. Once qemu-img starts | ||
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> | ||
11 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | tests/qemu-iotests/106 | 4 ++-- | ||
15 | tests/qemu-iotests/214 | 6 ++++-- | ||
16 | tests/qemu-iotests/308 | 4 ++-- | ||
17 | 3 files changed, 8 insertions(+), 6 deletions(-) | ||
18 | |||
19 | diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106 | ||
20 | index XXXXXXX..XXXXXXX 100755 | ||
21 | --- a/tests/qemu-iotests/106 | ||
22 | +++ b/tests/qemu-iotests/106 | ||
23 | @@ -XXX,XX +XXX,XX @@ for create_mode in off falloc full; do | ||
24 | expected_size=$((expected_size + $GROWTH_SIZE)) | ||
25 | fi | ||
26 | |||
27 | - actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') | ||
28 | + actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1) | ||
29 | actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/') | ||
30 | |||
31 | # The actual size may exceed the expected size, depending on the file | ||
32 | @@ -XXX,XX +XXX,XX @@ for growth_mode in falloc full; do | ||
33 | _make_test_img -o "extent_size_hint=0" 2G | ||
34 | $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K | ||
35 | |||
36 | - actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') | ||
37 | + actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size' | head -n 1) | ||
38 | actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/') | ||
39 | |||
40 | if [ $actual_size -lt $GROWTH_SIZE ]; then | ||
41 | diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214 | ||
42 | index XXXXXXX..XXXXXXX 100755 | ||
43 | --- a/tests/qemu-iotests/214 | ||
44 | +++ b/tests/qemu-iotests/214 | ||
45 | @@ -XXX,XX +XXX,XX @@ let data_size="8 * $cluster_size" | ||
46 | $QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \ | ||
47 | 2>&1 | _filter_qemu_io | _filter_testdir | ||
48 | sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" | | ||
49 | - sed -n '/"actual-size":/ s/[^0-9]//gp') | ||
50 | + sed -n '/"actual-size":/ s/[^0-9]//gp' | | ||
51 | + head -n 1) | ||
52 | |||
53 | _make_test_img 2M -o cluster_size=$cluster_size | ||
54 | echo "Write compressed data:" | ||
55 | @@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\ | ||
56 | _filter_qemu_io | _filter_testdir | ||
57 | |||
58 | sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" | | ||
59 | - sed -n '/"actual-size":/ s/[^0-9]//gp') | ||
60 | + sed -n '/"actual-size":/ s/[^0-9]//gp' | | ||
61 | + head -n 1) | ||
62 | |||
63 | if [ $sizeA -lt $sizeB ] | ||
64 | then | ||
65 | diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308 | ||
66 | index XXXXXXX..XXXXXXX 100755 | ||
67 | --- a/tests/qemu-iotests/308 | ||
68 | +++ b/tests/qemu-iotests/308 | ||
69 | @@ -XXX,XX +XXX,XX @@ echo | ||
70 | echo '=== Remove export ===' | ||
71 | |||
72 | # Double-check that $EXT_MP appears as a non-empty file (the raw image) | ||
73 | -$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | ||
74 | +$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1 | ||
75 | |||
76 | fuse_export_del 'export-mp' | ||
77 | |||
78 | # See that the file appears empty again | ||
79 | -$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | ||
80 | +$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1 | ||
81 | |||
82 | echo | ||
83 | echo '=== Writable export ===' | ||
84 | -- | ||
85 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Hanna Reitz <hreitz@redhat.com> | |
2 | |||
3 | For every node in the backing chain, collect its BlockGraphInfo struct | ||
4 | using bdrv_query_block_graph_info(). Print all nodes' information, | ||
5 | indenting child nodes and labelling them with a path constructed from | ||
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> | ||
26 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
27 | --- | ||
28 | qapi/block-core.json | 4 +-- | ||
29 | qemu-img.c | 69 ++++++++++++++++++++++++++------------ | ||
30 | tests/qemu-iotests/065 | 2 +- | ||
31 | tests/qemu-iotests/302.out | 5 +++ | ||
32 | 4 files changed, 56 insertions(+), 24 deletions(-) | ||
33 | |||
34 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/qapi/block-core.json | ||
37 | +++ b/qapi/block-core.json | ||
38 | @@ -XXX,XX +XXX,XX @@ | ||
39 | ## | ||
40 | # @DummyBlockCoreForceArrays: | ||
41 | # | ||
42 | -# Not used by QMP; hack to let us use BlockNodeInfoList internally | ||
43 | +# Not used by QMP; hack to let us use BlockGraphInfoList internally | ||
44 | # | ||
45 | # Since: 8.0 | ||
46 | ## | ||
47 | { 'struct': 'DummyBlockCoreForceArrays', | ||
48 | - 'data': { 'unused-block-node-info': ['BlockNodeInfo'] } } | ||
49 | + 'data': { 'unused-block-graph-info': ['BlockGraphInfo'] } } | ||
50 | diff --git a/qemu-img.c b/qemu-img.c | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/qemu-img.c | ||
53 | +++ b/qemu-img.c | ||
54 | @@ -XXX,XX +XXX,XX @@ static void dump_snapshots(BlockDriverState *bs) | ||
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 | } | ||
129 | |||
130 | /** | ||
131 | - * Open an image file chain and return an BlockNodeInfoList | ||
132 | + * Open an image file chain and return an BlockGraphInfoList | ||
133 | * | ||
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 | ||
231 | index XXXXXXX..XXXXXXX 100644 | ||
232 | --- a/tests/qemu-iotests/302.out | ||
233 | +++ b/tests/qemu-iotests/302.out | ||
234 | @@ -XXX,XX +XXX,XX @@ image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock | ||
235 | file format: raw | ||
236 | virtual size: 448 KiB (458752 bytes) | ||
237 | disk size: unavailable | ||
238 | +Child node '/file': | ||
239 | + image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock | ||
240 | + file format: nbd | ||
241 | + virtual size: 448 KiB (458752 bytes) | ||
242 | + disk size: unavailable | ||
243 | |||
244 | === Converted image info === | ||
245 | image: TEST_IMG | ||
246 | -- | ||
247 | 2.38.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Hanna Reitz <hreitz@redhat.com> | ||
1 | 2 | ||
3 | Currently, when querying a qcow2 image, qemu-img info reports something | ||
4 | like this: | ||
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> | ||
57 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
58 | --- | ||
59 | include/block/qapi.h | 2 +- | ||
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(-) | ||
65 | |||
66 | diff --git a/include/block/qapi.h b/include/block/qapi.h | ||
67 | index XXXXXXX..XXXXXXX 100644 | ||
68 | --- a/include/block/qapi.h | ||
69 | +++ b/include/block/qapi.h | ||
70 | @@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn); | ||
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); | ||
96 | } | ||
97 | |||
98 | -void bdrv_node_info_dump(BlockNodeInfo *info, int indentation) | ||
99 | +/** | ||
100 | + * Print the given @info object in human-readable form. Every field is indented | ||
101 | + * using the given @indentation (four spaces per indentation level). | ||
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) | ||
118 | { | ||
119 | char *size_buf, *dsize_buf; | ||
120 | g_autofree char *ind_s = g_strdup_printf("%*s", indentation * 4, ""); | ||
121 | |||
122 | + if (indentation == 0) { | ||
123 | + /* Top level, consider this a normal image */ | ||
124 | + protocol = false; | ||
125 | + } | ||
126 | + | ||
127 | if (!info->has_actual_size) { | ||
128 | dsize_buf = g_strdup("unavailable"); | ||
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 === | ||
182 | -- | ||
183 | 2.38.1 | diff view generated by jsdifflib |