1 | The following changes since commit b98a66201dbc7cf3b962f4bb260f66100cc75578: | 1 | The following changes since commit ec11dc41eec5142b4776db1296972c6323ba5847: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-4.0-rc0-2' into staging (2019-03-19 12:55:02 +0000) | 3 | Merge tag 'pull-misc-2022-05-11' of git://repo.or.cz/qemu/armbru into staging (2022-05-11 09:00:26 -0700) |
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 | git://repo.or.cz/qemu/kevin.git tags/for-upstream |
8 | 8 | ||
9 | for you to fetch changes up to 59fba0aaee7438002d9803a86c888f21a1070cc8: | 9 | for you to fetch changes up to f70625299ecc9ba577c87f3d1d75012c747c7d88: |
10 | 10 | ||
11 | qemu-iotests: Treat custom TEST_DIR in 051 (2019-03-19 15:51:31 +0100) | 11 | qemu-iotests: inline common.config into common.rc (2022-05-12 15:42:49 +0200) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block layer patches: | 14 | Block layer patches |
15 | 15 | ||
16 | - mirror: Fix early return from drain (could cause deadlocks) | 16 | - coroutine: Fix crashes due to too large pool batch size |
17 | - vmdk: Fixed probing for version 3 images | 17 | - fdc: Prevent end-of-track overrun |
18 | - vl: Fix to create migration object before block backends again (fixes | 18 | - nbd: MULTI_CONN for shared writable exports |
19 | segfault for block drivers that set migration blockers) | 19 | - iotests test runner improvements |
20 | - Several minor fixes, documentation and test case improvements | ||
21 | 20 | ||
22 | ---------------------------------------------------------------- | 21 | ---------------------------------------------------------------- |
23 | Alberto Garcia (1): | 22 | Daniel P. Berrangé (2): |
24 | block: Make bdrv_{copy_on_read,crypto_luks,replication} static | 23 | tests/qemu-iotests: print intent to run a test in TAP mode |
24 | .gitlab-ci.d: export meson testlog.txt as an artifact | ||
25 | 25 | ||
26 | Kevin Wolf (3): | 26 | Eric Blake (2): |
27 | qcow2: Fix data file error condition in qcow2_co_create() | 27 | qemu-nbd: Pass max connections to blockdev layer |
28 | block: Silence Coverity in bdrv_drop_intermediate() | 28 | nbd/server: Allow MULTI_CONN for shared writable exports |
29 | qemu-iotests: Fix 232 for non-qcow2 | ||
30 | 29 | ||
31 | Lukáš Doktor (1): | 30 | Hanna Reitz (1): |
32 | qemu-iotests: Treat custom TEST_DIR in 051 | 31 | iotests/testrunner: Flush after run_test() |
33 | 32 | ||
34 | Markus Armbruster (1): | 33 | Kevin Wolf (2): |
35 | vl: Fix to create migration object before block backends again | 34 | coroutine: Rename qemu_coroutine_inc/dec_pool_size() |
35 | coroutine: Revert to constant batch size | ||
36 | 36 | ||
37 | Max Reitz (1): | 37 | Paolo Bonzini (1): |
38 | blockdev: Check @replaces in blockdev_mirror_common | 38 | qemu-iotests: inline common.config into common.rc |
39 | 39 | ||
40 | Sam Eiderman (1): | 40 | Philippe Mathieu-Daudé (2): |
41 | vmdk: Support version=3 in VMDK descriptor files | 41 | hw/block/fdc: Prevent end-of-track overrun (CVE-2021-3507) |
42 | tests/qtest/fdc-test: Add a regression test for CVE-2021-3507 | ||
42 | 43 | ||
43 | Sergio Lopez (2): | 44 | qapi/block-export.json | 8 +- |
44 | mirror: Confirm we're quiesced only if the job is paused or cancelled | 45 | docs/interop/nbd.txt | 1 + |
45 | iotests: 153: Wait for an answer to QMP commands | 46 | docs/tools/qemu-nbd.rst | 3 +- |
47 | include/block/nbd.h | 5 +- | ||
48 | include/qemu/coroutine.h | 6 +- | ||
49 | blockdev-nbd.c | 13 +- | ||
50 | hw/block/fdc.c | 8 ++ | ||
51 | hw/block/virtio-blk.c | 6 +- | ||
52 | nbd/server.c | 10 +- | ||
53 | qemu-nbd.c | 2 +- | ||
54 | tests/qtest/fdc-test.c | 21 ++++ | ||
55 | util/qemu-coroutine.c | 26 ++-- | ||
56 | tests/qemu-iotests/testrunner.py | 4 + | ||
57 | .gitlab-ci.d/buildtest-template.yml | 12 +- | ||
58 | MAINTAINERS | 1 + | ||
59 | tests/qemu-iotests/common.config | 41 ------- | ||
60 | tests/qemu-iotests/common.rc | 31 +++-- | ||
61 | tests/qemu-iotests/tests/nbd-multiconn | 145 +++++++++++++++++++++++ | ||
62 | tests/qemu-iotests/tests/nbd-multiconn.out | 5 + | ||
63 | tests/qemu-iotests/tests/nbd-qemu-allocation.out | 2 +- | ||
64 | 20 files changed, 261 insertions(+), 89 deletions(-) | ||
65 | delete mode 100644 tests/qemu-iotests/common.config | ||
66 | create mode 100755 tests/qemu-iotests/tests/nbd-multiconn | ||
67 | create mode 100644 tests/qemu-iotests/tests/nbd-multiconn.out | ||
46 | 68 | ||
47 | Vladimir Sementsov-Ogievskiy (2): | ||
48 | qapi: fix block-latency-histogram-set description and examples | ||
49 | blockjob: fix user pause in block_job_error_action | ||
50 | 69 | ||
51 | qapi/block-core.json | 10 +++--- | ||
52 | block.c | 7 ++-- | ||
53 | block/copy-on-read.c | 2 +- | ||
54 | block/crypto.c | 2 +- | ||
55 | block/mirror.c | 16 ++++++++++ | ||
56 | block/qcow2.c | 2 +- | ||
57 | block/replication.c | 2 +- | ||
58 | block/vmdk.c | 6 ++-- | ||
59 | blockdev.c | 55 +++++++++++++++++++------------- | ||
60 | blockjob.c | 8 +++-- | ||
61 | vl.c | 15 +++++---- | ||
62 | tests/qemu-iotests/051 | 2 +- | ||
63 | tests/qemu-iotests/153 | 12 +++---- | ||
64 | tests/qemu-iotests/153.out | 6 ++++ | ||
65 | tests/qemu-iotests/232 | 30 ------------------ | ||
66 | tests/qemu-iotests/232.out | 20 ------------ | ||
67 | tests/qemu-iotests/247 | 79 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
68 | tests/qemu-iotests/247.out | 22 +++++++++++++ | ||
69 | tests/qemu-iotests/group | 1 + | ||
70 | 19 files changed, 193 insertions(+), 104 deletions(-) | ||
71 | create mode 100755 tests/qemu-iotests/247 | ||
72 | create mode 100644 tests/qemu-iotests/247.out | ||
73 | diff view generated by jsdifflib |
1 | From: Lukáš Doktor <ldoktor@redhat.com> | 1 | It's true that these functions currently affect the batch size in which |
---|---|---|---|
2 | coroutines are reused (i.e. moved from the global release pool to the | ||
3 | allocation pool of a specific thread), but this is a bug and will be | ||
4 | fixed in a separate patch. | ||
2 | 5 | ||
3 | When custom TEST_DIR is specified the output includes it without leading | 6 | In fact, the comment in the header file already just promises that it |
4 | '/': | 7 | influences the pool size, so reflect this in the name of the functions. |
8 | As a nice side effect, the shorter function name makes some line | ||
9 | wrapping unnecessary. | ||
5 | 10 | ||
6 | $ TEST_DIR=/var/tmp ./check -file -qcow2 051 | 11 | Cc: qemu-stable@nongnu.org |
7 | .... | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | -drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": | 13 | Message-Id: <20220510151020.105528-2-kwolf@redhat.com> |
9 | {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}, "driver": "qcow2", | ||
10 | "file": {"driver": "file", "filename": SNAPSHOT_PATH}} (qcow2, | ||
11 | read-only) | ||
12 | +drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": | ||
13 | {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}, "driver": "qcow2", | ||
14 | "file": {"driver": "file", "filename": "TEST_DIR/vl.ziHfeP"}} (qcow2, | ||
15 | read-only) | ||
16 | |||
17 | Let's remove it from the sed regexp. | ||
18 | |||
19 | Signed-off-by: Lukáš Doktor <ldoktor@redhat.com> | ||
20 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
21 | --- | 15 | --- |
22 | tests/qemu-iotests/051 | 2 +- | 16 | include/qemu/coroutine.h | 6 +++--- |
23 | 1 file changed, 1 insertion(+), 1 deletion(-) | 17 | hw/block/virtio-blk.c | 6 ++---- |
18 | util/qemu-coroutine.c | 4 ++-- | ||
19 | 3 files changed, 7 insertions(+), 9 deletions(-) | ||
24 | 20 | ||
25 | diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 | 21 | diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h |
26 | index XXXXXXX..XXXXXXX 100755 | 22 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/tests/qemu-iotests/051 | 23 | --- a/include/qemu/coroutine.h |
28 | +++ b/tests/qemu-iotests/051 | 24 | +++ b/include/qemu/coroutine.h |
29 | @@ -XXX,XX +XXX,XX @@ TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on | 25 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn yield_until_fd_readable(int fd); |
30 | echo "info block" | | 26 | /** |
31 | run_qemu -drive file="$TEST_IMG",snapshot=on,read-only=on,if=none,id=$device_id | | 27 | * Increase coroutine pool size |
32 | _filter_qemu_io | | 28 | */ |
33 | - sed -e 's#"/[^"]*/vl\.[A-Za-z0-9]\{6\}"#SNAPSHOT_PATH#g' | 29 | -void qemu_coroutine_increase_pool_batch_size(unsigned int additional_pool_size); |
34 | + sed -e 's#"[^"]*/vl\.[A-Za-z0-9]\{6\}"#SNAPSHOT_PATH#g' | 30 | +void qemu_coroutine_inc_pool_size(unsigned int additional_pool_size); |
35 | 31 | ||
36 | 32 | /** | |
37 | # success, all done | 33 | - * Devcrease coroutine pool size |
34 | + * Decrease coroutine pool size | ||
35 | */ | ||
36 | -void qemu_coroutine_decrease_pool_batch_size(unsigned int additional_pool_size); | ||
37 | +void qemu_coroutine_dec_pool_size(unsigned int additional_pool_size); | ||
38 | |||
39 | #include "qemu/lockable.h" | ||
40 | |||
41 | diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c | ||
42 | index XXXXXXX..XXXXXXX 100644 | ||
43 | --- a/hw/block/virtio-blk.c | ||
44 | +++ b/hw/block/virtio-blk.c | ||
45 | @@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) | ||
46 | for (i = 0; i < conf->num_queues; i++) { | ||
47 | virtio_add_queue(vdev, conf->queue_size, virtio_blk_handle_output); | ||
48 | } | ||
49 | - qemu_coroutine_increase_pool_batch_size(conf->num_queues * conf->queue_size | ||
50 | - / 2); | ||
51 | + qemu_coroutine_inc_pool_size(conf->num_queues * conf->queue_size / 2); | ||
52 | virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err); | ||
53 | if (err != NULL) { | ||
54 | error_propagate(errp, err); | ||
55 | @@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_unrealize(DeviceState *dev) | ||
56 | for (i = 0; i < conf->num_queues; i++) { | ||
57 | virtio_del_queue(vdev, i); | ||
58 | } | ||
59 | - qemu_coroutine_decrease_pool_batch_size(conf->num_queues * conf->queue_size | ||
60 | - / 2); | ||
61 | + qemu_coroutine_dec_pool_size(conf->num_queues * conf->queue_size / 2); | ||
62 | qemu_del_vm_change_state_handler(s->change); | ||
63 | blockdev_mark_auto_del(s->blk); | ||
64 | virtio_cleanup(vdev); | ||
65 | diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/util/qemu-coroutine.c | ||
68 | +++ b/util/qemu-coroutine.c | ||
69 | @@ -XXX,XX +XXX,XX @@ AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co) | ||
70 | return co->ctx; | ||
71 | } | ||
72 | |||
73 | -void qemu_coroutine_increase_pool_batch_size(unsigned int additional_pool_size) | ||
74 | +void qemu_coroutine_inc_pool_size(unsigned int additional_pool_size) | ||
75 | { | ||
76 | qatomic_add(&pool_batch_size, additional_pool_size); | ||
77 | } | ||
78 | |||
79 | -void qemu_coroutine_decrease_pool_batch_size(unsigned int removing_pool_size) | ||
80 | +void qemu_coroutine_dec_pool_size(unsigned int removing_pool_size) | ||
81 | { | ||
82 | qatomic_sub(&pool_batch_size, removing_pool_size); | ||
83 | } | ||
38 | -- | 84 | -- |
39 | 2.20.1 | 85 | 2.35.3 |
40 | |||
41 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | Commit 4c41c69e changed the way the coroutine pool is sized because for |
---|---|---|---|
2 | virtio-blk devices with a large queue size and heavy I/O, it was just | ||
3 | too small and caused coroutines to be deleted and reallocated soon | ||
4 | afterwards. The change made the size dynamic based on the number of | ||
5 | queues and the queue size of virtio-blk devices. | ||
2 | 6 | ||
3 | Job (especially mirror) may call block_job_error_action several | 7 | There are two important numbers here: Slightly simplified, when a |
4 | times before actual pause if it has several in-flight requests. | 8 | coroutine terminates, it is generally stored in the global release pool |
9 | up to a certain pool size, and if the pool is full, it is freed. | ||
10 | Conversely, when allocating a new coroutine, the coroutines in the | ||
11 | release pool are reused if the pool already has reached a certain | ||
12 | minimum size (the batch size), otherwise we allocate new coroutines. | ||
5 | 13 | ||
6 | block_job_error_action will call job_pause more than once in this case, | 14 | The problem after commit 4c41c69e is that it not only increases the |
7 | which lead to following block-job-resume qmp command can't actually | 15 | maximum pool size (which is the intended effect), but also the batch |
8 | resume the job. | 16 | size for reusing coroutines (which is a bug). It means that in cases |
17 | with many devices and/or a large queue size (which defaults to the | ||
18 | number of vcpus for virtio-blk-pci), many thousand coroutines could be | ||
19 | sitting in the release pool without being reused. | ||
9 | 20 | ||
10 | Fix it by do not increase pause level in block_job_error_action if | 21 | This is not only a waste of memory and allocations, but it actually |
11 | user_paused already set. | 22 | makes the QEMU process likely to hit the vm.max_map_count limit on Linux |
23 | because each coroutine requires two mappings (its stack and the guard | ||
24 | page for the stack), causing it to abort() in qemu_alloc_stack() because | ||
25 | when the limit is hit, mprotect() starts to fail with ENOMEM. | ||
12 | 26 | ||
13 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 27 | In order to fix the problem, change the batch size back to 64 to avoid |
28 | uselessly accumulating coroutines in the release pool, but keep the | ||
29 | dynamic maximum pool size so that coroutines aren't freed too early | ||
30 | in heavy I/O scenarios. | ||
31 | |||
32 | Note that this fix doesn't strictly make it impossible to hit the limit, | ||
33 | but this would only happen if most of the coroutines are actually in use | ||
34 | at the same time, not just sitting in a pool. This is the same behaviour | ||
35 | as we already had before commit 4c41c69e. Fully preventing this would | ||
36 | require allowing qemu_coroutine_create() to return an error, but it | ||
37 | doesn't seem to be a scenario that people hit in practice. | ||
38 | |||
39 | Cc: qemu-stable@nongnu.org | ||
40 | Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2079938 | ||
41 | Fixes: 4c41c69e05fe28c0f95f8abd2ebf407e95a4f04b | ||
42 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
43 | Message-Id: <20220510151020.105528-3-kwolf@redhat.com> | ||
44 | Tested-by: Hiroki Narukawa <hnarukaw@yahoo-corp.jp> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 45 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
15 | --- | 46 | --- |
16 | blockjob.c | 8 +++++--- | 47 | util/qemu-coroutine.c | 22 ++++++++++++++-------- |
17 | 1 file changed, 5 insertions(+), 3 deletions(-) | 48 | 1 file changed, 14 insertions(+), 8 deletions(-) |
18 | 49 | ||
19 | diff --git a/blockjob.c b/blockjob.c | 50 | diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c |
20 | index XXXXXXX..XXXXXXX 100644 | 51 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/blockjob.c | 52 | --- a/util/qemu-coroutine.c |
22 | +++ b/blockjob.c | 53 | +++ b/util/qemu-coroutine.c |
23 | @@ -XXX,XX +XXX,XX @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err, | 54 | @@ -XXX,XX +XXX,XX @@ |
24 | action); | 55 | #include "qemu/coroutine-tls.h" |
25 | } | 56 | #include "block/aio.h" |
26 | if (action == BLOCK_ERROR_ACTION_STOP) { | 57 | |
27 | - job_pause(&job->job); | 58 | -/** Initial batch size is 64, and is increased on demand */ |
28 | - /* make the pause user visible, which will be resumed from QMP. */ | 59 | +/** |
29 | - job->job.user_paused = true; | 60 | + * The minimal batch size is always 64, coroutines from the release_pool are |
30 | + if (!job->job.user_paused) { | 61 | + * reused as soon as there are 64 coroutines in it. The maximum pool size starts |
31 | + job_pause(&job->job); | 62 | + * with 64 and is increased on demand so that coroutines are not deleted even if |
32 | + /* make the pause user visible, which will be resumed from QMP. */ | 63 | + * they are not immediately reused. |
33 | + job->job.user_paused = true; | 64 | + */ |
34 | + } | 65 | enum { |
35 | block_job_iostatus_set_err(job, error); | 66 | - POOL_INITIAL_BATCH_SIZE = 64, |
36 | } | 67 | + POOL_MIN_BATCH_SIZE = 64, |
37 | return action; | 68 | + POOL_INITIAL_MAX_SIZE = 64, |
69 | }; | ||
70 | |||
71 | /** Free list to speed up creation */ | ||
72 | static QSLIST_HEAD(, Coroutine) release_pool = QSLIST_HEAD_INITIALIZER(pool); | ||
73 | -static unsigned int pool_batch_size = POOL_INITIAL_BATCH_SIZE; | ||
74 | +static unsigned int pool_max_size = POOL_INITIAL_MAX_SIZE; | ||
75 | static unsigned int release_pool_size; | ||
76 | |||
77 | typedef QSLIST_HEAD(, Coroutine) CoroutineQSList; | ||
78 | @@ -XXX,XX +XXX,XX @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque) | ||
79 | |||
80 | co = QSLIST_FIRST(alloc_pool); | ||
81 | if (!co) { | ||
82 | - if (release_pool_size > qatomic_read(&pool_batch_size)) { | ||
83 | + if (release_pool_size > POOL_MIN_BATCH_SIZE) { | ||
84 | /* Slow path; a good place to register the destructor, too. */ | ||
85 | Notifier *notifier = get_ptr_coroutine_pool_cleanup_notifier(); | ||
86 | if (!notifier->notify) { | ||
87 | @@ -XXX,XX +XXX,XX @@ static void coroutine_delete(Coroutine *co) | ||
88 | co->caller = NULL; | ||
89 | |||
90 | if (CONFIG_COROUTINE_POOL) { | ||
91 | - if (release_pool_size < qatomic_read(&pool_batch_size) * 2) { | ||
92 | + if (release_pool_size < qatomic_read(&pool_max_size) * 2) { | ||
93 | QSLIST_INSERT_HEAD_ATOMIC(&release_pool, co, pool_next); | ||
94 | qatomic_inc(&release_pool_size); | ||
95 | return; | ||
96 | } | ||
97 | - if (get_alloc_pool_size() < qatomic_read(&pool_batch_size)) { | ||
98 | + if (get_alloc_pool_size() < qatomic_read(&pool_max_size)) { | ||
99 | QSLIST_INSERT_HEAD(get_ptr_alloc_pool(), co, pool_next); | ||
100 | set_alloc_pool_size(get_alloc_pool_size() + 1); | ||
101 | return; | ||
102 | @@ -XXX,XX +XXX,XX @@ AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co) | ||
103 | |||
104 | void qemu_coroutine_inc_pool_size(unsigned int additional_pool_size) | ||
105 | { | ||
106 | - qatomic_add(&pool_batch_size, additional_pool_size); | ||
107 | + qatomic_add(&pool_max_size, additional_pool_size); | ||
108 | } | ||
109 | |||
110 | void qemu_coroutine_dec_pool_size(unsigned int removing_pool_size) | ||
111 | { | ||
112 | - qatomic_sub(&pool_batch_size, removing_pool_size); | ||
113 | + qatomic_sub(&pool_max_size, removing_pool_size); | ||
114 | } | ||
38 | -- | 115 | -- |
39 | 2.20.1 | 116 | 2.35.3 |
40 | |||
41 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | From: Hanna Reitz <hreitz@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | There no @device parameter, only the @id one. | 3 | When stdout is not a terminal, the buffer may not be flushed at each end |
4 | of line, so we should flush after each test is done. This is especially | ||
5 | apparent when run by check-block, in two ways: | ||
4 | 6 | ||
5 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 7 | First, when running make check-block -jX with X > 1, progress indication |
8 | was missing, even though testrunner.py does theoretically print each | ||
9 | test's status once it has been run, even in multi-processing mode. | ||
10 | Flushing after each test restores this progress indication. | ||
11 | |||
12 | Second, sometimes make check-block failed altogether, with an error | ||
13 | message that "too few tests [were] run". I presume that's because one | ||
14 | worker process in the job pool did not get to flush its stdout before | ||
15 | the main process exited, and so meson did not get to see that worker's | ||
16 | test results. In any case, by flushing at the end of run_test(), the | ||
17 | problem has disappeared for me. | ||
18 | |||
19 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||
20 | Message-Id: <20220506134215.10086-1-hreitz@redhat.com> | ||
6 | Reviewed-by: Eric Blake <eblake@redhat.com> | 21 | Reviewed-by: Eric Blake <eblake@redhat.com> |
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 22 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | --- | 23 | --- |
9 | qapi/block-core.json | 10 +++++----- | 24 | tests/qemu-iotests/testrunner.py | 1 + |
10 | 1 file changed, 5 insertions(+), 5 deletions(-) | 25 | 1 file changed, 1 insertion(+) |
11 | 26 | ||
12 | diff --git a/qapi/block-core.json b/qapi/block-core.json | 27 | diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py |
13 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/qapi/block-core.json | 29 | --- a/tests/qemu-iotests/testrunner.py |
15 | +++ b/qapi/block-core.json | 30 | +++ b/tests/qemu-iotests/testrunner.py |
16 | @@ -XXX,XX +XXX,XX @@ | 31 | @@ -XXX,XX +XXX,XX @@ def run_test(self, test: str, |
17 | # | 32 | else: |
18 | # Manage read, write and flush latency histograms for the device. | 33 | print(res.casenotrun) |
19 | # | 34 | |
20 | -# If only @device parameter is specified, remove all present latency histograms | 35 | + sys.stdout.flush() |
21 | +# If only @id parameter is specified, remove all present latency histograms | 36 | return res |
22 | # for the device. Otherwise, add/reset some of (or all) latency histograms. | 37 | |
23 | # | 38 | def run_tests(self, tests: List[str], jobs: int = 1) -> bool: |
24 | # @id: The name or QOM path of the guest device. | ||
25 | @@ -XXX,XX +XXX,XX @@ | ||
26 | # [0, 10), [10, 50), [50, 100), [100, +inf): | ||
27 | # | ||
28 | # -> { "execute": "block-latency-histogram-set", | ||
29 | -# "arguments": { "device": "drive0", | ||
30 | +# "arguments": { "id": "drive0", | ||
31 | # "boundaries": [10, 50, 100] } } | ||
32 | # <- { "return": {} } | ||
33 | # | ||
34 | @@ -XXX,XX +XXX,XX @@ | ||
35 | # not changed (or not created): | ||
36 | # | ||
37 | # -> { "execute": "block-latency-histogram-set", | ||
38 | -# "arguments": { "device": "drive0", | ||
39 | +# "arguments": { "id": "drive0", | ||
40 | # "boundaries-write": [10, 50, 100] } } | ||
41 | # <- { "return": {} } | ||
42 | # | ||
43 | @@ -XXX,XX +XXX,XX @@ | ||
44 | # write: [0, 1000), [1000, 5000), [5000, +inf) | ||
45 | # | ||
46 | # -> { "execute": "block-latency-histogram-set", | ||
47 | -# "arguments": { "device": "drive0", | ||
48 | +# "arguments": { "id": "drive0", | ||
49 | # "boundaries": [10, 50, 100], | ||
50 | # "boundaries-write": [1000, 5000] } } | ||
51 | # <- { "return": {} } | ||
52 | @@ -XXX,XX +XXX,XX @@ | ||
53 | # Example: remove all latency histograms: | ||
54 | # | ||
55 | # -> { "execute": "block-latency-histogram-set", | ||
56 | -# "arguments": { "device": "drive0" } } | ||
57 | +# "arguments": { "id": "drive0" } } | ||
58 | # <- { "return": {} } | ||
59 | ## | ||
60 | { 'command': 'block-latency-histogram-set', | ||
61 | -- | 39 | -- |
62 | 2.20.1 | 40 | 2.35.3 |
63 | |||
64 | diff view generated by jsdifflib |
1 | From: Sergio Lopez <slp@redhat.com> | 1 | From: Daniel P. Berrangé <berrange@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | There are various actions in this test that must be executed | 3 | When running I/O tests using TAP output mode, we get a single TAP test |
4 | sequentially, as the result of it depends on the state triggered by the | 4 | with a sub-test reported for each I/O test that is run. The output looks |
5 | previous one. | 5 | something like this: |
6 | 6 | ||
7 | If the last argument of _send_qemu_cmd() is an empty string, it just | 7 | 1..123 |
8 | sends the QMP commands without waiting for an answer. While unlikely, it | 8 | ok qcow2 011 |
9 | may happen that the next action in the test gets invoked before QEMU | 9 | ok qcow2 012 |
10 | processes the QMP request. | 10 | ok qcow2 013 |
11 | ok qcow2 217 | ||
12 | ... | ||
11 | 13 | ||
12 | This issue seems to be easier to reproduce on servers with limited | 14 | If everything runs or fails normally this is fine, but periodically we |
13 | resources or highly loaded. | 15 | have been seeing the test harness abort early before all 123 tests have |
16 | been run, just leaving a fairly useless message like | ||
14 | 17 | ||
15 | With this change, we wait for an answer on all _send_qemu_cmd() calls. | 18 | TAP parsing error: Too few tests run (expected 123, got 107) |
16 | 19 | ||
17 | Signed-off-by: Sergio Lopez <slp@redhat.com> | 20 | we have no idea which tests were running at the time the test harness |
21 | abruptly exited. This change causes us to print a message about our | ||
22 | intent to run each test, so we have a record of what is active at the | ||
23 | time the harness exits abnormally. | ||
24 | |||
25 | 1..123 | ||
26 | # running qcow2 011 | ||
27 | ok qcow2 011 | ||
28 | # running qcow2 012 | ||
29 | ok qcow2 012 | ||
30 | # running qcow2 013 | ||
31 | ok qcow2 013 | ||
32 | # running qcow2 217 | ||
33 | ok qcow2 217 | ||
34 | ... | ||
35 | |||
36 | Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> | ||
37 | Message-Id: <20220509124134.867431-2-berrange@redhat.com> | ||
38 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 39 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
19 | --- | 40 | --- |
20 | tests/qemu-iotests/153 | 12 ++++++------ | 41 | tests/qemu-iotests/testrunner.py | 3 +++ |
21 | tests/qemu-iotests/153.out | 6 ++++++ | 42 | 1 file changed, 3 insertions(+) |
22 | 2 files changed, 12 insertions(+), 6 deletions(-) | ||
23 | 43 | ||
24 | diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153 | 44 | diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py |
25 | index XXXXXXX..XXXXXXX 100755 | ||
26 | --- a/tests/qemu-iotests/153 | ||
27 | +++ b/tests/qemu-iotests/153 | ||
28 | @@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do | ||
29 | _img_info -U | grep 'file format' | ||
30 | fi | ||
31 | done | ||
32 | - _send_qemu_cmd $h "{ 'execute': 'quit', }" "" | ||
33 | + _send_qemu_cmd $h "{ 'execute': 'quit' }" '' | ||
34 | echo | ||
35 | echo "Round done" | ||
36 | _cleanup_qemu | ||
37 | @@ -XXX,XX +XXX,XX @@ echo "Adding drive" | ||
38 | _send_qemu_cmd $QEMU_HANDLE \ | ||
39 | "{ 'execute': 'human-monitor-command', | ||
40 | 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=${TEST_IMG}' } }" \ | ||
41 | - "" | ||
42 | + 'return' | ||
43 | |||
44 | _run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512' | ||
45 | |||
46 | @@ -XXX,XX +XXX,XX @@ echo "== Closing an image should unlock it ==" | ||
47 | _send_qemu_cmd $QEMU_HANDLE \ | ||
48 | "{ 'execute': 'human-monitor-command', | ||
49 | 'arguments': { 'command-line': 'drive_del d0' } }" \ | ||
50 | - "" | ||
51 | + 'return' | ||
52 | |||
53 | _run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512' | ||
54 | |||
55 | @@ -XXX,XX +XXX,XX @@ for d in d0 d1; do | ||
56 | _send_qemu_cmd $QEMU_HANDLE \ | ||
57 | "{ 'execute': 'human-monitor-command', | ||
58 | 'arguments': { 'command-line': 'drive_add 0 if=none,id=$d,file=${TEST_IMG},readonly=on' } }" \ | ||
59 | - "" | ||
60 | + 'return' | ||
61 | done | ||
62 | |||
63 | _run_cmd $QEMU_IMG info "${TEST_IMG}" | ||
64 | @@ -XXX,XX +XXX,XX @@ _run_cmd $QEMU_IMG info "${TEST_IMG}" | ||
65 | _send_qemu_cmd $QEMU_HANDLE \ | ||
66 | "{ 'execute': 'human-monitor-command', | ||
67 | 'arguments': { 'command-line': 'drive_del d0' } }" \ | ||
68 | - "" | ||
69 | + 'return' | ||
70 | |||
71 | _run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512' | ||
72 | |||
73 | @@ -XXX,XX +XXX,XX @@ echo "Closing the other" | ||
74 | _send_qemu_cmd $QEMU_HANDLE \ | ||
75 | "{ 'execute': 'human-monitor-command', | ||
76 | 'arguments': { 'command-line': 'drive_del d1' } }" \ | ||
77 | - "" | ||
78 | + 'return' | ||
79 | |||
80 | _run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512' | ||
81 | |||
82 | diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out | ||
83 | index XXXXXXX..XXXXXXX 100644 | 45 | index XXXXXXX..XXXXXXX 100644 |
84 | --- a/tests/qemu-iotests/153.out | 46 | --- a/tests/qemu-iotests/testrunner.py |
85 | +++ b/tests/qemu-iotests/153.out | 47 | +++ b/tests/qemu-iotests/testrunner.py |
86 | @@ -XXX,XX +XXX,XX @@ Is another process using the image [TEST_DIR/t.qcow2]? | 48 | @@ -XXX,XX +XXX,XX @@ def run_test(self, test: str, |
87 | _qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c | 49 | starttime=start, |
88 | {"return": {}} | 50 | lasttime=last_el, |
89 | Adding drive | 51 | end = '\n' if mp else '\r') |
90 | +{"return": "OKrn"} | 52 | + else: |
91 | 53 | + testname = os.path.basename(test) | |
92 | _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 | 54 | + print(f'# running {self.env.imgfmt} {testname}') |
93 | can't open device TEST_DIR/t.qcow2: Failed to get "write" lock | 55 | |
94 | @@ -XXX,XX +XXX,XX @@ Creating overlay with qemu-img when the guest is running should be allowed | 56 | res = self.do_run_test(test, mp) |
95 | |||
96 | _qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay | ||
97 | == Closing an image should unlock it == | ||
98 | +{"return": ""} | ||
99 | |||
100 | _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 | ||
101 | Adding two and closing one | ||
102 | +{"return": "OKrn"} | ||
103 | +{"return": "OKrn"} | ||
104 | |||
105 | _qemu_img_wrapper info TEST_DIR/t.qcow2 | ||
106 | +{"return": ""} | ||
107 | |||
108 | _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 | ||
109 | can't open device TEST_DIR/t.qcow2: Failed to get "write" lock | ||
110 | Is another process using the image [TEST_DIR/t.qcow2]? | ||
111 | Closing the other | ||
112 | +{"return": ""} | ||
113 | |||
114 | _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 | ||
115 | 57 | ||
116 | -- | 58 | -- |
117 | 2.20.1 | 59 | 2.35.3 |
118 | 60 | ||
119 | 61 | diff view generated by jsdifflib |
1 | From: Markus Armbruster <armbru@redhat.com> | 1 | From: Daniel P. Berrangé <berrange@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Recent commit cda4aa9a5a0 moved block backend creation before machine | 3 | When running 'make check' we only get a summary of progress on the |
4 | property evaluation. This broke qemu-iotests 055. Turns out we need | 4 | console. Fortunately meson/ninja have saved the raw test output to a |
5 | to create the migration object before block backends, so block | 5 | logfile. Exposing this log will make it easier to debug failures that |
6 | backends can add migration blockers. Fix by calling | 6 | happen in CI. |
7 | migration_object_init() earlier, right before configure_blockdev(). | ||
8 | 7 | ||
9 | Fixes: cda4aa9a5a08777cf13e164c0543bd4888b8adce | 8 | Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> |
10 | Reported-by: Kevin Wolf <kwolf@redhat.com> | 9 | Message-Id: <20220509124134.867431-3-berrange@redhat.com> |
11 | Signed-off-by: Markus Armbruster <armbru@redhat.com> | 10 | Reviewed-by: Thomas Huth <thuth@redhat.com> |
11 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
13 | --- | 13 | --- |
14 | vl.c | 15 ++++++++------- | 14 | .gitlab-ci.d/buildtest-template.yml | 12 ++++++++++-- |
15 | 1 file changed, 8 insertions(+), 7 deletions(-) | 15 | 1 file changed, 10 insertions(+), 2 deletions(-) |
16 | 16 | ||
17 | diff --git a/vl.c b/vl.c | 17 | diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml |
18 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/vl.c | 19 | --- a/.gitlab-ci.d/buildtest-template.yml |
20 | +++ b/vl.c | 20 | +++ b/.gitlab-ci.d/buildtest-template.yml |
21 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp) | 21 | @@ -XXX,XX +XXX,XX @@ |
22 | exit(0); | 22 | make -j"$JOBS" $MAKE_CHECK_ARGS ; |
23 | } | 23 | fi |
24 | 24 | ||
25 | + /* | 25 | -.native_test_job_template: |
26 | + * Migration object can only be created after global properties | 26 | +.common_test_job_template: |
27 | + * are applied correctly. | 27 | stage: test |
28 | + */ | 28 | image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest |
29 | + migration_object_init(); | 29 | script: |
30 | @@ -XXX,XX +XXX,XX @@ | ||
31 | # Avoid recompiling by hiding ninja with NINJA=":" | ||
32 | - make NINJA=":" $MAKE_CHECK_ARGS | ||
33 | |||
34 | +.native_test_job_template: | ||
35 | + extends: .common_test_job_template | ||
36 | + artifacts: | ||
37 | + name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" | ||
38 | + expire_in: 7 days | ||
39 | + paths: | ||
40 | + - build/meson-logs/testlog.txt | ||
30 | + | 41 | + |
31 | /* | 42 | .avocado_test_job_template: |
32 | * Note: we need to create block backends before | 43 | - extends: .native_test_job_template |
33 | * machine_set_property(), so machine properties can refer to | 44 | + extends: .common_test_job_template |
34 | - * them. | 45 | cache: |
35 | + * them, and after migration_object_init(), so we can create | 46 | key: "${CI_JOB_NAME}-cache" |
36 | + * migration blockers. | 47 | paths: |
37 | */ | ||
38 | configure_blockdev(&bdo_queue, machine_class, snapshot); | ||
39 | |||
40 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp) | ||
41 | machine_class->name, machine_class->deprecation_reason); | ||
42 | } | ||
43 | |||
44 | - /* | ||
45 | - * Migration object can only be created after global properties | ||
46 | - * are applied correctly. | ||
47 | - */ | ||
48 | - migration_object_init(); | ||
49 | - | ||
50 | if (qtest_chrdev) { | ||
51 | qtest_init(qtest_chrdev, qtest_log, &error_fatal); | ||
52 | } | ||
53 | -- | 48 | -- |
54 | 2.20.1 | 49 | 2.35.3 |
55 | 50 | ||
56 | 51 | diff view generated by jsdifflib |
1 | From: Max Reitz <mreitz@redhat.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | There is no reason why the constraints we put on @replaces should be | 3 | Per the 82078 datasheet, if the end-of-track (EOT byte in |
4 | limited to drive-mirror. Therefore, move the sanity checks from | 4 | the FIFO) is more than the number of sectors per side, the |
5 | qmp_drive_mirror() to blockdev_mirror_common() so they apply to | 5 | command is terminated unsuccessfully: |
6 | blockdev-mirror as well. | ||
7 | 6 | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 7 | * 5.2.5 DATA TRANSFER TERMINATION |
9 | Reviewed-by: Eric Blake <eblake@redhat.com> | 8 | |
10 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 9 | The 82078 supports terminal count explicitly through |
10 | the TC pin and implicitly through the underrun/over- | ||
11 | run and end-of-track (EOT) functions. For full sector | ||
12 | transfers, the EOT parameter can define the last | ||
13 | sector to be transferred in a single or multisector | ||
14 | transfer. If the last sector to be transferred is a par- | ||
15 | tial sector, the host can stop transferring the data in | ||
16 | mid-sector, and the 82078 will continue to complete | ||
17 | the sector as if a hardware TC was received. The | ||
18 | only difference between these implicit functions and | ||
19 | TC is that they return "abnormal termination" result | ||
20 | status. Such status indications can be ignored if they | ||
21 | were expected. | ||
22 | |||
23 | * 6.1.3 READ TRACK | ||
24 | |||
25 | This command terminates when the EOT specified | ||
26 | number of sectors have been read. If the 82078 | ||
27 | does not find an I D Address Mark on the diskette | ||
28 | after the second· occurrence of a pulse on the | ||
29 | INDX# pin, then it sets the IC code in Status Regis- | ||
30 | ter 0 to "01" (Abnormal termination), sets the MA bit | ||
31 | in Status Register 1 to "1", and terminates the com- | ||
32 | mand. | ||
33 | |||
34 | * 6.1.6 VERIFY | ||
35 | |||
36 | Refer to Table 6-6 and Table 6-7 for information | ||
37 | concerning the values of MT and EC versus SC and | ||
38 | EOT value. | ||
39 | |||
40 | * Table 6·6. Result Phase Table | ||
41 | |||
42 | * Table 6-7. Verify Command Result Phase Table | ||
43 | |||
44 | Fix by aborting the transfer when EOT > # Sectors Per Side. | ||
45 | |||
46 | Cc: qemu-stable@nongnu.org | ||
47 | Cc: Hervé Poussineau <hpoussin@reactos.org> | ||
48 | Fixes: baca51faff0 ("floppy driver: disk geometry auto detect") | ||
49 | Reported-by: Alexander Bulekov <alxndr@bu.edu> | ||
50 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/339 | ||
51 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
52 | Message-Id: <20211118115733.4038610-2-philmd@redhat.com> | ||
53 | Reviewed-by: Hanna Reitz <hreitz@redhat.com> | ||
11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 54 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
12 | --- | 55 | --- |
13 | blockdev.c | 55 ++++++++++++++++++++++++++++++++---------------------- | 56 | hw/block/fdc.c | 8 ++++++++ |
14 | 1 file changed, 33 insertions(+), 22 deletions(-) | 57 | 1 file changed, 8 insertions(+) |
15 | 58 | ||
16 | diff --git a/blockdev.c b/blockdev.c | 59 | diff --git a/hw/block/fdc.c b/hw/block/fdc.c |
17 | index XXXXXXX..XXXXXXX 100644 | 60 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/blockdev.c | 61 | --- a/hw/block/fdc.c |
19 | +++ b/blockdev.c | 62 | +++ b/hw/block/fdc.c |
20 | @@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, | 63 | @@ -XXX,XX +XXX,XX @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction) |
21 | sync = MIRROR_SYNC_MODE_FULL; | 64 | int tmp; |
22 | } | 65 | fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]); |
23 | 66 | tmp = (fdctrl->fifo[6] - ks + 1); | |
24 | + if (has_replaces) { | 67 | + if (tmp < 0) { |
25 | + BlockDriverState *to_replace_bs; | 68 | + FLOPPY_DPRINTF("invalid EOT: %d\n", tmp); |
26 | + AioContext *replace_aio_context; | 69 | + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); |
27 | + int64_t bs_size, replace_size; | 70 | + fdctrl->fifo[3] = kt; |
28 | + | 71 | + fdctrl->fifo[4] = kh; |
29 | + bs_size = bdrv_getlength(bs); | 72 | + fdctrl->fifo[5] = ks; |
30 | + if (bs_size < 0) { | ||
31 | + error_setg_errno(errp, -bs_size, "Failed to query device's size"); | ||
32 | + return; | 73 | + return; |
33 | + } | 74 | + } |
34 | + | 75 | if (fdctrl->fifo[0] & 0x80) |
35 | + to_replace_bs = check_to_replace_node(bs, replaces, errp); | 76 | tmp += fdctrl->fifo[6]; |
36 | + if (!to_replace_bs) { | 77 | fdctrl->data_len *= tmp; |
37 | + return; | ||
38 | + } | ||
39 | + | ||
40 | + replace_aio_context = bdrv_get_aio_context(to_replace_bs); | ||
41 | + aio_context_acquire(replace_aio_context); | ||
42 | + replace_size = bdrv_getlength(to_replace_bs); | ||
43 | + aio_context_release(replace_aio_context); | ||
44 | + | ||
45 | + if (replace_size < 0) { | ||
46 | + error_setg_errno(errp, -replace_size, | ||
47 | + "Failed to query the replacement node's size"); | ||
48 | + return; | ||
49 | + } | ||
50 | + if (bs_size != replace_size) { | ||
51 | + error_setg(errp, "cannot replace image with a mirror image of " | ||
52 | + "different size"); | ||
53 | + return; | ||
54 | + } | ||
55 | + } | ||
56 | + | ||
57 | /* pass the node name to replace to mirror start since it's loose coupling | ||
58 | * and will allow to check whether the node still exist at mirror completion | ||
59 | */ | ||
60 | @@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) | ||
61 | } | ||
62 | |||
63 | if (arg->has_replaces) { | ||
64 | - BlockDriverState *to_replace_bs; | ||
65 | - AioContext *replace_aio_context; | ||
66 | - int64_t replace_size; | ||
67 | - | ||
68 | if (!arg->has_node_name) { | ||
69 | error_setg(errp, "a node-name must be provided when replacing a" | ||
70 | " named node of the graph"); | ||
71 | goto out; | ||
72 | } | ||
73 | - | ||
74 | - to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err); | ||
75 | - | ||
76 | - if (!to_replace_bs) { | ||
77 | - error_propagate(errp, local_err); | ||
78 | - goto out; | ||
79 | - } | ||
80 | - | ||
81 | - replace_aio_context = bdrv_get_aio_context(to_replace_bs); | ||
82 | - aio_context_acquire(replace_aio_context); | ||
83 | - replace_size = bdrv_getlength(to_replace_bs); | ||
84 | - aio_context_release(replace_aio_context); | ||
85 | - | ||
86 | - if (size != replace_size) { | ||
87 | - error_setg(errp, "cannot replace image with a mirror image of " | ||
88 | - "different size"); | ||
89 | - goto out; | ||
90 | - } | ||
91 | } | ||
92 | |||
93 | if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) { | ||
94 | -- | 78 | -- |
95 | 2.20.1 | 79 | 2.35.3 |
96 | 80 | ||
97 | 81 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Signed-off-by: Alberto Garcia <berto@igalia.com> | 3 | Add the reproducer from https://gitlab.com/qemu-project/qemu/-/issues/339 |
4 | |||
5 | Without the previous commit, when running 'make check-qtest-i386' | ||
6 | with QEMU configured with '--enable-sanitizers' we get: | ||
7 | |||
8 | ==4028352==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000062a00 at pc 0x5626d03c491a bp 0x7ffdb4199410 sp 0x7ffdb4198bc0 | ||
9 | READ of size 786432 at 0x619000062a00 thread T0 | ||
10 | #0 0x5626d03c4919 in __asan_memcpy (qemu-system-i386+0x1e65919) | ||
11 | #1 0x5626d1c023cc in flatview_write_continue softmmu/physmem.c:2787:13 | ||
12 | #2 0x5626d1bf0c0f in flatview_write softmmu/physmem.c:2822:14 | ||
13 | #3 0x5626d1bf0798 in address_space_write softmmu/physmem.c:2914:18 | ||
14 | #4 0x5626d1bf0f37 in address_space_rw softmmu/physmem.c:2924:16 | ||
15 | #5 0x5626d1bf14c8 in cpu_physical_memory_rw softmmu/physmem.c:2933:5 | ||
16 | #6 0x5626d0bd5649 in cpu_physical_memory_write include/exec/cpu-common.h:82:5 | ||
17 | #7 0x5626d0bd0a07 in i8257_dma_write_memory hw/dma/i8257.c:452:9 | ||
18 | #8 0x5626d09f825d in fdctrl_transfer_handler hw/block/fdc.c:1616:13 | ||
19 | #9 0x5626d0a048b4 in fdctrl_start_transfer hw/block/fdc.c:1539:13 | ||
20 | #10 0x5626d09f4c3e in fdctrl_write_data hw/block/fdc.c:2266:13 | ||
21 | #11 0x5626d09f22f7 in fdctrl_write hw/block/fdc.c:829:9 | ||
22 | #12 0x5626d1c20bc5 in portio_write softmmu/ioport.c:207:17 | ||
23 | |||
24 | 0x619000062a00 is located 0 bytes to the right of 512-byte region [0x619000062800,0x619000062a00) | ||
25 | allocated by thread T0 here: | ||
26 | #0 0x5626d03c66ec in posix_memalign (qemu-system-i386+0x1e676ec) | ||
27 | #1 0x5626d2b988d4 in qemu_try_memalign util/oslib-posix.c:210:11 | ||
28 | #2 0x5626d2b98b0c in qemu_memalign util/oslib-posix.c:226:27 | ||
29 | #3 0x5626d09fbaf0 in fdctrl_realize_common hw/block/fdc.c:2341:20 | ||
30 | #4 0x5626d0a150ed in isabus_fdc_realize hw/block/fdc-isa.c:113:5 | ||
31 | #5 0x5626d2367935 in device_set_realized hw/core/qdev.c:531:13 | ||
32 | |||
33 | SUMMARY: AddressSanitizer: heap-buffer-overflow (qemu-system-i386+0x1e65919) in __asan_memcpy | ||
34 | Shadow bytes around the buggy address: | ||
35 | 0x0c32800044f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
36 | 0x0c3280004500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
37 | 0x0c3280004510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
38 | 0x0c3280004520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
39 | 0x0c3280004530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
40 | =>0x0c3280004540:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
41 | 0x0c3280004550: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
42 | 0x0c3280004560: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
43 | 0x0c3280004570: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
44 | 0x0c3280004580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa | ||
45 | 0x0c3280004590: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd | ||
46 | Shadow byte legend (one shadow byte represents 8 application bytes): | ||
47 | Addressable: 00 | ||
48 | Heap left redzone: fa | ||
49 | Freed heap region: fd | ||
50 | ==4028352==ABORTING | ||
51 | |||
52 | [ kwolf: Added snapshot=on to prevent write file lock failure ] | ||
53 | |||
54 | Reported-by: Alexander Bulekov <alxndr@bu.edu> | ||
55 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
56 | Reviewed-by: Alexander Bulekov <alxndr@bu.edu> | ||
4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 57 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
5 | --- | 58 | --- |
6 | block/copy-on-read.c | 2 +- | 59 | tests/qtest/fdc-test.c | 21 +++++++++++++++++++++ |
7 | block/crypto.c | 2 +- | 60 | 1 file changed, 21 insertions(+) |
8 | block/replication.c | 2 +- | ||
9 | 3 files changed, 3 insertions(+), 3 deletions(-) | ||
10 | 61 | ||
11 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | 62 | diff --git a/tests/qtest/fdc-test.c b/tests/qtest/fdc-test.c |
12 | index XXXXXXX..XXXXXXX 100644 | 63 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/block/copy-on-read.c | 64 | --- a/tests/qtest/fdc-test.c |
14 | +++ b/block/copy-on-read.c | 65 | +++ b/tests/qtest/fdc-test.c |
15 | @@ -XXX,XX +XXX,XX @@ static bool cor_recurse_is_first_non_filter(BlockDriverState *bs, | 66 | @@ -XXX,XX +XXX,XX @@ static void test_cve_2021_20196(void) |
67 | qtest_quit(s); | ||
16 | } | 68 | } |
17 | 69 | ||
18 | 70 | +static void test_cve_2021_3507(void) | |
19 | -BlockDriver bdrv_copy_on_read = { | 71 | +{ |
20 | +static BlockDriver bdrv_copy_on_read = { | 72 | + QTestState *s; |
21 | .format_name = "copy-on-read", | 73 | + |
22 | 74 | + s = qtest_initf("-nographic -m 32M -nodefaults " | |
23 | .bdrv_open = cor_open, | 75 | + "-drive file=%s,format=raw,if=floppy,snapshot=on", |
24 | diff --git a/block/crypto.c b/block/crypto.c | 76 | + test_image); |
25 | index XXXXXXX..XXXXXXX 100644 | 77 | + qtest_outl(s, 0x9, 0x0a0206); |
26 | --- a/block/crypto.c | 78 | + qtest_outw(s, 0x3f4, 0x1600); |
27 | +++ b/block/crypto.c | 79 | + qtest_outw(s, 0x3f4, 0x0000); |
28 | @@ -XXX,XX +XXX,XX @@ static const char *const block_crypto_strong_runtime_opts[] = { | 80 | + qtest_outw(s, 0x3f4, 0x0000); |
29 | NULL | 81 | + qtest_outw(s, 0x3f4, 0x0000); |
30 | }; | 82 | + qtest_outw(s, 0x3f4, 0x0200); |
31 | 83 | + qtest_outw(s, 0x3f4, 0x0200); | |
32 | -BlockDriver bdrv_crypto_luks = { | 84 | + qtest_outw(s, 0x3f4, 0x0000); |
33 | +static BlockDriver bdrv_crypto_luks = { | 85 | + qtest_outw(s, 0x3f4, 0x0000); |
34 | .format_name = "luks", | 86 | + qtest_outw(s, 0x3f4, 0x0000); |
35 | .instance_size = sizeof(BlockCrypto), | 87 | + qtest_quit(s); |
36 | .bdrv_probe = block_crypto_probe_luks, | 88 | +} |
37 | diff --git a/block/replication.c b/block/replication.c | 89 | + |
38 | index XXXXXXX..XXXXXXX 100644 | 90 | int main(int argc, char **argv) |
39 | --- a/block/replication.c | 91 | { |
40 | +++ b/block/replication.c | 92 | int fd; |
41 | @@ -XXX,XX +XXX,XX @@ static const char *const replication_strong_runtime_opts[] = { | 93 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) |
42 | NULL | 94 | qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19); |
43 | }; | 95 | qtest_add_func("/fdc/fuzz-registers", fuzz_registers); |
44 | 96 | qtest_add_func("/fdc/fuzz/cve_2021_20196", test_cve_2021_20196); | |
45 | -BlockDriver bdrv_replication = { | 97 | + qtest_add_func("/fdc/fuzz/cve_2021_3507", test_cve_2021_3507); |
46 | +static BlockDriver bdrv_replication = { | 98 | |
47 | .format_name = "replication", | 99 | ret = g_test_run(); |
48 | .instance_size = sizeof(BDRVReplicationState), | ||
49 | 100 | ||
50 | -- | 101 | -- |
51 | 2.20.1 | 102 | 2.35.3 |
52 | 103 | ||
53 | 104 | diff view generated by jsdifflib |
1 | From: Sam Eiderman <shmuel.eiderman@oracle.com> | 1 | From: Eric Blake <eblake@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Commit 509d39aa22909c0ed1aabf896865f19c81fb38a1 added support for read | 3 | The next patch wants to adjust whether the NBD server code advertises |
4 | only VMDKs of version 3. | 4 | MULTI_CONN based on whether it is known if the server limits to |
5 | exactly one client. For a server started by QMP, this information is | ||
6 | obtained through nbd_server_start (which can support more than one | ||
7 | export); but for qemu-nbd (which supports exactly one export), it is | ||
8 | controlled only by the command-line option -e/--shared. Since we | ||
9 | already have a hook function used by qemu-nbd, it's easiest to just | ||
10 | alter its signature to fit our needs. | ||
5 | 11 | ||
6 | This commit fixes the probe function to correctly handle descriptors of | 12 | Signed-off-by: Eric Blake <eblake@redhat.com> |
7 | version 3. | 13 | Message-Id: <20220512004924.417153-2-eblake@redhat.com> |
8 | |||
9 | This commit has two effects: | ||
10 | 1. We no longer need to supply '-f vmdk' when pointing to descriptor | ||
11 | files of version 3 in qemu/qemu-img command line arguments. | ||
12 | 2. This fixes the scenario where a VMDK points to a parent version 3 | ||
13 | descriptor file which is being probed as "raw" instead of "vmdk". | ||
14 | |||
15 | Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> | ||
16 | Reviewed-by: Mark Kanda <mark.kanda@oracle.com> | ||
17 | Signed-off-by: Shmuel Eiderman <shmuel.eiderman@oracle.com> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
19 | --- | 15 | --- |
20 | block/vmdk.c | 6 ++++-- | 16 | include/block/nbd.h | 2 +- |
21 | 1 file changed, 4 insertions(+), 2 deletions(-) | 17 | blockdev-nbd.c | 8 ++++---- |
18 | qemu-nbd.c | 2 +- | ||
19 | 3 files changed, 6 insertions(+), 6 deletions(-) | ||
22 | 20 | ||
23 | diff --git a/block/vmdk.c b/block/vmdk.c | 21 | diff --git a/include/block/nbd.h b/include/block/nbd.h |
24 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/block/vmdk.c | 23 | --- a/include/block/nbd.h |
26 | +++ b/block/vmdk.c | 24 | +++ b/include/block/nbd.h |
27 | @@ -XXX,XX +XXX,XX @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename) | 25 | @@ -XXX,XX +XXX,XX @@ void nbd_client_new(QIOChannelSocket *sioc, |
28 | } | 26 | void nbd_client_get(NBDClient *client); |
29 | if (end - p >= strlen("version=X\n")) { | 27 | void nbd_client_put(NBDClient *client); |
30 | if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 || | 28 | |
31 | - strncmp("version=2\n", p, strlen("version=2\n")) == 0) { | 29 | -void nbd_server_is_qemu_nbd(bool value); |
32 | + strncmp("version=2\n", p, strlen("version=2\n")) == 0 || | 30 | +void nbd_server_is_qemu_nbd(int max_connections); |
33 | + strncmp("version=3\n", p, strlen("version=3\n")) == 0) { | 31 | bool nbd_server_is_running(void); |
34 | return 100; | 32 | void nbd_server_start(SocketAddress *addr, const char *tls_creds, |
35 | } | 33 | const char *tls_authz, uint32_t max_connections, |
36 | } | 34 | diff --git a/blockdev-nbd.c b/blockdev-nbd.c |
37 | if (end - p >= strlen("version=X\r\n")) { | 35 | index XXXXXXX..XXXXXXX 100644 |
38 | if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 || | 36 | --- a/blockdev-nbd.c |
39 | - strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) { | 37 | +++ b/blockdev-nbd.c |
40 | + strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0 || | 38 | @@ -XXX,XX +XXX,XX @@ typedef struct NBDServerData { |
41 | + strncmp("version=3\r\n", p, strlen("version=3\r\n")) == 0) { | 39 | } NBDServerData; |
42 | return 100; | 40 | |
43 | } | 41 | static NBDServerData *nbd_server; |
44 | } | 42 | -static bool is_qemu_nbd; |
43 | +static int qemu_nbd_connections = -1; /* Non-negative if this is qemu-nbd */ | ||
44 | |||
45 | static void nbd_update_server_watch(NBDServerData *s); | ||
46 | |||
47 | -void nbd_server_is_qemu_nbd(bool value) | ||
48 | +void nbd_server_is_qemu_nbd(int max_connections) | ||
49 | { | ||
50 | - is_qemu_nbd = value; | ||
51 | + qemu_nbd_connections = max_connections; | ||
52 | } | ||
53 | |||
54 | bool nbd_server_is_running(void) | ||
55 | { | ||
56 | - return nbd_server || is_qemu_nbd; | ||
57 | + return nbd_server || qemu_nbd_connections >= 0; | ||
58 | } | ||
59 | |||
60 | static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) | ||
61 | diff --git a/qemu-nbd.c b/qemu-nbd.c | ||
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/qemu-nbd.c | ||
64 | +++ b/qemu-nbd.c | ||
65 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) | ||
66 | |||
67 | bs->detect_zeroes = detect_zeroes; | ||
68 | |||
69 | - nbd_server_is_qemu_nbd(true); | ||
70 | + nbd_server_is_qemu_nbd(shared); | ||
71 | |||
72 | export_opts = g_new(BlockExportOptions, 1); | ||
73 | *export_opts = (BlockExportOptions) { | ||
45 | -- | 74 | -- |
46 | 2.20.1 | 75 | 2.35.3 |
47 | |||
48 | diff view generated by jsdifflib |
1 | 232 is marked as generic, but commit 12efe428c9e added code that assumes | 1 | From: Eric Blake <eblake@redhat.com> |
---|---|---|---|
2 | qcow2. What the new test really needs is backing files and support for | 2 | |
3 | updating the backing file link (.bdrv_change_backing_file). | 3 | According to the NBD spec, a server that advertises |
4 | 4 | NBD_FLAG_CAN_MULTI_CONN promises that multiple client connections will | |
5 | Split the non-generic code into a new test case 247 and make it work | 5 | not see any cache inconsistencies: when properly separated by a single |
6 | with qed, too. | 6 | flush, actions performed by one client will be visible to another |
7 | 7 | client, regardless of which client did the flush. | |
8 | |||
9 | We always satisfy these conditions in qemu - even when we support | ||
10 | multiple clients, ALL clients go through a single point of reference | ||
11 | into the block layer, with no local caching. The effect of one client | ||
12 | is instantly visible to the next client. Even if our backend were a | ||
13 | network device, we argue that any multi-path caching effects that | ||
14 | would cause inconsistencies in back-to-back actions not seeing the | ||
15 | effect of previous actions would be a bug in that backend, and not the | ||
16 | fault of caching in qemu. As such, it is safe to unconditionally | ||
17 | advertise CAN_MULTI_CONN for any qemu NBD server situation that | ||
18 | supports parallel clients. | ||
19 | |||
20 | Note, however, that we don't want to advertise CAN_MULTI_CONN when we | ||
21 | know that a second client cannot connect (for historical reasons, | ||
22 | qemu-nbd defaults to a single connection while nbd-server-add and QMP | ||
23 | commands default to unlimited connections; but we already have | ||
24 | existing means to let either style of NBD server creation alter those | ||
25 | defaults). This is visible by no longer advertising MULTI_CONN for | ||
26 | 'qemu-nbd -r' without -e, as in the iotest nbd-qemu-allocation. | ||
27 | |||
28 | The harder part of this patch is setting up an iotest to demonstrate | ||
29 | behavior of multiple NBD clients to a single server. It might be | ||
30 | possible with parallel qemu-io processes, but I found it easier to do | ||
31 | in python with the help of libnbd, and help from Nir and Vladimir in | ||
32 | writing the test. | ||
33 | |||
34 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
35 | Suggested-by: Nir Soffer <nsoffer@redhat.com> | ||
36 | Suggested-by: Vladimir Sementsov-Ogievskiy <v.sementsov-og@mail.ru> | ||
37 | Message-Id: <20220512004924.417153-3-eblake@redhat.com> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 38 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
9 | --- | 39 | --- |
10 | tests/qemu-iotests/232 | 30 --------------- | 40 | qapi/block-export.json | 8 +- |
11 | tests/qemu-iotests/232.out | 20 ---------- | 41 | docs/interop/nbd.txt | 1 + |
12 | tests/qemu-iotests/247 | 79 ++++++++++++++++++++++++++++++++++++++ | 42 | docs/tools/qemu-nbd.rst | 3 +- |
13 | tests/qemu-iotests/247.out | 22 +++++++++++ | 43 | include/block/nbd.h | 3 +- |
14 | tests/qemu-iotests/group | 1 + | 44 | blockdev-nbd.c | 5 + |
15 | 5 files changed, 102 insertions(+), 50 deletions(-) | 45 | nbd/server.c | 10 +- |
16 | create mode 100755 tests/qemu-iotests/247 | 46 | MAINTAINERS | 1 + |
17 | create mode 100644 tests/qemu-iotests/247.out | 47 | tests/qemu-iotests/tests/nbd-multiconn | 145 ++++++++++++++++++ |
18 | 48 | tests/qemu-iotests/tests/nbd-multiconn.out | 5 + | |
19 | diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232 | 49 | .../tests/nbd-qemu-allocation.out | 2 +- |
20 | index XXXXXXX..XXXXXXX 100755 | 50 | 10 files changed, 172 insertions(+), 11 deletions(-) |
21 | --- a/tests/qemu-iotests/232 | 51 | create mode 100755 tests/qemu-iotests/tests/nbd-multiconn |
22 | +++ b/tests/qemu-iotests/232 | 52 | create mode 100644 tests/qemu-iotests/tests/nbd-multiconn.out |
23 | @@ -XXX,XX +XXX,XX @@ run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,a | 53 | |
24 | run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on | 54 | diff --git a/qapi/block-export.json b/qapi/block-export.json |
25 | run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0 | 55 | index XXXXXXX..XXXXXXX 100644 |
26 | 56 | --- a/qapi/block-export.json | |
27 | -echo | 57 | +++ b/qapi/block-export.json |
28 | -echo "=== Try commit to backing file with auto-read-only ===" | 58 | @@ -XXX,XX +XXX,XX @@ |
29 | -echo | 59 | # recreated on the fly while the NBD server is active. |
30 | - | 60 | # If missing, it will default to denying access (since 4.0). |
31 | -TEST_IMG="$TEST_IMG.0" _make_test_img $size | 61 | # @max-connections: The maximum number of connections to allow at the same |
32 | -TEST_IMG="$TEST_IMG.1" _make_test_img $size | 62 | -# time, 0 for unlimited. (since 5.2; default: 0) |
33 | -TEST_IMG="$TEST_IMG.2" _make_test_img $size | 63 | +# time, 0 for unlimited. Setting this to 1 also stops |
34 | -TEST_IMG="$TEST_IMG.3" _make_test_img $size | 64 | +# the server from advertising multiple client support |
35 | -TEST_IMG="$TEST_IMG.4" _make_test_img $size | 65 | +# (since 5.2; default: 0) |
36 | - | 66 | # |
37 | -(cat <<EOF | 67 | # Since: 4.2 |
38 | -{"execute":"qmp_capabilities"} | 68 | ## |
39 | -{"execute":"block-commit", | 69 | @@ -XXX,XX +XXX,XX @@ |
40 | - "arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}} | 70 | # recreated on the fly while the NBD server is active. |
41 | -EOF | 71 | # If missing, it will default to denying access (since 4.0). |
42 | -sleep 1 | 72 | # @max-connections: The maximum number of connections to allow at the same |
43 | -echo '{"execute":"quit"}' | 73 | -# time, 0 for unlimited. (since 5.2; default: 0) |
44 | -) | $QEMU -qmp stdio -nographic -nodefaults \ | 74 | +# time, 0 for unlimited. Setting this to 1 also stops |
45 | - -blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \ | 75 | +# the server from advertising multiple client support |
46 | - -blockdev qcow2,node-name=format-0,file=file-0,read-only=on \ | 76 | +# (since 5.2; default: 0). |
47 | - -blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \ | 77 | # |
48 | - -blockdev qcow2,node-name=format-1,file=file-1,read-only=on,backing=format-0 \ | 78 | # Returns: error if the server is already running. |
49 | - -blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \ | 79 | # |
50 | - -blockdev qcow2,node-name=format-2,file=file-2,read-only=on,backing=format-1 \ | 80 | diff --git a/docs/interop/nbd.txt b/docs/interop/nbd.txt |
51 | - -blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \ | 81 | index XXXXXXX..XXXXXXX 100644 |
52 | - -blockdev qcow2,node-name=format-3,file=file-3,read-only=on,backing=format-2 \ | 82 | --- a/docs/interop/nbd.txt |
53 | - -blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \ | 83 | +++ b/docs/interop/nbd.txt |
54 | - -blockdev qcow2,node-name=format-4,file=file-4,read-only=on,backing=format-3 | | 84 | @@ -XXX,XX +XXX,XX @@ NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE |
55 | - _filter_qmp | 85 | * 4.2: NBD_FLAG_CAN_MULTI_CONN for shareable read-only exports, |
56 | - | 86 | NBD_CMD_FLAG_FAST_ZERO |
57 | # success, all done | 87 | * 5.2: NBD_CMD_BLOCK_STATUS for "qemu:allocation-depth" |
58 | echo "*** done" | 88 | +* 7.1: NBD_FLAG_CAN_MULTI_CONN for shareable writable exports |
59 | rm -f $seq.full | 89 | diff --git a/docs/tools/qemu-nbd.rst b/docs/tools/qemu-nbd.rst |
60 | diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out | 90 | index XXXXXXX..XXXXXXX 100644 |
61 | index XXXXXXX..XXXXXXX 100644 | 91 | --- a/docs/tools/qemu-nbd.rst |
62 | --- a/tests/qemu-iotests/232.out | 92 | +++ b/docs/tools/qemu-nbd.rst |
63 | +++ b/tests/qemu-iotests/232.out | 93 | @@ -XXX,XX +XXX,XX @@ driver options if :option:`--image-opts` is specified. |
64 | @@ -XXX,XX +XXX,XX @@ QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read | 94 | .. option:: -e, --shared=NUM |
65 | QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied | 95 | |
66 | node0: TEST_DIR/t.IMGFMT (file) | 96 | Allow up to *NUM* clients to share the device (default |
67 | QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied | 97 | - ``1``), 0 for unlimited. Safe for readers, but for now, |
68 | - | 98 | - consistency is not guaranteed between multiple writers. |
69 | -=== Try commit to backing file with auto-read-only === | 99 | + ``1``), 0 for unlimited. |
70 | - | 100 | |
71 | -Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728 | 101 | .. option:: -t, --persistent |
72 | -Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728 | 102 | |
73 | -Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728 | 103 | diff --git a/include/block/nbd.h b/include/block/nbd.h |
74 | -Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728 | 104 | index XXXXXXX..XXXXXXX 100644 |
75 | -Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728 | 105 | --- a/include/block/nbd.h |
76 | -QMP_VERSION | 106 | +++ b/include/block/nbd.h |
77 | -{"return": {}} | 107 | @@ -XXX,XX +XXX,XX @@ |
78 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} | 108 | /* |
79 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} | 109 | - * Copyright (C) 2016-2020 Red Hat, Inc. |
80 | -{"return": {}} | 110 | + * Copyright (C) 2016-2022 Red Hat, Inc. |
81 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} | 111 | * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws> |
82 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} | 112 | * |
83 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}} | 113 | * Network Block Device |
84 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} | 114 | @@ -XXX,XX +XXX,XX @@ void nbd_client_put(NBDClient *client); |
85 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} | 115 | |
86 | -{"return": {}} | 116 | void nbd_server_is_qemu_nbd(int max_connections); |
87 | -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} | 117 | bool nbd_server_is_running(void); |
88 | *** done | 118 | +int nbd_server_max_connections(void); |
89 | diff --git a/tests/qemu-iotests/247 b/tests/qemu-iotests/247 | 119 | void nbd_server_start(SocketAddress *addr, const char *tls_creds, |
120 | const char *tls_authz, uint32_t max_connections, | ||
121 | Error **errp); | ||
122 | diff --git a/blockdev-nbd.c b/blockdev-nbd.c | ||
123 | index XXXXXXX..XXXXXXX 100644 | ||
124 | --- a/blockdev-nbd.c | ||
125 | +++ b/blockdev-nbd.c | ||
126 | @@ -XXX,XX +XXX,XX @@ bool nbd_server_is_running(void) | ||
127 | return nbd_server || qemu_nbd_connections >= 0; | ||
128 | } | ||
129 | |||
130 | +int nbd_server_max_connections(void) | ||
131 | +{ | ||
132 | + return nbd_server ? nbd_server->max_connections : qemu_nbd_connections; | ||
133 | +} | ||
134 | + | ||
135 | static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) | ||
136 | { | ||
137 | nbd_client_put(client); | ||
138 | diff --git a/nbd/server.c b/nbd/server.c | ||
139 | index XXXXXXX..XXXXXXX 100644 | ||
140 | --- a/nbd/server.c | ||
141 | +++ b/nbd/server.c | ||
142 | @@ -XXX,XX +XXX,XX @@ | ||
143 | /* | ||
144 | - * Copyright (C) 2016-2021 Red Hat, Inc. | ||
145 | + * Copyright (C) 2016-2022 Red Hat, Inc. | ||
146 | * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws> | ||
147 | * | ||
148 | * Network Block Device Server Side | ||
149 | @@ -XXX,XX +XXX,XX @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, | ||
150 | int64_t size; | ||
151 | uint64_t perm, shared_perm; | ||
152 | bool readonly = !exp_args->writable; | ||
153 | - bool shared = !exp_args->writable; | ||
154 | BlockDirtyBitmapOrStrList *bitmaps; | ||
155 | size_t i; | ||
156 | int ret; | ||
157 | @@ -XXX,XX +XXX,XX @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, | ||
158 | exp->description = g_strdup(arg->description); | ||
159 | exp->nbdflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_FLUSH | | ||
160 | NBD_FLAG_SEND_FUA | NBD_FLAG_SEND_CACHE); | ||
161 | + | ||
162 | + if (nbd_server_max_connections() != 1) { | ||
163 | + exp->nbdflags |= NBD_FLAG_CAN_MULTI_CONN; | ||
164 | + } | ||
165 | if (readonly) { | ||
166 | exp->nbdflags |= NBD_FLAG_READ_ONLY; | ||
167 | - if (shared) { | ||
168 | - exp->nbdflags |= NBD_FLAG_CAN_MULTI_CONN; | ||
169 | - } | ||
170 | } else { | ||
171 | exp->nbdflags |= (NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_WRITE_ZEROES | | ||
172 | NBD_FLAG_SEND_FAST_ZERO); | ||
173 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
174 | index XXXXXXX..XXXXXXX 100644 | ||
175 | --- a/MAINTAINERS | ||
176 | +++ b/MAINTAINERS | ||
177 | @@ -XXX,XX +XXX,XX @@ F: qemu-nbd.* | ||
178 | F: blockdev-nbd.c | ||
179 | F: docs/interop/nbd.txt | ||
180 | F: docs/tools/qemu-nbd.rst | ||
181 | +F: tests/qemu-iotests/tests/*nbd* | ||
182 | T: git https://repo.or.cz/qemu/ericb.git nbd | ||
183 | T: git https://src.openvz.org/scm/~vsementsov/qemu.git nbd | ||
184 | |||
185 | diff --git a/tests/qemu-iotests/tests/nbd-multiconn b/tests/qemu-iotests/tests/nbd-multiconn | ||
90 | new file mode 100755 | 186 | new file mode 100755 |
91 | index XXXXXXX..XXXXXXX | 187 | index XXXXXXX..XXXXXXX |
92 | --- /dev/null | 188 | --- /dev/null |
93 | +++ b/tests/qemu-iotests/247 | 189 | +++ b/tests/qemu-iotests/tests/nbd-multiconn |
94 | @@ -XXX,XX +XXX,XX @@ | 190 | @@ -XXX,XX +XXX,XX @@ |
95 | +#!/usr/bin/env bash | 191 | +#!/usr/bin/env python3 |
96 | +# | 192 | +# group: rw auto quick |
97 | +# Test for auto-read-only with commit block job | 193 | +# |
98 | +# | 194 | +# Test cases for NBD multi-conn advertisement |
99 | +# Copyright (C) 2019 Red Hat, Inc. | 195 | +# |
196 | +# Copyright (C) 2022 Red Hat, Inc. | ||
100 | +# | 197 | +# |
101 | +# This program is free software; you can redistribute it and/or modify | 198 | +# This program is free software; you can redistribute it and/or modify |
102 | +# it under the terms of the GNU General Public License as published by | 199 | +# it under the terms of the GNU General Public License as published by |
103 | +# the Free Software Foundation; either version 2 of the License, or | 200 | +# the Free Software Foundation; either version 2 of the License, or |
104 | +# (at your option) any later version. | 201 | +# (at your option) any later version. |
... | ... | ||
108 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 205 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
109 | +# GNU General Public License for more details. | 206 | +# GNU General Public License for more details. |
110 | +# | 207 | +# |
111 | +# You should have received a copy of the GNU General Public License | 208 | +# You should have received a copy of the GNU General Public License |
112 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | 209 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
113 | +# | 210 | + |
114 | + | 211 | +import os |
115 | +# creator | 212 | +from contextlib import contextmanager |
116 | +owner=kwolf@redhat.com | 213 | +import iotests |
117 | + | 214 | +from iotests import qemu_img_create, qemu_io |
118 | +seq=`basename $0` | 215 | + |
119 | +echo "QA output created by $seq" | 216 | + |
120 | + | 217 | +disk = os.path.join(iotests.test_dir, 'disk') |
121 | +status=1 # failure is the default! | 218 | +size = '4M' |
122 | + | 219 | +nbd_sock = os.path.join(iotests.sock_dir, 'nbd_sock') |
123 | +_cleanup() | 220 | +nbd_uri = 'nbd+unix:///{}?socket=' + nbd_sock |
124 | +{ | 221 | + |
125 | + _cleanup_test_img | 222 | + |
126 | + rm -f $TEST_IMG.[01234] | 223 | +@contextmanager |
127 | +} | 224 | +def open_nbd(export_name): |
128 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | 225 | + h = nbd.NBD() |
129 | + | 226 | + try: |
130 | +# get standard environment, filters and checks | 227 | + h.connect_uri(nbd_uri.format(export_name)) |
131 | +. ./common.rc | 228 | + yield h |
132 | +. ./common.filter | 229 | + finally: |
133 | + | 230 | + h.shutdown() |
134 | +# Requires backing files and .bdrv_change_backing_file support | 231 | + |
135 | +_supported_fmt qcow2 qed | 232 | +class TestNbdMulticonn(iotests.QMPTestCase): |
136 | +_supported_proto file | 233 | + def setUp(self): |
137 | +_supported_os Linux | 234 | + qemu_img_create('-f', iotests.imgfmt, disk, size) |
138 | + | 235 | + qemu_io('-c', 'w -P 1 0 2M', '-c', 'w -P 2 2M 2M', disk) |
139 | +size=128M | 236 | + |
140 | + | 237 | + self.vm = iotests.VM() |
141 | +echo | 238 | + self.vm.launch() |
142 | +echo "=== Try commit to backing file with auto-read-only ===" | 239 | + result = self.vm.qmp('blockdev-add', { |
143 | +echo | 240 | + 'driver': 'qcow2', |
144 | +TEST_IMG="$TEST_IMG.0" _make_test_img $size | 241 | + 'node-name': 'n', |
145 | +TEST_IMG="$TEST_IMG.1" _make_test_img $size | 242 | + 'file': {'driver': 'file', 'filename': disk} |
146 | +TEST_IMG="$TEST_IMG.2" _make_test_img $size | 243 | + }) |
147 | +TEST_IMG="$TEST_IMG.3" _make_test_img $size | 244 | + self.assert_qmp(result, 'return', {}) |
148 | +TEST_IMG="$TEST_IMG.4" _make_test_img $size | 245 | + |
149 | + | 246 | + def tearDown(self): |
150 | +(cat <<EOF | 247 | + self.vm.shutdown() |
151 | +{"execute":"qmp_capabilities"} | 248 | + os.remove(disk) |
152 | +{"execute":"block-commit", | 249 | + try: |
153 | + "arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}} | 250 | + os.remove(nbd_sock) |
154 | +EOF | 251 | + except OSError: |
155 | +sleep 1 | 252 | + pass |
156 | +echo '{"execute":"quit"}' | 253 | + |
157 | +) | $QEMU -qmp stdio -nographic -nodefaults \ | 254 | + @contextmanager |
158 | + -blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \ | 255 | + def run_server(self, max_connections=None): |
159 | + -blockdev $IMGFMT,node-name=format-0,file=file-0,read-only=on \ | 256 | + args = { |
160 | + -blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \ | 257 | + 'addr': { |
161 | + -blockdev $IMGFMT,node-name=format-1,file=file-1,read-only=on,backing=format-0 \ | 258 | + 'type': 'unix', |
162 | + -blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \ | 259 | + 'data': {'path': nbd_sock} |
163 | + -blockdev $IMGFMT,node-name=format-2,file=file-2,read-only=on,backing=format-1 \ | 260 | + } |
164 | + -blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \ | 261 | + } |
165 | + -blockdev $IMGFMT,node-name=format-3,file=file-3,read-only=on,backing=format-2 \ | 262 | + if max_connections is not None: |
166 | + -blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \ | 263 | + args['max-connections'] = max_connections |
167 | + -blockdev $IMGFMT,node-name=format-4,file=file-4,read-only=on,backing=format-3 | | 264 | + |
168 | + _filter_qmp | 265 | + result = self.vm.qmp('nbd-server-start', args) |
169 | + | 266 | + self.assert_qmp(result, 'return', {}) |
170 | +# success, all done | 267 | + yield |
171 | +echo "*** done" | 268 | + |
172 | +rm -f $seq.full | 269 | + result = self.vm.qmp('nbd-server-stop') |
173 | +status=0 | 270 | + self.assert_qmp(result, 'return', {}) |
174 | diff --git a/tests/qemu-iotests/247.out b/tests/qemu-iotests/247.out | 271 | + |
272 | + def add_export(self, name, writable=None): | ||
273 | + args = { | ||
274 | + 'type': 'nbd', | ||
275 | + 'id': name, | ||
276 | + 'node-name': 'n', | ||
277 | + 'name': name, | ||
278 | + } | ||
279 | + if writable is not None: | ||
280 | + args['writable'] = writable | ||
281 | + | ||
282 | + result = self.vm.qmp('block-export-add', args) | ||
283 | + self.assert_qmp(result, 'return', {}) | ||
284 | + | ||
285 | + def test_default_settings(self): | ||
286 | + with self.run_server(): | ||
287 | + self.add_export('r') | ||
288 | + self.add_export('w', writable=True) | ||
289 | + with open_nbd('r') as h: | ||
290 | + self.assertTrue(h.can_multi_conn()) | ||
291 | + with open_nbd('w') as h: | ||
292 | + self.assertTrue(h.can_multi_conn()) | ||
293 | + | ||
294 | + def test_limited_connections(self): | ||
295 | + with self.run_server(max_connections=1): | ||
296 | + self.add_export('r') | ||
297 | + self.add_export('w', writable=True) | ||
298 | + with open_nbd('r') as h: | ||
299 | + self.assertFalse(h.can_multi_conn()) | ||
300 | + with open_nbd('w') as h: | ||
301 | + self.assertFalse(h.can_multi_conn()) | ||
302 | + | ||
303 | + def test_parallel_writes(self): | ||
304 | + with self.run_server(): | ||
305 | + self.add_export('w', writable=True) | ||
306 | + | ||
307 | + clients = [nbd.NBD() for _ in range(3)] | ||
308 | + for c in clients: | ||
309 | + c.connect_uri(nbd_uri.format('w')) | ||
310 | + self.assertTrue(c.can_multi_conn()) | ||
311 | + | ||
312 | + initial_data = clients[0].pread(1024 * 1024, 0) | ||
313 | + self.assertEqual(initial_data, b'\x01' * 1024 * 1024) | ||
314 | + | ||
315 | + updated_data = b'\x03' * 1024 * 1024 | ||
316 | + clients[1].pwrite(updated_data, 0) | ||
317 | + clients[2].flush() | ||
318 | + current_data = clients[0].pread(1024 * 1024, 0) | ||
319 | + | ||
320 | + self.assertEqual(updated_data, current_data) | ||
321 | + | ||
322 | + for i in range(3): | ||
323 | + clients[i].shutdown() | ||
324 | + | ||
325 | + | ||
326 | +if __name__ == '__main__': | ||
327 | + try: | ||
328 | + # Easier to use libnbd than to try and set up parallel | ||
329 | + # 'qemu-nbd --list' or 'qemu-io' processes, but not all systems | ||
330 | + # have libnbd installed. | ||
331 | + import nbd # type: ignore | ||
332 | + | ||
333 | + iotests.main(supported_fmts=['qcow2']) | ||
334 | + except ImportError: | ||
335 | + iotests.notrun('libnbd not installed') | ||
336 | diff --git a/tests/qemu-iotests/tests/nbd-multiconn.out b/tests/qemu-iotests/tests/nbd-multiconn.out | ||
175 | new file mode 100644 | 337 | new file mode 100644 |
176 | index XXXXXXX..XXXXXXX | 338 | index XXXXXXX..XXXXXXX |
177 | --- /dev/null | 339 | --- /dev/null |
178 | +++ b/tests/qemu-iotests/247.out | 340 | +++ b/tests/qemu-iotests/tests/nbd-multiconn.out |
179 | @@ -XXX,XX +XXX,XX @@ | 341 | @@ -XXX,XX +XXX,XX @@ |
180 | +QA output created by 247 | 342 | +... |
181 | + | 343 | +---------------------------------------------------------------------- |
182 | +=== Try commit to backing file with auto-read-only === | 344 | +Ran 3 tests |
183 | + | 345 | + |
184 | +Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728 | 346 | +OK |
185 | +Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728 | 347 | diff --git a/tests/qemu-iotests/tests/nbd-qemu-allocation.out b/tests/qemu-iotests/tests/nbd-qemu-allocation.out |
186 | +Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728 | 348 | index XXXXXXX..XXXXXXX 100644 |
187 | +Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728 | 349 | --- a/tests/qemu-iotests/tests/nbd-qemu-allocation.out |
188 | +Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728 | 350 | +++ b/tests/qemu-iotests/tests/nbd-qemu-allocation.out |
189 | +QMP_VERSION | 351 | @@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 1048576 |
190 | +{"return": {}} | 352 | exports available: 1 |
191 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} | 353 | export: '' |
192 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} | 354 | size: 4194304 |
193 | +{"return": {}} | 355 | - flags: 0x58f ( readonly flush fua df multi cache ) |
194 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} | 356 | + flags: 0x48f ( readonly flush fua df cache ) |
195 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} | 357 | min block: 1 |
196 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}} | 358 | opt block: 4096 |
197 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} | 359 | max block: 33554432 |
198 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} | ||
199 | +{"return": {}} | ||
200 | +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} | ||
201 | +*** done | ||
202 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
203 | index XXXXXXX..XXXXXXX 100644 | ||
204 | --- a/tests/qemu-iotests/group | ||
205 | +++ b/tests/qemu-iotests/group | ||
206 | @@ -XXX,XX +XXX,XX @@ | ||
207 | 244 rw auto quick | ||
208 | 245 rw auto | ||
209 | 246 rw auto quick | ||
210 | +247 rw auto quick | ||
211 | -- | 360 | -- |
212 | 2.20.1 | 361 | 2.35.3 |
213 | |||
214 | diff view generated by jsdifflib |
1 | From: Sergio Lopez <slp@redhat.com> | 1 | From: Paolo Bonzini <pbonzini@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | While child_job_drained_begin() calls to job_pause(), the job doesn't | 3 | common.rc has some complicated logic to find the common.config that |
4 | actually transition between states until it runs again and reaches a | 4 | dates back to xfstests and is completely unnecessary now. Just include |
5 | pause point. This means bdrv_drained_begin() may return with some jobs | 5 | the contents of the file. |
6 | using the node still having 'busy == true'. | ||
7 | 6 | ||
8 | As a consequence, block_job_detach_aio_context() may get into a | 7 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
9 | deadlock, waiting for the job to be actually paused, while the coroutine | 8 | Message-Id: <20220505094723.732116-1-pbonzini@redhat.com> |
10 | servicing the job is yielding and doesn't get the opportunity to get | ||
11 | scheduled again. This situation can be reproduced by issuing a | ||
12 | 'block-commit' immediately followed by a 'device_del'. | ||
13 | |||
14 | To ensure bdrv_drained_begin() only returns when the jobs have been | ||
15 | paused, we change mirror_drained_poll() to only confirm it's quiesced | ||
16 | when job->paused == true and there aren't any in-flight requests, except | ||
17 | if we reached that point by a drained section initiated by the | ||
18 | mirror/commit job itself. | ||
19 | |||
20 | The other block jobs shouldn't need any changes, as the default | ||
21 | drained_poll() behavior is to only confirm it's quiesced if the job is | ||
22 | not busy or completed. | ||
23 | |||
24 | Signed-off-by: Sergio Lopez <slp@redhat.com> | ||
25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
26 | --- | 10 | --- |
27 | block/mirror.c | 16 ++++++++++++++++ | 11 | tests/qemu-iotests/common.config | 41 -------------------------------- |
28 | 1 file changed, 16 insertions(+) | 12 | tests/qemu-iotests/common.rc | 31 ++++++++++++++---------- |
13 | 2 files changed, 19 insertions(+), 53 deletions(-) | ||
14 | delete mode 100644 tests/qemu-iotests/common.config | ||
29 | 15 | ||
30 | diff --git a/block/mirror.c b/block/mirror.c | 16 | diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config |
17 | deleted file mode 100644 | ||
18 | index XXXXXXX..XXXXXXX | ||
19 | --- a/tests/qemu-iotests/common.config | ||
20 | +++ /dev/null | ||
21 | @@ -XXX,XX +XXX,XX @@ | ||
22 | -#!/usr/bin/env bash | ||
23 | -# | ||
24 | -# Copyright (C) 2009 Red Hat, Inc. | ||
25 | -# Copyright (c) 2000-2003,2006 Silicon Graphics, Inc. All Rights Reserved. | ||
26 | -# | ||
27 | -# This program is free software; you can redistribute it and/or | ||
28 | -# modify it under the terms of the GNU General Public License as | ||
29 | -# published by the Free Software Foundation. | ||
30 | -# | ||
31 | -# This program is distributed in the hope that it would be useful, | ||
32 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
33 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
34 | -# GNU General Public License for more details. | ||
35 | -# | ||
36 | -# You should have received a copy of the GNU General Public License | ||
37 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
38 | -# | ||
39 | -# all tests should use a common language setting to prevent golden | ||
40 | -# output mismatches. | ||
41 | -export LANG=C | ||
42 | - | ||
43 | -PATH=".:$PATH" | ||
44 | - | ||
45 | -HOSTOS=$(uname -s) | ||
46 | -arch=$(uname -m) | ||
47 | -[[ "$arch" =~ "ppc64" ]] && qemu_arch=ppc64 || qemu_arch="$arch" | ||
48 | - | ||
49 | -# make sure we have a standard umask | ||
50 | -umask 022 | ||
51 | - | ||
52 | -_optstr_add() | ||
53 | -{ | ||
54 | - if [ -n "$1" ]; then | ||
55 | - echo "$1,$2" | ||
56 | - else | ||
57 | - echo "$2" | ||
58 | - fi | ||
59 | -} | ||
60 | - | ||
61 | -# make sure this script returns success | ||
62 | -true | ||
63 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | ||
31 | index XXXXXXX..XXXXXXX 100644 | 64 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/block/mirror.c | 65 | --- a/tests/qemu-iotests/common.rc |
33 | +++ b/block/mirror.c | 66 | +++ b/tests/qemu-iotests/common.rc |
34 | @@ -XXX,XX +XXX,XX @@ typedef struct MirrorBlockJob { | 67 | @@ -XXX,XX +XXX,XX @@ |
35 | bool initial_zeroing_ongoing; | 68 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
36 | int in_active_write_counter; | 69 | # |
37 | bool prepared; | 70 | |
38 | + bool in_drain; | 71 | +export LANG=C |
39 | } MirrorBlockJob; | 72 | + |
40 | 73 | +PATH=".:$PATH" | |
41 | typedef struct MirrorBDSOpaque { | 74 | + |
42 | @@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job) | 75 | +HOSTOS=$(uname -s) |
43 | 76 | +arch=$(uname -m) | |
44 | /* The mirror job has no requests in flight any more, but we need to | 77 | +[[ "$arch" =~ "ppc64" ]] && qemu_arch=ppc64 || qemu_arch="$arch" |
45 | * drain potential other users of the BDS before changing the graph. */ | 78 | + |
46 | + assert(s->in_drain); | 79 | +# make sure we have a standard umask |
47 | bdrv_drained_begin(target_bs); | 80 | +umask 022 |
48 | bdrv_replace_node(to_replace, target_bs, &local_err); | 81 | + |
49 | bdrv_drained_end(target_bs); | 82 | # bail out, setting up .notrun file |
50 | @@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job) | 83 | _notrun() |
51 | bs_opaque->job = NULL; | ||
52 | |||
53 | bdrv_drained_end(src); | ||
54 | + s->in_drain = false; | ||
55 | bdrv_unref(mirror_top_bs); | ||
56 | bdrv_unref(src); | ||
57 | |||
58 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp) | ||
59 | */ | ||
60 | trace_mirror_before_drain(s, cnt); | ||
61 | |||
62 | + s->in_drain = true; | ||
63 | bdrv_drained_begin(bs); | ||
64 | cnt = bdrv_get_dirty_count(s->dirty_bitmap); | ||
65 | if (cnt > 0 || mirror_flush(s) < 0) { | ||
66 | bdrv_drained_end(bs); | ||
67 | + s->in_drain = false; | ||
68 | continue; | ||
69 | } | ||
70 | |||
71 | @@ -XXX,XX +XXX,XX @@ immediate_exit: | ||
72 | bdrv_dirty_iter_free(s->dbi); | ||
73 | |||
74 | if (need_drain) { | ||
75 | + s->in_drain = true; | ||
76 | bdrv_drained_begin(bs); | ||
77 | } | ||
78 | |||
79 | @@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_pause(Job *job) | ||
80 | static bool mirror_drained_poll(BlockJob *job) | ||
81 | { | 84 | { |
82 | MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); | 85 | @@ -XXX,XX +XXX,XX @@ peek_file_raw() |
83 | + | 86 | dd if="$1" bs=1 skip="$2" count="$3" status=none |
84 | + /* If the job isn't paused nor cancelled, we can't be sure that it won't | ||
85 | + * issue more requests. We make an exception if we've reached this point | ||
86 | + * from one of our own drain sections, to avoid a deadlock waiting for | ||
87 | + * ourselves. | ||
88 | + */ | ||
89 | + if (!s->common.job.paused && !s->common.job.cancelled && !s->in_drain) { | ||
90 | + return true; | ||
91 | + } | ||
92 | + | ||
93 | return !!s->in_flight; | ||
94 | } | 87 | } |
95 | 88 | ||
89 | -config=common.config | ||
90 | -test -f $config || config=../common.config | ||
91 | -if ! test -f $config | ||
92 | -then | ||
93 | - echo "$0: failed to find common.config" | ||
94 | - exit 1 | ||
95 | -fi | ||
96 | -if ! . $config | ||
97 | - then | ||
98 | - echo "$0: failed to source common.config" | ||
99 | - exit 1 | ||
100 | -fi | ||
101 | +_optstr_add() | ||
102 | +{ | ||
103 | + if [ -n "$1" ]; then | ||
104 | + echo "$1,$2" | ||
105 | + else | ||
106 | + echo "$2" | ||
107 | + fi | ||
108 | +} | ||
109 | |||
110 | # Set the variables to the empty string to turn Valgrind off | ||
111 | # for specific processes, e.g. | ||
96 | -- | 112 | -- |
97 | 2.20.1 | 113 | 2.35.3 |
98 | |||
99 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | We were trying to check whether bdrv_open_blockdev_ref() returned | ||
2 | success, but accidentally checked the wrong variable. Spotted by | ||
3 | Coverity (CID 1399703). | ||
4 | 1 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
6 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
7 | Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> | ||
8 | --- | ||
9 | block/qcow2.c | 2 +- | ||
10 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
11 | |||
12 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/block/qcow2.c | ||
15 | +++ b/block/qcow2.c | ||
16 | @@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) | ||
17 | goto out; | ||
18 | } | ||
19 | data_bs = bdrv_open_blockdev_ref(qcow2_opts->data_file, errp); | ||
20 | - if (bs == NULL) { | ||
21 | + if (data_bs == NULL) { | ||
22 | ret = -EIO; | ||
23 | goto out; | ||
24 | } | ||
25 | -- | ||
26 | 2.20.1 | ||
27 | |||
28 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Coverity doesn't like that the return value of bdrv_check_update_perm() | ||
2 | stays unused only in this place (CID 1399710). | ||
3 | 1 | ||
4 | Even if checking local_err should be equivalent to checking ret < 0, | ||
5 | let's switch to using the return value to be more consistent (and in | ||
6 | case of a bug somewhere down the call chain, forgetting to assign errp | ||
7 | is more likely than returning 0 for an error case). | ||
8 | |||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
11 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
13 | --- | ||
14 | block.c | 7 +++---- | ||
15 | 1 file changed, 3 insertions(+), 4 deletions(-) | ||
16 | |||
17 | diff --git a/block.c b/block.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/block.c | ||
20 | +++ b/block.c | ||
21 | @@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
22 | QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) { | ||
23 | /* Check whether we are allowed to switch c from top to base */ | ||
24 | GSList *ignore_children = g_slist_prepend(NULL, c); | ||
25 | - bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm, | ||
26 | - ignore_children, &local_err); | ||
27 | + ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm, | ||
28 | + ignore_children, &local_err); | ||
29 | g_slist_free(ignore_children); | ||
30 | - if (local_err) { | ||
31 | - ret = -EPERM; | ||
32 | + if (ret < 0) { | ||
33 | error_report_err(local_err); | ||
34 | goto exit; | ||
35 | } | ||
36 | -- | ||
37 | 2.20.1 | ||
38 | |||
39 | diff view generated by jsdifflib |