1 | The following changes since commit 22dbfdecc3c52228d3489da3fe81da92b21197bf: | 1 | The following changes since commit 00b1faea41d283e931256aa78aa975a369ec3ae6: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20191010.0' into staging (2019-10-14 15:09:08 +0100) | 3 | Merge tag 'pull-target-arm-20230123' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2023-01-23 13:40:28 +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 a1406a9262a087d9ec9627b88da13c4590b61dae: | 9 | for you to fetch changes up to 19a9c20a68f47b133e7bc8da789f2b21831fb9b0: |
10 | 10 | ||
11 | iotests: Test large write request to qcow2 file (2019-10-14 17:12:48 +0200) | 11 | qemu-img: Change info key names for protocol nodes (2023-01-24 12:09:26 +0100) |
12 | |||
13 | v2: | ||
14 | - Rebased to resolve merge conflicts in coroutine.h | ||
12 | 15 | ||
13 | ---------------------------------------------------------------- | 16 | ---------------------------------------------------------------- |
14 | Block layer patches: | 17 | Block layer patches |
15 | 18 | ||
16 | - block: Fix crash with qcow2 partial cluster COW with small cluster | 19 | - qemu-img info: Show protocol-level information |
17 | sizes (misaligned write requests with BDRV_REQ_NO_FALLBACK) | 20 | - Move more functions to coroutines |
18 | - qcow2: Fix integer overflow potentially causing corruption with huge | 21 | - Make coroutine annotations ready for static analysis |
19 | requests | 22 | - qemu-img: Fix exit code for errors closing the image |
20 | - vhdx: Detect truncated image files | 23 | - qcow2 bitmaps: Fix theoretical corruption in error path |
21 | - tools: Support help options for --object | 24 | - pflash: Only load non-zero parts of backend image to save memory |
22 | - Various block-related replay improvements | 25 | - Code cleanup and test case improvements |
23 | - iotests/028: Fix for long $TEST_DIRs | ||
24 | 26 | ||
25 | ---------------------------------------------------------------- | 27 | ---------------------------------------------------------------- |
26 | Alberto Garcia (1): | 28 | Alberto Faria (2): |
27 | block: Reject misaligned write requests with BDRV_REQ_NO_FALLBACK | 29 | coroutine: annotate coroutine_fn for libclang |
30 | block: Add no_coroutine_fn and coroutine_mixed_fn marker | ||
31 | |||
32 | Emanuele Giuseppe Esposito (14): | ||
33 | block-coroutine-wrapper: support void functions | ||
34 | block: Convert bdrv_io_plug() to co_wrapper | ||
35 | block: Convert bdrv_io_unplug() to co_wrapper | ||
36 | block: Convert bdrv_is_inserted() to co_wrapper | ||
37 | block: Rename refresh_total_sectors to bdrv_refresh_total_sectors | ||
38 | block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed | ||
39 | block-backend: use bdrv_getlength instead of blk_getlength | ||
40 | block: use bdrv_co_refresh_total_sectors when possible | ||
41 | block: Convert bdrv_get_allocated_file_size() to co_wrapper | ||
42 | block: Convert bdrv_get_info() to co_wrapper_mixed | ||
43 | block: Convert bdrv_eject() to co_wrapper | ||
44 | block: Convert bdrv_lock_medium() to co_wrapper | ||
45 | block: Convert bdrv_debug_event() to co_wrapper_mixed | ||
46 | block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate() | ||
47 | |||
48 | Hanna Reitz (12): | ||
49 | block: Improve empty format-specific info dump | ||
50 | block/file: Add file-specific image info | ||
51 | block/vmdk: Change extent info type | ||
52 | block: Split BlockNodeInfo off of ImageInfo | ||
53 | qemu-img: Use BlockNodeInfo | ||
54 | block/qapi: Let bdrv_query_image_info() recurse | ||
55 | block/qapi: Introduce BlockGraphInfo | ||
56 | block/qapi: Add indentation to bdrv_node_info_dump() | ||
57 | iotests: Filter child node information | ||
58 | iotests/106, 214, 308: Read only one size line | ||
59 | qemu-img: Let info print block graph | ||
60 | qemu-img: Change info key names for protocol nodes | ||
28 | 61 | ||
29 | Kevin Wolf (4): | 62 | Kevin Wolf (4): |
30 | vl: Split off user_creatable_print_help() | 63 | qcow2: Fix theoretical corruption in store_bitmap() error path |
31 | qemu-io: Support help options for --object | 64 | qemu-img commit: Report errors while closing the image |
32 | qemu-img: Support help options for --object | 65 | qemu-img bitmap: Report errors while closing the image |
33 | qemu-nbd: Support help options for --object | 66 | qemu-iotests: Test qemu-img bitmap/commit exit code on error |
34 | 67 | ||
35 | Max Reitz (3): | 68 | Paolo Bonzini (2): |
36 | iotests/028: Fix for long $TEST_DIRs | 69 | qemu-io: do not reinvent the blk_pwrite_zeroes wheel |
37 | qcow2: Limit total allocation range to INT_MAX | 70 | block: remove bdrv_coroutine_enter |
38 | iotests: Test large write request to qcow2 file | ||
39 | 71 | ||
40 | Pavel Dovgaluk (6): | 72 | Philippe Mathieu-Daudé (1): |
41 | block: implement bdrv_snapshot_goto for blkreplay | 73 | block/nbd: Add missing <qemu/bswap.h> include |
42 | replay: disable default snapshot for record/replay | ||
43 | replay: update docs for record/replay with block devices | ||
44 | replay: don't drain/flush bdrv queue while RR is working | ||
45 | replay: finish record/replay before closing the disks | ||
46 | replay: add BH oneshot event for block layer | ||
47 | 74 | ||
48 | Peter Lieven (1): | 75 | Thomas Huth (2): |
49 | block/vhdx: add check for truncated image files | 76 | tests/qemu-iotests/312: Mark "quorum" as required driver |
77 | tests/qemu-iotests/262: Check for availability of "blkverify" first | ||
50 | 78 | ||
51 | docs/replay.txt | 12 +++- | 79 | Xiang Zheng (1): |
52 | include/qom/object_interfaces.h | 12 ++++ | 80 | pflash: Only read non-zero parts of backend image |
53 | include/sysemu/replay.h | 4 ++ | ||
54 | replay/replay-internal.h | 1 + | ||
55 | block/blkreplay.c | 8 +++ | ||
56 | block/block-backend.c | 9 ++- | ||
57 | block/io.c | 39 ++++++++++++- | ||
58 | block/iscsi.c | 5 +- | ||
59 | block/nfs.c | 6 +- | ||
60 | block/null.c | 4 +- | ||
61 | block/nvme.c | 6 +- | ||
62 | block/qcow2-cluster.c | 5 +- | ||
63 | block/rbd.c | 5 +- | ||
64 | block/vhdx.c | 120 ++++++++++++++++++++++++++++++++++------ | ||
65 | block/vxhs.c | 5 +- | ||
66 | cpus.c | 2 - | ||
67 | qemu-img.c | 34 +++++++----- | ||
68 | qemu-io.c | 9 ++- | ||
69 | qemu-nbd.c | 9 ++- | ||
70 | qom/object_interfaces.c | 61 ++++++++++++++++++++ | ||
71 | replay/replay-events.c | 16 ++++++ | ||
72 | replay/replay.c | 2 + | ||
73 | stubs/replay-user.c | 9 +++ | ||
74 | vl.c | 63 ++++----------------- | ||
75 | stubs/Makefile.objs | 1 + | ||
76 | tests/qemu-iotests/028 | 11 +++- | ||
77 | tests/qemu-iotests/028.out | 1 - | ||
78 | tests/qemu-iotests/268 | 55 ++++++++++++++++++ | ||
79 | tests/qemu-iotests/268.out | 7 +++ | ||
80 | tests/qemu-iotests/270 | 83 +++++++++++++++++++++++++++ | ||
81 | tests/qemu-iotests/270.out | 9 +++ | ||
82 | tests/qemu-iotests/group | 2 + | ||
83 | 32 files changed, 504 insertions(+), 111 deletions(-) | ||
84 | create mode 100644 stubs/replay-user.c | ||
85 | create mode 100755 tests/qemu-iotests/268 | ||
86 | create mode 100644 tests/qemu-iotests/268.out | ||
87 | create mode 100755 tests/qemu-iotests/270 | ||
88 | create mode 100644 tests/qemu-iotests/270.out | ||
89 | 81 | ||
82 | qapi/block-core.json | 123 +++++++- | ||
83 | include/block/block-common.h | 11 +- | ||
84 | include/block/block-io.h | 41 ++- | ||
85 | include/block/block_int-common.h | 26 +- | ||
86 | include/block/block_int-io.h | 5 +- | ||
87 | include/block/nbd.h | 1 + | ||
88 | include/block/qapi.h | 14 +- | ||
89 | include/qemu/osdep.h | 44 +++ | ||
90 | include/sysemu/block-backend-io.h | 31 +- | ||
91 | block.c | 88 +++--- | ||
92 | block/blkdebug.c | 11 +- | ||
93 | block/blkio.c | 15 +- | ||
94 | block/blklogwrites.c | 6 +- | ||
95 | block/blkreplay.c | 6 +- | ||
96 | block/blkverify.c | 6 +- | ||
97 | block/block-backend.c | 38 +-- | ||
98 | block/commit.c | 4 +- | ||
99 | block/copy-on-read.c | 18 +- | ||
100 | block/crypto.c | 14 +- | ||
101 | block/curl.c | 10 +- | ||
102 | block/file-posix.c | 137 +++++---- | ||
103 | block/file-win32.c | 18 +- | ||
104 | block/filter-compress.c | 20 +- | ||
105 | block/gluster.c | 23 +- | ||
106 | block/io.c | 76 ++--- | ||
107 | block/iscsi.c | 17 +- | ||
108 | block/mirror.c | 6 +- | ||
109 | block/monitor/block-hmp-cmds.c | 2 +- | ||
110 | block/nbd.c | 8 +- | ||
111 | block/nfs.c | 4 +- | ||
112 | block/null.c | 13 +- | ||
113 | block/nvme.c | 14 +- | ||
114 | block/preallocate.c | 16 +- | ||
115 | block/qapi.c | 317 ++++++++++++++++----- | ||
116 | block/qcow.c | 5 +- | ||
117 | block/qcow2-bitmap.c | 5 +- | ||
118 | block/qcow2-refcount.c | 2 +- | ||
119 | block/qcow2.c | 17 +- | ||
120 | block/qed.c | 11 +- | ||
121 | block/quorum.c | 8 +- | ||
122 | block/raw-format.c | 25 +- | ||
123 | block/rbd.c | 9 +- | ||
124 | block/replication.c | 6 +- | ||
125 | block/ssh.c | 4 +- | ||
126 | block/throttle.c | 6 +- | ||
127 | block/vdi.c | 7 +- | ||
128 | block/vhdx.c | 5 +- | ||
129 | block/vmdk.c | 22 +- | ||
130 | block/vpc.c | 5 +- | ||
131 | blockdev.c | 8 +- | ||
132 | hw/block/block.c | 36 ++- | ||
133 | hw/scsi/scsi-disk.c | 5 + | ||
134 | qemu-img.c | 100 +++++-- | ||
135 | qemu-io-cmds.c | 62 +--- | ||
136 | tests/unit/test-block-iothread.c | 3 + | ||
137 | scripts/block-coroutine-wrapper.py | 20 +- | ||
138 | tests/qemu-iotests/iotests.py | 18 +- | ||
139 | block/meson.build | 1 + | ||
140 | tests/qemu-iotests/065 | 2 +- | ||
141 | tests/qemu-iotests/106 | 4 +- | ||
142 | tests/qemu-iotests/214 | 6 +- | ||
143 | tests/qemu-iotests/262 | 3 +- | ||
144 | tests/qemu-iotests/302.out | 5 + | ||
145 | tests/qemu-iotests/308 | 4 +- | ||
146 | tests/qemu-iotests/312 | 1 + | ||
147 | tests/qemu-iotests/common.filter | 22 +- | ||
148 | tests/qemu-iotests/common.rc | 22 +- | ||
149 | tests/qemu-iotests/tests/qemu-img-close-errors | 95 ++++++ | ||
150 | tests/qemu-iotests/tests/qemu-img-close-errors.out | 23 ++ | ||
151 | 69 files changed, 1208 insertions(+), 552 deletions(-) | ||
152 | create mode 100755 tests/qemu-iotests/tests/qemu-img-close-errors | ||
153 | create mode 100644 tests/qemu-iotests/tests/qemu-img-close-errors.out | ||
154 | |||
155 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Peter Lieven <pl@kamp.de> | ||
2 | 1 | ||
3 | qemu is currently not able to detect truncated vhdx image files. | ||
4 | Add a basic check if all allocated blocks are reachable at open and | ||
5 | report all errors during bdrv_co_check. | ||
6 | |||
7 | Signed-off-by: Peter Lieven <pl@kamp.de> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | --- | ||
10 | block/vhdx.c | 120 +++++++++++++++++++++++++++++++++++++++++++-------- | ||
11 | 1 file changed, 103 insertions(+), 17 deletions(-) | ||
12 | |||
13 | diff --git a/block/vhdx.c b/block/vhdx.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/block/vhdx.c | ||
16 | +++ b/block/vhdx.c | ||
17 | @@ -XXX,XX +XXX,XX @@ | ||
18 | #include "qemu/option.h" | ||
19 | #include "qemu/crc32c.h" | ||
20 | #include "qemu/bswap.h" | ||
21 | +#include "qemu/error-report.h" | ||
22 | #include "vhdx.h" | ||
23 | #include "migration/blocker.h" | ||
24 | #include "qemu/uuid.h" | ||
25 | @@ -XXX,XX +XXX,XX @@ static int vhdx_region_check(BDRVVHDXState *s, uint64_t start, uint64_t length) | ||
26 | end = start + length; | ||
27 | QLIST_FOREACH(r, &s->regions, entries) { | ||
28 | if (!((start >= r->end) || (end <= r->start))) { | ||
29 | + error_report("VHDX region %" PRIu64 "-%" PRIu64 " overlaps with " | ||
30 | + "region %" PRIu64 "-%." PRIu64, start, end, r->start, | ||
31 | + r->end); | ||
32 | ret = -EINVAL; | ||
33 | goto exit; | ||
34 | } | ||
35 | @@ -XXX,XX +XXX,XX @@ static void vhdx_calc_bat_entries(BDRVVHDXState *s) | ||
36 | |||
37 | } | ||
38 | |||
39 | +static int vhdx_check_bat_entries(BlockDriverState *bs, int *errcnt) | ||
40 | +{ | ||
41 | + BDRVVHDXState *s = bs->opaque; | ||
42 | + int64_t image_file_size = bdrv_getlength(bs->file->bs); | ||
43 | + uint64_t payblocks = s->chunk_ratio; | ||
44 | + uint64_t i; | ||
45 | + int ret = 0; | ||
46 | + | ||
47 | + if (image_file_size < 0) { | ||
48 | + error_report("Could not determinate VHDX image file size."); | ||
49 | + return image_file_size; | ||
50 | + } | ||
51 | + | ||
52 | + for (i = 0; i < s->bat_entries; i++) { | ||
53 | + if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) == | ||
54 | + PAYLOAD_BLOCK_FULLY_PRESENT) { | ||
55 | + uint64_t offset = s->bat[i] & VHDX_BAT_FILE_OFF_MASK; | ||
56 | + /* | ||
57 | + * Allow that the last block exists only partially. The VHDX spec | ||
58 | + * states that the image file can only grow in blocksize increments, | ||
59 | + * but QEMU created images with partial last blocks in the past. | ||
60 | + */ | ||
61 | + uint32_t block_length = MIN(s->block_size, | ||
62 | + bs->total_sectors * BDRV_SECTOR_SIZE - i * s->block_size); | ||
63 | + /* | ||
64 | + * Check for BAT entry overflow. | ||
65 | + */ | ||
66 | + if (offset > INT64_MAX - s->block_size) { | ||
67 | + error_report("VHDX BAT entry %" PRIu64 " offset overflow.", i); | ||
68 | + ret = -EINVAL; | ||
69 | + if (!errcnt) { | ||
70 | + break; | ||
71 | + } | ||
72 | + (*errcnt)++; | ||
73 | + } | ||
74 | + /* | ||
75 | + * Check if fully allocated BAT entries do not reside after | ||
76 | + * end of the image file. | ||
77 | + */ | ||
78 | + if (offset >= image_file_size) { | ||
79 | + error_report("VHDX BAT entry %" PRIu64 " start offset %" PRIu64 | ||
80 | + " points after end of file (%" PRIi64 "). Image" | ||
81 | + " has probably been truncated.", | ||
82 | + i, offset, image_file_size); | ||
83 | + ret = -EINVAL; | ||
84 | + if (!errcnt) { | ||
85 | + break; | ||
86 | + } | ||
87 | + (*errcnt)++; | ||
88 | + } else if (offset + block_length > image_file_size) { | ||
89 | + error_report("VHDX BAT entry %" PRIu64 " end offset %" PRIu64 | ||
90 | + " points after end of file (%" PRIi64 "). Image" | ||
91 | + " has probably been truncated.", | ||
92 | + i, offset + block_length - 1, image_file_size); | ||
93 | + ret = -EINVAL; | ||
94 | + if (!errcnt) { | ||
95 | + break; | ||
96 | + } | ||
97 | + (*errcnt)++; | ||
98 | + } | ||
99 | + | ||
100 | + /* | ||
101 | + * verify populated BAT field file offsets against | ||
102 | + * region table and log entries | ||
103 | + */ | ||
104 | + if (payblocks--) { | ||
105 | + /* payload bat entries */ | ||
106 | + int ret2; | ||
107 | + ret2 = vhdx_region_check(s, offset, s->block_size); | ||
108 | + if (ret2 < 0) { | ||
109 | + ret = -EINVAL; | ||
110 | + if (!errcnt) { | ||
111 | + break; | ||
112 | + } | ||
113 | + (*errcnt)++; | ||
114 | + } | ||
115 | + } else { | ||
116 | + payblocks = s->chunk_ratio; | ||
117 | + /* | ||
118 | + * Once differencing files are supported, verify sector bitmap | ||
119 | + * blocks here | ||
120 | + */ | ||
121 | + } | ||
122 | + } | ||
123 | + } | ||
124 | + | ||
125 | + return ret; | ||
126 | +} | ||
127 | + | ||
128 | static void vhdx_close(BlockDriverState *bs) | ||
129 | { | ||
130 | BDRVVHDXState *s = bs->opaque; | ||
131 | @@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, | ||
132 | goto fail; | ||
133 | } | ||
134 | |||
135 | - uint64_t payblocks = s->chunk_ratio; | ||
136 | - /* endian convert, and verify populated BAT field file offsets against | ||
137 | - * region table and log entries */ | ||
138 | + /* endian convert populated BAT field entires */ | ||
139 | for (i = 0; i < s->bat_entries; i++) { | ||
140 | s->bat[i] = le64_to_cpu(s->bat[i]); | ||
141 | - if (payblocks--) { | ||
142 | - /* payload bat entries */ | ||
143 | - if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) == | ||
144 | - PAYLOAD_BLOCK_FULLY_PRESENT) { | ||
145 | - ret = vhdx_region_check(s, s->bat[i] & VHDX_BAT_FILE_OFF_MASK, | ||
146 | - s->block_size); | ||
147 | - if (ret < 0) { | ||
148 | - goto fail; | ||
149 | - } | ||
150 | - } | ||
151 | - } else { | ||
152 | - payblocks = s->chunk_ratio; | ||
153 | - /* Once differencing files are supported, verify sector bitmap | ||
154 | - * blocks here */ | ||
155 | + } | ||
156 | + | ||
157 | + if (!(flags & BDRV_O_CHECK)) { | ||
158 | + ret = vhdx_check_bat_entries(bs, NULL); | ||
159 | + if (ret < 0) { | ||
160 | + goto fail; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_check(BlockDriverState *bs, | ||
165 | if (s->log_replayed_on_open) { | ||
166 | result->corruptions_fixed++; | ||
167 | } | ||
168 | + | ||
169 | + vhdx_check_bat_entries(bs, &result->corruptions); | ||
170 | + | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | -- | ||
175 | 2.20.1 | ||
176 | |||
177 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> | ||
2 | 1 | ||
3 | This patch enables making snapshots with blkreplay used in | ||
4 | block devices. | ||
5 | This function is required to make bdrv_snapshot_goto without | ||
6 | calling .bdrv_open which is not implemented. | ||
7 | |||
8 | Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> | ||
9 | Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | --- | ||
12 | block/blkreplay.c | 8 ++++++++ | ||
13 | 1 file changed, 8 insertions(+) | ||
14 | |||
15 | diff --git a/block/blkreplay.c b/block/blkreplay.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/block/blkreplay.c | ||
18 | +++ b/block/blkreplay.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs) | ||
20 | return ret; | ||
21 | } | ||
22 | |||
23 | +static int blkreplay_snapshot_goto(BlockDriverState *bs, | ||
24 | + const char *snapshot_id) | ||
25 | +{ | ||
26 | + return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL); | ||
27 | +} | ||
28 | + | ||
29 | static BlockDriver bdrv_blkreplay = { | ||
30 | .format_name = "blkreplay", | ||
31 | .instance_size = 0, | ||
32 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkreplay = { | ||
33 | .bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes, | ||
34 | .bdrv_co_pdiscard = blkreplay_co_pdiscard, | ||
35 | .bdrv_co_flush = blkreplay_co_flush, | ||
36 | + | ||
37 | + .bdrv_snapshot_goto = blkreplay_snapshot_goto, | ||
38 | }; | ||
39 | |||
40 | static void bdrv_blkreplay_init(void) | ||
41 | -- | ||
42 | 2.20.1 | ||
43 | |||
44 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> | ||
2 | 1 | ||
3 | This patch disables setting '-snapshot' option on by default | ||
4 | in record/replay mode. This is needed for creating vmstates in record | ||
5 | and replay modes. | ||
6 | |||
7 | Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> | ||
8 | Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | vl.c | 10 ++++++++-- | ||
12 | 1 file changed, 8 insertions(+), 2 deletions(-) | ||
13 | |||
14 | diff --git a/vl.c b/vl.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/vl.c | ||
17 | +++ b/vl.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static void configure_blockdev(BlockdevOptionsQueue *bdo_queue, | ||
19 | qapi_free_BlockdevOptions(bdo->bdo); | ||
20 | g_free(bdo); | ||
21 | } | ||
22 | - if (snapshot || replay_mode != REPLAY_MODE_NONE) { | ||
23 | + if (snapshot) { | ||
24 | qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, | ||
25 | NULL, NULL); | ||
26 | } | ||
27 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp) | ||
28 | drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS); | ||
29 | break; | ||
30 | case QEMU_OPTION_snapshot: | ||
31 | - snapshot = 1; | ||
32 | + { | ||
33 | + Error *blocker = NULL; | ||
34 | + snapshot = 1; | ||
35 | + error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, | ||
36 | + "-snapshot"); | ||
37 | + replay_add_blocker(blocker); | ||
38 | + } | ||
39 | break; | ||
40 | case QEMU_OPTION_numa: | ||
41 | opts = qemu_opts_parse_noisily(qemu_find_opts("numa"), | ||
42 | -- | ||
43 | 2.20.1 | ||
44 | |||
45 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
2 | 1 | ||
3 | This patch updates the description of the command lines for using | ||
4 | record/replay with attached block devices. | ||
5 | |||
6 | Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
8 | --- | ||
9 | docs/replay.txt | 12 +++++++++--- | ||
10 | 1 file changed, 9 insertions(+), 3 deletions(-) | ||
11 | |||
12 | diff --git a/docs/replay.txt b/docs/replay.txt | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/docs/replay.txt | ||
15 | +++ b/docs/replay.txt | ||
16 | @@ -XXX,XX +XXX,XX @@ Usage of the record/replay: | ||
17 | * First, record the execution with the following command line: | ||
18 | qemu-system-i386 \ | ||
19 | -icount shift=7,rr=record,rrfile=replay.bin \ | ||
20 | - -drive file=disk.qcow2,if=none,id=img-direct \ | ||
21 | + -drive file=disk.qcow2,if=none,snapshot,id=img-direct \ | ||
22 | -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \ | ||
23 | -device ide-hd,drive=img-blkreplay \ | ||
24 | -netdev user,id=net1 -device rtl8139,netdev=net1 \ | ||
25 | @@ -XXX,XX +XXX,XX @@ Usage of the record/replay: | ||
26 | * After recording, you can replay it by using another command line: | ||
27 | qemu-system-i386 \ | ||
28 | -icount shift=7,rr=replay,rrfile=replay.bin \ | ||
29 | - -drive file=disk.qcow2,if=none,id=img-direct \ | ||
30 | + -drive file=disk.qcow2,if=none,snapshot,id=img-direct \ | ||
31 | -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \ | ||
32 | -device ide-hd,drive=img-blkreplay \ | ||
33 | -netdev user,id=net1 -device rtl8139,netdev=net1 \ | ||
34 | @@ -XXX,XX +XXX,XX @@ Block devices record/replay module intercepts calls of | ||
35 | bdrv coroutine functions at the top of block drivers stack. | ||
36 | To record and replay block operations the drive must be configured | ||
37 | as following: | ||
38 | - -drive file=disk.qcow2,if=none,id=img-direct | ||
39 | + -drive file=disk.qcow2,if=none,snapshot,id=img-direct | ||
40 | -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay | ||
41 | -device ide-hd,drive=img-blkreplay | ||
42 | |||
43 | @@ -XXX,XX +XXX,XX @@ This snapshot is created at start of recording and restored at start | ||
44 | of replaying. It also can be loaded while replaying to roll back | ||
45 | the execution. | ||
46 | |||
47 | +'snapshot' flag of the disk image must be removed to save the snapshots | ||
48 | +in the overlay (or original image) instead of using the temporary overlay. | ||
49 | + -drive file=disk.ovl,if=none,id=img-direct | ||
50 | + -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay | ||
51 | + -device ide-hd,drive=img-blkreplay | ||
52 | + | ||
53 | Use QEMU monitor to create additional snapshots. 'savevm <name>' command | ||
54 | created the snapshot and 'loadvm <name>' restores it. To prevent corruption | ||
55 | of the original disk image, use overlay files linked to the original images. | ||
56 | -- | ||
57 | 2.20.1 | ||
58 | |||
59 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
2 | 1 | ||
3 | In record/replay mode bdrv queue is controlled by replay mechanism. | ||
4 | It does not allow saving or loading the snapshots | ||
5 | when bdrv queue is not empty. Stopping the VM is not blocked by nonempty | ||
6 | queue, but flushing the queue is still impossible there, | ||
7 | because it may cause deadlocks in replay mode. | ||
8 | This patch disables bdrv_drain_all and bdrv_flush_all in | ||
9 | record/replay mode. | ||
10 | |||
11 | Stopping the machine when the IO requests are not finished is needed | ||
12 | for the debugging. E.g., breakpoint may be set at the specified step, | ||
13 | and forcing the IO requests to finish may break the determinism | ||
14 | of the execution. | ||
15 | |||
16 | Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> | ||
17 | Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
19 | --- | ||
20 | block/io.c | 28 ++++++++++++++++++++++++++++ | ||
21 | cpus.c | 2 -- | ||
22 | 2 files changed, 28 insertions(+), 2 deletions(-) | ||
23 | |||
24 | diff --git a/block/io.c b/block/io.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/block/io.c | ||
27 | +++ b/block/io.c | ||
28 | @@ -XXX,XX +XXX,XX @@ | ||
29 | #include "qapi/error.h" | ||
30 | #include "qemu/error-report.h" | ||
31 | #include "qemu/main-loop.h" | ||
32 | +#include "sysemu/replay.h" | ||
33 | |||
34 | #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ | ||
35 | |||
36 | @@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void) | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | + /* | ||
41 | + * bdrv queue is managed by record/replay, | ||
42 | + * waiting for finishing the I/O requests may | ||
43 | + * be infinite | ||
44 | + */ | ||
45 | + if (replay_events_enabled()) { | ||
46 | + return; | ||
47 | + } | ||
48 | + | ||
49 | /* AIO_WAIT_WHILE() with a NULL context can only be called from the main | ||
50 | * loop AioContext, so make sure we're in the main context. */ | ||
51 | assert(qemu_get_current_aio_context() == qemu_get_aio_context()); | ||
52 | @@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void) | ||
53 | BlockDriverState *bs = NULL; | ||
54 | int drained_end_counter = 0; | ||
55 | |||
56 | + /* | ||
57 | + * bdrv queue is managed by record/replay, | ||
58 | + * waiting for finishing the I/O requests may | ||
59 | + * be endless | ||
60 | + */ | ||
61 | + if (replay_events_enabled()) { | ||
62 | + return; | ||
63 | + } | ||
64 | + | ||
65 | while ((bs = bdrv_next_all_states(bs))) { | ||
66 | AioContext *aio_context = bdrv_get_aio_context(bs); | ||
67 | |||
68 | @@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void) | ||
69 | BlockDriverState *bs = NULL; | ||
70 | int result = 0; | ||
71 | |||
72 | + /* | ||
73 | + * bdrv queue is managed by record/replay, | ||
74 | + * creating new flush request for stopping | ||
75 | + * the VM may break the determinism | ||
76 | + */ | ||
77 | + if (replay_events_enabled()) { | ||
78 | + return result; | ||
79 | + } | ||
80 | + | ||
81 | for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { | ||
82 | AioContext *aio_context = bdrv_get_aio_context(bs); | ||
83 | int ret; | ||
84 | diff --git a/cpus.c b/cpus.c | ||
85 | index XXXXXXX..XXXXXXX 100644 | ||
86 | --- a/cpus.c | ||
87 | +++ b/cpus.c | ||
88 | @@ -XXX,XX +XXX,XX @@ static int do_vm_stop(RunState state, bool send_stop) | ||
89 | } | ||
90 | |||
91 | bdrv_drain_all(); | ||
92 | - replay_disable_events(); | ||
93 | ret = bdrv_flush_all(); | ||
94 | |||
95 | return ret; | ||
96 | @@ -XXX,XX +XXX,XX @@ int vm_prepare_start(void) | ||
97 | /* We are sending this now, but the CPUs will be resumed shortly later */ | ||
98 | qapi_event_send_resume(); | ||
99 | |||
100 | - replay_enable_events(); | ||
101 | cpu_enable_ticks(); | ||
102 | runstate_set(RUN_STATE_RUNNING); | ||
103 | vm_state_notify(1, RUN_STATE_RUNNING); | ||
104 | -- | ||
105 | 2.20.1 | ||
106 | |||
107 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
2 | 1 | ||
3 | After recent updates block devices cannot be closed on qemu exit. | ||
4 | This happens due to the block request polling when replay is not finished. | ||
5 | Therefore now we stop execution recording before closing the block devices. | ||
6 | |||
7 | Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | --- | ||
10 | replay/replay.c | 2 ++ | ||
11 | vl.c | 1 + | ||
12 | 2 files changed, 3 insertions(+) | ||
13 | |||
14 | diff --git a/replay/replay.c b/replay/replay.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/replay/replay.c | ||
17 | +++ b/replay/replay.c | ||
18 | @@ -XXX,XX +XXX,XX @@ void replay_finish(void) | ||
19 | g_free(replay_snapshot); | ||
20 | replay_snapshot = NULL; | ||
21 | |||
22 | + replay_mode = REPLAY_MODE_NONE; | ||
23 | + | ||
24 | replay_finish_events(); | ||
25 | } | ||
26 | |||
27 | diff --git a/vl.c b/vl.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/vl.c | ||
30 | +++ b/vl.c | ||
31 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp) | ||
32 | |||
33 | /* No more vcpu or device emulation activity beyond this point */ | ||
34 | vm_shutdown(); | ||
35 | + replay_finish(); | ||
36 | |||
37 | job_cancel_sync_all(); | ||
38 | bdrv_close_all(); | ||
39 | -- | ||
40 | 2.20.1 | ||
41 | |||
42 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
2 | 1 | ||
3 | Replay is capable of recording normal BH events, but sometimes | ||
4 | there are single use callbacks scheduled with aio_bh_schedule_oneshot | ||
5 | function. This patch enables recording and replaying such callbacks. | ||
6 | Block layer uses these events for calling the completion function. | ||
7 | Replaying these calls makes the execution deterministic. | ||
8 | |||
9 | Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
10 | Acked-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | --- | ||
13 | include/sysemu/replay.h | 4 ++++ | ||
14 | replay/replay-internal.h | 1 + | ||
15 | block/block-backend.c | 9 ++++++--- | ||
16 | block/io.c | 4 ++-- | ||
17 | block/iscsi.c | 5 +++-- | ||
18 | block/nfs.c | 6 ++++-- | ||
19 | block/null.c | 4 +++- | ||
20 | block/nvme.c | 6 ++++-- | ||
21 | block/rbd.c | 5 +++-- | ||
22 | block/vxhs.c | 5 +++-- | ||
23 | replay/replay-events.c | 16 ++++++++++++++++ | ||
24 | stubs/replay-user.c | 9 +++++++++ | ||
25 | stubs/Makefile.objs | 1 + | ||
26 | 13 files changed, 59 insertions(+), 16 deletions(-) | ||
27 | create mode 100644 stubs/replay-user.c | ||
28 | |||
29 | diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/include/sysemu/replay.h | ||
32 | +++ b/include/sysemu/replay.h | ||
33 | @@ -XXX,XX +XXX,XX @@ | ||
34 | #include "qapi/qapi-types-misc.h" | ||
35 | #include "qapi/qapi-types-run-state.h" | ||
36 | #include "qapi/qapi-types-ui.h" | ||
37 | +#include "block/aio.h" | ||
38 | |||
39 | /* replay clock kinds */ | ||
40 | enum ReplayClockKind { | ||
41 | @@ -XXX,XX +XXX,XX @@ void replay_enable_events(void); | ||
42 | bool replay_events_enabled(void); | ||
43 | /*! Adds bottom half event to the queue */ | ||
44 | void replay_bh_schedule_event(QEMUBH *bh); | ||
45 | +/* Adds oneshot bottom half event to the queue */ | ||
46 | +void replay_bh_schedule_oneshot_event(AioContext *ctx, | ||
47 | + QEMUBHFunc *cb, void *opaque); | ||
48 | /*! Adds input event to the queue */ | ||
49 | void replay_input_event(QemuConsole *src, InputEvent *evt); | ||
50 | /*! Adds input sync event to the queue */ | ||
51 | diff --git a/replay/replay-internal.h b/replay/replay-internal.h | ||
52 | index XXXXXXX..XXXXXXX 100644 | ||
53 | --- a/replay/replay-internal.h | ||
54 | +++ b/replay/replay-internal.h | ||
55 | @@ -XXX,XX +XXX,XX @@ enum ReplayEvents { | ||
56 | |||
57 | enum ReplayAsyncEventKind { | ||
58 | REPLAY_ASYNC_EVENT_BH, | ||
59 | + REPLAY_ASYNC_EVENT_BH_ONESHOT, | ||
60 | REPLAY_ASYNC_EVENT_INPUT, | ||
61 | REPLAY_ASYNC_EVENT_INPUT_SYNC, | ||
62 | REPLAY_ASYNC_EVENT_CHAR_READ, | ||
63 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
64 | index XXXXXXX..XXXXXXX 100644 | ||
65 | --- a/block/block-backend.c | ||
66 | +++ b/block/block-backend.c | ||
67 | @@ -XXX,XX +XXX,XX @@ | ||
68 | #include "hw/qdev-core.h" | ||
69 | #include "sysemu/blockdev.h" | ||
70 | #include "sysemu/runstate.h" | ||
71 | +#include "sysemu/sysemu.h" | ||
72 | +#include "sysemu/replay.h" | ||
73 | #include "qapi/error.h" | ||
74 | #include "qapi/qapi-events-block.h" | ||
75 | #include "qemu/id.h" | ||
76 | @@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk, | ||
77 | acb->blk = blk; | ||
78 | acb->ret = ret; | ||
79 | |||
80 | - aio_bh_schedule_oneshot(blk_get_aio_context(blk), error_callback_bh, acb); | ||
81 | + replay_bh_schedule_oneshot_event(blk_get_aio_context(blk), | ||
82 | + error_callback_bh, acb); | ||
83 | return &acb->common; | ||
84 | } | ||
85 | |||
86 | @@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes, | ||
87 | |||
88 | acb->has_returned = true; | ||
89 | if (acb->rwco.ret != NOT_DONE) { | ||
90 | - aio_bh_schedule_oneshot(blk_get_aio_context(blk), | ||
91 | - blk_aio_complete_bh, acb); | ||
92 | + replay_bh_schedule_oneshot_event(blk_get_aio_context(blk), | ||
93 | + blk_aio_complete_bh, acb); | ||
94 | } | ||
95 | |||
96 | return &acb->common; | ||
97 | diff --git a/block/io.c b/block/io.c | ||
98 | index XXXXXXX..XXXXXXX 100644 | ||
99 | --- a/block/io.c | ||
100 | +++ b/block/io.c | ||
101 | @@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, | ||
102 | if (bs) { | ||
103 | bdrv_inc_in_flight(bs); | ||
104 | } | ||
105 | - aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), | ||
106 | - bdrv_co_drain_bh_cb, &data); | ||
107 | + replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs), | ||
108 | + bdrv_co_drain_bh_cb, &data); | ||
109 | |||
110 | qemu_coroutine_yield(); | ||
111 | /* If we are resumed from some other event (such as an aio completion or a | ||
112 | diff --git a/block/iscsi.c b/block/iscsi.c | ||
113 | index XXXXXXX..XXXXXXX 100644 | ||
114 | --- a/block/iscsi.c | ||
115 | +++ b/block/iscsi.c | ||
116 | @@ -XXX,XX +XXX,XX @@ | ||
117 | #include "qemu/module.h" | ||
118 | #include "qemu/option.h" | ||
119 | #include "qemu/uuid.h" | ||
120 | +#include "sysemu/replay.h" | ||
121 | #include "qapi/error.h" | ||
122 | #include "qapi/qapi-commands-misc.h" | ||
123 | #include "qapi/qmp/qdict.h" | ||
124 | @@ -XXX,XX +XXX,XX @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, | ||
125 | } | ||
126 | |||
127 | if (iTask->co) { | ||
128 | - aio_bh_schedule_oneshot(iTask->iscsilun->aio_context, | ||
129 | - iscsi_co_generic_bh_cb, iTask); | ||
130 | + replay_bh_schedule_oneshot_event(iTask->iscsilun->aio_context, | ||
131 | + iscsi_co_generic_bh_cb, iTask); | ||
132 | } else { | ||
133 | iTask->complete = 1; | ||
134 | } | ||
135 | diff --git a/block/nfs.c b/block/nfs.c | ||
136 | index XXXXXXX..XXXXXXX 100644 | ||
137 | --- a/block/nfs.c | ||
138 | +++ b/block/nfs.c | ||
139 | @@ -XXX,XX +XXX,XX @@ | ||
140 | #include "qemu/option.h" | ||
141 | #include "qemu/uri.h" | ||
142 | #include "qemu/cutils.h" | ||
143 | +#include "sysemu/sysemu.h" | ||
144 | +#include "sysemu/replay.h" | ||
145 | #include "qapi/qapi-visit-block-core.h" | ||
146 | #include "qapi/qmp/qdict.h" | ||
147 | #include "qapi/qmp/qstring.h" | ||
148 | @@ -XXX,XX +XXX,XX @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data, | ||
149 | if (task->ret < 0) { | ||
150 | error_report("NFS Error: %s", nfs_get_error(nfs)); | ||
151 | } | ||
152 | - aio_bh_schedule_oneshot(task->client->aio_context, | ||
153 | - nfs_co_generic_bh_cb, task); | ||
154 | + replay_bh_schedule_oneshot_event(task->client->aio_context, | ||
155 | + nfs_co_generic_bh_cb, task); | ||
156 | } | ||
157 | |||
158 | static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset, | ||
159 | diff --git a/block/null.c b/block/null.c | ||
160 | index XXXXXXX..XXXXXXX 100644 | ||
161 | --- a/block/null.c | ||
162 | +++ b/block/null.c | ||
163 | @@ -XXX,XX +XXX,XX @@ | ||
164 | #include "qemu/module.h" | ||
165 | #include "qemu/option.h" | ||
166 | #include "block/block_int.h" | ||
167 | +#include "sysemu/replay.h" | ||
168 | |||
169 | #define NULL_OPT_LATENCY "latency-ns" | ||
170 | #define NULL_OPT_ZEROES "read-zeroes" | ||
171 | @@ -XXX,XX +XXX,XX @@ static inline BlockAIOCB *null_aio_common(BlockDriverState *bs, | ||
172 | timer_mod_ns(&acb->timer, | ||
173 | qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns); | ||
174 | } else { | ||
175 | - aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), null_bh_cb, acb); | ||
176 | + replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs), | ||
177 | + null_bh_cb, acb); | ||
178 | } | ||
179 | return &acb->common; | ||
180 | } | ||
181 | diff --git a/block/nvme.c b/block/nvme.c | ||
182 | index XXXXXXX..XXXXXXX 100644 | ||
183 | --- a/block/nvme.c | ||
184 | +++ b/block/nvme.c | ||
185 | @@ -XXX,XX +XXX,XX @@ | ||
186 | #include "qemu/option.h" | ||
187 | #include "qemu/vfio-helpers.h" | ||
188 | #include "block/block_int.h" | ||
189 | +#include "sysemu/replay.h" | ||
190 | #include "trace.h" | ||
191 | |||
192 | #include "block/nvme.h" | ||
193 | @@ -XXX,XX +XXX,XX @@ static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q) | ||
194 | smp_mb_release(); | ||
195 | *q->cq.doorbell = cpu_to_le32(q->cq.head); | ||
196 | if (!qemu_co_queue_empty(&q->free_req_queue)) { | ||
197 | - aio_bh_schedule_oneshot(s->aio_context, nvme_free_req_queue_cb, q); | ||
198 | + replay_bh_schedule_oneshot_event(s->aio_context, | ||
199 | + nvme_free_req_queue_cb, q); | ||
200 | } | ||
201 | } | ||
202 | q->busy = false; | ||
203 | @@ -XXX,XX +XXX,XX @@ static void nvme_rw_cb(void *opaque, int ret) | ||
204 | /* The rw coroutine hasn't yielded, don't try to enter. */ | ||
205 | return; | ||
206 | } | ||
207 | - aio_bh_schedule_oneshot(data->ctx, nvme_rw_cb_bh, data); | ||
208 | + replay_bh_schedule_oneshot_event(data->ctx, nvme_rw_cb_bh, data); | ||
209 | } | ||
210 | |||
211 | static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs, | ||
212 | diff --git a/block/rbd.c b/block/rbd.c | ||
213 | index XXXXXXX..XXXXXXX 100644 | ||
214 | --- a/block/rbd.c | ||
215 | +++ b/block/rbd.c | ||
216 | @@ -XXX,XX +XXX,XX @@ | ||
217 | #include "block/qdict.h" | ||
218 | #include "crypto/secret.h" | ||
219 | #include "qemu/cutils.h" | ||
220 | +#include "sysemu/replay.h" | ||
221 | #include "qapi/qmp/qstring.h" | ||
222 | #include "qapi/qmp/qdict.h" | ||
223 | #include "qapi/qmp/qjson.h" | ||
224 | @@ -XXX,XX +XXX,XX @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb) | ||
225 | rcb->ret = rbd_aio_get_return_value(c); | ||
226 | rbd_aio_release(c); | ||
227 | |||
228 | - aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs), | ||
229 | - rbd_finish_bh, rcb); | ||
230 | + replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs), | ||
231 | + rbd_finish_bh, rcb); | ||
232 | } | ||
233 | |||
234 | static int rbd_aio_discard_wrapper(rbd_image_t image, | ||
235 | diff --git a/block/vxhs.c b/block/vxhs.c | ||
236 | index XXXXXXX..XXXXXXX 100644 | ||
237 | --- a/block/vxhs.c | ||
238 | +++ b/block/vxhs.c | ||
239 | @@ -XXX,XX +XXX,XX @@ | ||
240 | #include "qapi/error.h" | ||
241 | #include "qemu/uuid.h" | ||
242 | #include "crypto/tlscredsx509.h" | ||
243 | +#include "sysemu/replay.h" | ||
244 | |||
245 | #define VXHS_OPT_FILENAME "filename" | ||
246 | #define VXHS_OPT_VDISK_ID "vdisk-id" | ||
247 | @@ -XXX,XX +XXX,XX @@ static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error) | ||
248 | trace_vxhs_iio_callback(error); | ||
249 | } | ||
250 | |||
251 | - aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs), | ||
252 | - vxhs_complete_aio_bh, acb); | ||
253 | + replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs), | ||
254 | + vxhs_complete_aio_bh, acb); | ||
255 | break; | ||
256 | |||
257 | default: | ||
258 | diff --git a/replay/replay-events.c b/replay/replay-events.c | ||
259 | index XXXXXXX..XXXXXXX 100644 | ||
260 | --- a/replay/replay-events.c | ||
261 | +++ b/replay/replay-events.c | ||
262 | @@ -XXX,XX +XXX,XX @@ static void replay_run_event(Event *event) | ||
263 | case REPLAY_ASYNC_EVENT_BH: | ||
264 | aio_bh_call(event->opaque); | ||
265 | break; | ||
266 | + case REPLAY_ASYNC_EVENT_BH_ONESHOT: | ||
267 | + ((QEMUBHFunc *)event->opaque)(event->opaque2); | ||
268 | + break; | ||
269 | case REPLAY_ASYNC_EVENT_INPUT: | ||
270 | qemu_input_event_send_impl(NULL, (InputEvent *)event->opaque); | ||
271 | qapi_free_InputEvent((InputEvent *)event->opaque); | ||
272 | @@ -XXX,XX +XXX,XX @@ void replay_bh_schedule_event(QEMUBH *bh) | ||
273 | } | ||
274 | } | ||
275 | |||
276 | +void replay_bh_schedule_oneshot_event(AioContext *ctx, | ||
277 | + QEMUBHFunc *cb, void *opaque) | ||
278 | +{ | ||
279 | + if (events_enabled) { | ||
280 | + uint64_t id = replay_get_current_icount(); | ||
281 | + replay_add_event(REPLAY_ASYNC_EVENT_BH_ONESHOT, cb, opaque, id); | ||
282 | + } else { | ||
283 | + aio_bh_schedule_oneshot(ctx, cb, opaque); | ||
284 | + } | ||
285 | +} | ||
286 | + | ||
287 | void replay_add_input_event(struct InputEvent *event) | ||
288 | { | ||
289 | replay_add_event(REPLAY_ASYNC_EVENT_INPUT, event, NULL, 0); | ||
290 | @@ -XXX,XX +XXX,XX @@ static void replay_save_event(Event *event, int checkpoint) | ||
291 | /* save event-specific data */ | ||
292 | switch (event->event_kind) { | ||
293 | case REPLAY_ASYNC_EVENT_BH: | ||
294 | + case REPLAY_ASYNC_EVENT_BH_ONESHOT: | ||
295 | replay_put_qword(event->id); | ||
296 | break; | ||
297 | case REPLAY_ASYNC_EVENT_INPUT: | ||
298 | @@ -XXX,XX +XXX,XX @@ static Event *replay_read_event(int checkpoint) | ||
299 | /* Events that has not to be in the queue */ | ||
300 | switch (replay_state.read_event_kind) { | ||
301 | case REPLAY_ASYNC_EVENT_BH: | ||
302 | + case REPLAY_ASYNC_EVENT_BH_ONESHOT: | ||
303 | if (replay_state.read_event_id == -1) { | ||
304 | replay_state.read_event_id = replay_get_qword(); | ||
305 | } | ||
306 | diff --git a/stubs/replay-user.c b/stubs/replay-user.c | ||
307 | new file mode 100644 | ||
308 | index XXXXXXX..XXXXXXX | ||
309 | --- /dev/null | ||
310 | +++ b/stubs/replay-user.c | ||
311 | @@ -XXX,XX +XXX,XX @@ | ||
312 | +#include "qemu/osdep.h" | ||
313 | +#include "sysemu/replay.h" | ||
314 | +#include "sysemu/sysemu.h" | ||
315 | + | ||
316 | +void replay_bh_schedule_oneshot_event(AioContext *ctx, | ||
317 | + QEMUBHFunc *cb, void *opaque) | ||
318 | +{ | ||
319 | + aio_bh_schedule_oneshot(ctx, cb, opaque); | ||
320 | +} | ||
321 | diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs | ||
322 | index XXXXXXX..XXXXXXX 100644 | ||
323 | --- a/stubs/Makefile.objs | ||
324 | +++ b/stubs/Makefile.objs | ||
325 | @@ -XXX,XX +XXX,XX @@ stub-obj-y += monitor.o | ||
326 | stub-obj-y += notify-event.o | ||
327 | stub-obj-y += qtest.o | ||
328 | stub-obj-y += replay.o | ||
329 | +stub-obj-y += replay-user.o | ||
330 | stub-obj-y += runstate-check.o | ||
331 | stub-obj-y += set-fd-handler.o | ||
332 | stub-obj-y += sysbus.o | ||
333 | -- | ||
334 | 2.20.1 | ||
335 | |||
336 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | The BDRV_REQ_NO_FALLBACK flag means that an operation should only be | ||
4 | performed if it can be offloaded or otherwise performed efficiently. | ||
5 | |||
6 | However a misaligned write request requires a RMW so we should return | ||
7 | an error and let the caller decide how to proceed. | ||
8 | |||
9 | This hits an assertion since commit c8bb23cbdb if the required | ||
10 | alignment is larger than the cluster size: | ||
11 | |||
12 | qemu-img create -f qcow2 -o cluster_size=2k img.qcow2 4G | ||
13 | qemu-io -c "open -o driver=qcow2,file.align=4k blkdebug::img.qcow2" \ | ||
14 | -c 'write 0 512' | ||
15 | qemu-io: block/io.c:1127: bdrv_driver_pwritev: Assertion `!(flags & BDRV_REQ_NO_FALLBACK)' failed. | ||
16 | Aborted | ||
17 | |||
18 | The reason is that when writing to an unallocated cluster we try to | ||
19 | skip the copy-on-write part and zeroize it using BDRV_REQ_NO_FALLBACK | ||
20 | instead, resulting in a write request that is too small (2KB cluster | ||
21 | size vs 4KB required alignment). | ||
22 | |||
23 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
24 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
25 | --- | ||
26 | block/io.c | 7 +++++ | ||
27 | tests/qemu-iotests/268 | 55 ++++++++++++++++++++++++++++++++++++++ | ||
28 | tests/qemu-iotests/268.out | 7 +++++ | ||
29 | tests/qemu-iotests/group | 1 + | ||
30 | 4 files changed, 70 insertions(+) | ||
31 | create mode 100755 tests/qemu-iotests/268 | ||
32 | create mode 100644 tests/qemu-iotests/268.out | ||
33 | |||
34 | diff --git a/block/io.c b/block/io.c | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/block/io.c | ||
37 | +++ b/block/io.c | ||
38 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | + /* If the request is misaligned then we can't make it efficient */ | ||
43 | + if ((flags & BDRV_REQ_NO_FALLBACK) && | ||
44 | + !QEMU_IS_ALIGNED(offset | bytes, align)) | ||
45 | + { | ||
46 | + return -ENOTSUP; | ||
47 | + } | ||
48 | + | ||
49 | bdrv_inc_in_flight(bs); | ||
50 | /* | ||
51 | * Align write if necessary by performing a read-modify-write cycle. | ||
52 | diff --git a/tests/qemu-iotests/268 b/tests/qemu-iotests/268 | ||
53 | new file mode 100755 | ||
54 | index XXXXXXX..XXXXXXX | ||
55 | --- /dev/null | ||
56 | +++ b/tests/qemu-iotests/268 | ||
57 | @@ -XXX,XX +XXX,XX @@ | ||
58 | +#!/usr/bin/env bash | ||
59 | +# | ||
60 | +# Test write request with required alignment larger than the cluster size | ||
61 | +# | ||
62 | +# Copyright (C) 2019 Igalia, S.L. | ||
63 | +# Author: Alberto Garcia <berto@igalia.com> | ||
64 | +# | ||
65 | +# This program is free software; you can redistribute it and/or modify | ||
66 | +# it under the terms of the GNU General Public License as published by | ||
67 | +# the Free Software Foundation; either version 2 of the License, or | ||
68 | +# (at your option) any later version. | ||
69 | +# | ||
70 | +# This program is distributed in the hope that it will be useful, | ||
71 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
72 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
73 | +# GNU General Public License for more details. | ||
74 | +# | ||
75 | +# You should have received a copy of the GNU General Public License | ||
76 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
77 | +# | ||
78 | + | ||
79 | +# creator | ||
80 | +owner=berto@igalia.com | ||
81 | + | ||
82 | +seq=`basename $0` | ||
83 | +echo "QA output created by $seq" | ||
84 | + | ||
85 | +status=1 # failure is the default! | ||
86 | + | ||
87 | +_cleanup() | ||
88 | +{ | ||
89 | + _cleanup_test_img | ||
90 | +} | ||
91 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
92 | + | ||
93 | +# get standard environment, filters and checks | ||
94 | +. ./common.rc | ||
95 | +. ./common.filter | ||
96 | + | ||
97 | +_supported_fmt qcow2 | ||
98 | +_supported_proto file | ||
99 | + | ||
100 | +echo | ||
101 | +echo "== Required alignment larger than cluster size ==" | ||
102 | + | ||
103 | +CLUSTER_SIZE=2k _make_test_img 1M | ||
104 | +# Since commit c8bb23cbdb writing to an unallocated cluster fills the | ||
105 | +# empty COW areas with bdrv_write_zeroes(flags=BDRV_REQ_NO_FALLBACK) | ||
106 | +$QEMU_IO -c "open -o driver=$IMGFMT,file.align=4k blkdebug::$TEST_IMG" \ | ||
107 | + -c "write 0 512" | _filter_qemu_io | ||
108 | + | ||
109 | +# success, all done | ||
110 | +echo "*** done" | ||
111 | +rm -f $seq.full | ||
112 | +status=0 | ||
113 | diff --git a/tests/qemu-iotests/268.out b/tests/qemu-iotests/268.out | ||
114 | new file mode 100644 | ||
115 | index XXXXXXX..XXXXXXX | ||
116 | --- /dev/null | ||
117 | +++ b/tests/qemu-iotests/268.out | ||
118 | @@ -XXX,XX +XXX,XX @@ | ||
119 | +QA output created by 268 | ||
120 | + | ||
121 | +== Required alignment larger than cluster size == | ||
122 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 | ||
123 | +wrote 512/512 bytes at offset 0 | ||
124 | +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
125 | +*** done | ||
126 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
127 | index XXXXXXX..XXXXXXX 100644 | ||
128 | --- a/tests/qemu-iotests/group | ||
129 | +++ b/tests/qemu-iotests/group | ||
130 | @@ -XXX,XX +XXX,XX @@ | ||
131 | 265 rw auto quick | ||
132 | 266 rw quick | ||
133 | 267 rw auto quick snapshot | ||
134 | +268 rw auto quick | ||
135 | -- | ||
136 | 2.20.1 | ||
137 | |||
138 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Max Reitz <mreitz@redhat.com> | ||
2 | 1 | ||
3 | For long test image paths, the order of the "Formatting" line and the | ||
4 | "(qemu)" prompt after a drive_backup HMP command may be reversed. In | ||
5 | fact, the interaction between the prompt and the line may lead to the | ||
6 | "Formatting" to being greppable at all after "read"-ing it (if the | ||
7 | prompt injects an IFS character into the "Formatting" string). | ||
8 | |||
9 | So just wait until we get a prompt. At that point, the block job must | ||
10 | have been started, so "info block-jobs" will only return "No active | ||
11 | jobs" once it is done. | ||
12 | |||
13 | Reported-by: Thomas Huth <thuth@redhat.com> | ||
14 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
15 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
17 | --- | ||
18 | tests/qemu-iotests/028 | 11 ++++++++--- | ||
19 | tests/qemu-iotests/028.out | 1 - | ||
20 | 2 files changed, 8 insertions(+), 4 deletions(-) | ||
21 | |||
22 | diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028 | ||
23 | index XXXXXXX..XXXXXXX 100755 | ||
24 | --- a/tests/qemu-iotests/028 | ||
25 | +++ b/tests/qemu-iotests/028 | ||
26 | @@ -XXX,XX +XXX,XX @@ fi | ||
27 | # Silence output since it contains the disk image path and QEMU's readline | ||
28 | # character echoing makes it very hard to filter the output. Plus, there | ||
29 | # is no telling how many times the command will repeat before succeeding. | ||
30 | -_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null | ||
31 | -_send_qemu_cmd $h "" "Formatting" | _filter_img_create | ||
32 | -qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs" >/dev/null | ||
33 | +# (Note that creating the image results in a "Formatting..." message over | ||
34 | +# stdout, which is the same channel the monitor uses. We cannot reliably | ||
35 | +# wait for it because the monitor output may interact with it in such a | ||
36 | +# way that _timed_wait_for cannot read it. However, once the block job is | ||
37 | +# done, we know that the "Formatting..." message must have appeared | ||
38 | +# already, so the output is still deterministic.) | ||
39 | +silent=y _send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" | ||
40 | +silent=y qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs" | ||
41 | _send_qemu_cmd $h "info block-jobs" "No active jobs" | ||
42 | _send_qemu_cmd $h 'quit' "" | ||
43 | |||
44 | diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out | ||
45 | index XXXXXXX..XXXXXXX 100644 | ||
46 | --- a/tests/qemu-iotests/028.out | ||
47 | +++ b/tests/qemu-iotests/028.out | ||
48 | @@ -XXX,XX +XXX,XX @@ No errors were found on the image. | ||
49 | |||
50 | block-backup | ||
51 | |||
52 | -Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT | ||
53 | (qemu) info block-jobs | ||
54 | No active jobs | ||
55 | === IO: pattern 195 | ||
56 | -- | ||
57 | 2.20.1 | ||
58 | |||
59 | diff view generated by jsdifflib |