1 | The following changes since commit 0280396a33c7210c4df5306afeab63411a41535a: | 1 | The following changes since commit ec11dc41eec5142b4776db1296972c6323ba5847: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-gdbstub-150221-1' into staging (2021-02-15 10:13:13 +0000) | 3 | Merge tag '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 b248e61652e20c3353af4b0ccb90f17d76f4db21: | 9 | for you to fetch changes up to f70625299ecc9ba577c87f3d1d75012c747c7d88: |
10 | 10 | ||
11 | monitor/qmp: Stop processing requests when shutdown is requested (2021-02-15 15:10:14 +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 | - qemu-storage-daemon: Enable object-add | 16 | - coroutine: Fix crashes due to too large pool batch size |
17 | - blockjob: Fix crash with IOthread when block commit after snapshot | 17 | - fdc: Prevent end-of-track overrun |
18 | - monitor: Shutdown fixes | 18 | - nbd: MULTI_CONN for shared writable exports |
19 | - xen-block: fix reporting of discard feature | 19 | - iotests test runner improvements |
20 | - qcow2: Remove half-initialised image file after failed image creation | ||
21 | - ahci: Fix DMA direction | ||
22 | - iotests fixes | ||
23 | 20 | ||
24 | ---------------------------------------------------------------- | 21 | ---------------------------------------------------------------- |
25 | Alexander Bulekov (1): | 22 | Daniel P. Berrangé (2): |
26 | hw/ide/ahci: map cmd_fis as DMA_DIRECTION_TO_DEVICE | 23 | tests/qemu-iotests: print intent to run a test in TAP mode |
24 | .gitlab-ci.d: export meson testlog.txt as an artifact | ||
27 | 25 | ||
28 | Kevin Wolf (3): | 26 | Eric Blake (2): |
29 | qemu-storage-daemon: Enable object-add | 27 | qemu-nbd: Pass max connections to blockdev layer |
30 | monitor: Fix assertion failure on shutdown | 28 | nbd/server: Allow MULTI_CONN for shared writable exports |
31 | monitor/qmp: Stop processing requests when shutdown is requested | ||
32 | 29 | ||
33 | Max Reitz (1): | 30 | Hanna Reitz (1): |
34 | iotests: Consistent $IMGOPTS boundary matching | 31 | iotests/testrunner: Flush after run_test() |
35 | 32 | ||
36 | Maxim Levitsky (3): | 33 | Kevin Wolf (2): |
37 | crypto: luks: Fix tiny memory leak | 34 | coroutine: Rename qemu_coroutine_inc/dec_pool_size() |
38 | block: add bdrv_co_delete_file_noerr | 35 | coroutine: Revert to constant batch size |
39 | block: qcow2: remove the created file on initialization error | ||
40 | 36 | ||
41 | Michael Qiu (1): | 37 | Paolo Bonzini (1): |
42 | blockjob: Fix crash with IOthread when block commit after snapshot | 38 | qemu-iotests: inline common.config into common.rc |
43 | 39 | ||
44 | Roger Pau Monné (1): | 40 | Philippe Mathieu-Daudé (2): |
45 | xen-block: fix reporting of discard feature | 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 | ||
46 | 43 | ||
47 | Thomas Huth (1): | 44 | qapi/block-export.json | 8 +- |
48 | tests/qemu-iotests: Remove test 259 from the "auto" group | 45 | docs/interop/nbd.txt | 1 + |
49 | 46 | docs/tools/qemu-nbd.rst | 3 +- | |
50 | include/block/block.h | 1 + | 47 | include/block/nbd.h | 5 +- |
51 | block.c | 22 ++++++++++++++++++++++ | 48 | include/qemu/coroutine.h | 6 +- |
52 | block/crypto.c | 13 ++----------- | 49 | blockdev-nbd.c | 13 +- |
53 | block/qcow2.c | 8 +++++--- | 50 | hw/block/fdc.c | 8 ++ |
54 | blockjob.c | 8 ++++++-- | 51 | hw/block/virtio-blk.c | 6 +- |
55 | hw/block/xen-block.c | 1 + | 52 | nbd/server.c | 10 +- |
56 | hw/ide/ahci.c | 12 ++++++------ | 53 | qemu-nbd.c | 2 +- |
57 | monitor/monitor.c | 25 +++++++++++++++---------- | 54 | tests/qtest/fdc-test.c | 21 ++++ |
58 | monitor/qmp.c | 5 +++++ | 55 | util/qemu-coroutine.c | 26 ++-- |
59 | storage-daemon/qemu-storage-daemon.c | 2 ++ | 56 | tests/qemu-iotests/testrunner.py | 4 + |
60 | tests/qemu-iotests/259 | 2 +- | 57 | .gitlab-ci.d/buildtest-template.yml | 12 +- |
61 | tests/qemu-iotests/common.rc | 4 +++- | 58 | MAINTAINERS | 1 + |
62 | 12 files changed, 69 insertions(+), 34 deletions(-) | 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 | ||
63 | 68 | ||
64 | 69 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | As we don't have a fully QAPIfied version of object-add yet and it still | ||
2 | has 'gen': false in the schema, it needs to be registered explicitly in | ||
3 | init_qmp_commands() to be available for users. | ||
4 | 1 | ||
5 | Fixes: 2af282ec51a27116d0402cab237b8970800f870c | ||
6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
7 | Message-Id: <20210204072137.19663-1-kwolf@redhat.com> | ||
8 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | storage-daemon/qemu-storage-daemon.c | 2 ++ | ||
12 | 1 file changed, 2 insertions(+) | ||
13 | |||
14 | diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/storage-daemon/qemu-storage-daemon.c | ||
17 | +++ b/storage-daemon/qemu-storage-daemon.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static void init_qmp_commands(void) | ||
19 | qmp_init_marshal(&qmp_commands); | ||
20 | qmp_register_command(&qmp_commands, "query-qmp-schema", | ||
21 | qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); | ||
22 | + qmp_register_command(&qmp_commands, "object-add", qmp_object_add, | ||
23 | + QCO_NO_OPTIONS); | ||
24 | |||
25 | QTAILQ_INIT(&qmp_cap_negotiation_commands); | ||
26 | qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", | ||
27 | -- | ||
28 | 2.29.2 | ||
29 | |||
30 | diff view generated by jsdifflib |
1 | Commit 357bda95 already tried to fix the order in monitor_cleanup() by | 1 | It's true that these functions currently affect the batch size in which |
---|---|---|---|
2 | moving shutdown of the dispatcher coroutine further to the start. | 2 | coroutines are reused (i.e. moved from the global release pool to the |
3 | However, it didn't go far enough: | 3 | allocation pool of a specific thread), but this is a bug and will be |
4 | fixed in a separate patch. | ||
4 | 5 | ||
5 | iothread_stop() makes sure that all pending work (bottom halves) in the | 6 | In fact, the comment in the header file already just promises that it |
6 | AioContext of the monitor iothread is completed. iothread_destroy() | 7 | influences the pool size, so reflect this in the name of the functions. |
7 | depends on this and fails an assertion if there is still a pending BH. | 8 | As a nice side effect, the shorter function name makes some line |
9 | wrapping unnecessary. | ||
8 | 10 | ||
9 | While the dispatcher coroutine is running, it will try to resume the | 11 | Cc: qemu-stable@nongnu.org |
10 | monitor after taking a request out of the queue, which involves a BH. | ||
11 | The dispatcher is run until it terminates in the AIO_WAIT_WHILE() loop. | ||
12 | However, adding new BHs between iothread_stop() and iothread_destroy() | ||
13 | is forbidden. | ||
14 | |||
15 | Fix this by stopping the dispatcher first before shutting down the other | ||
16 | parts of the monitor. This means we can now receive requests that aren't | ||
17 | handled any more when QEMU is shutting down, but this is unlikely to be | ||
18 | a problem for QMP clients. | ||
19 | |||
20 | Fixes: 357bda9590784ff75803d52de43150d4107ed98e | ||
21 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
22 | Message-Id: <20210212172028.288825-2-kwolf@redhat.com> | 13 | Message-Id: <20220510151020.105528-2-kwolf@redhat.com> |
23 | Tested-by: Markus Armbruster <armbru@redhat.com> | ||
24 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
26 | --- | 15 | --- |
27 | monitor/monitor.c | 25 +++++++++++++++---------- | 16 | include/qemu/coroutine.h | 6 +++--- |
28 | 1 file changed, 15 insertions(+), 10 deletions(-) | 17 | hw/block/virtio-blk.c | 6 ++---- |
18 | util/qemu-coroutine.c | 4 ++-- | ||
19 | 3 files changed, 7 insertions(+), 9 deletions(-) | ||
29 | 20 | ||
30 | diff --git a/monitor/monitor.c b/monitor/monitor.c | 21 | diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h |
31 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/monitor/monitor.c | 23 | --- a/include/qemu/coroutine.h |
33 | +++ b/monitor/monitor.c | 24 | +++ b/include/qemu/coroutine.h |
34 | @@ -XXX,XX +XXX,XX @@ void monitor_data_destroy(Monitor *mon) | 25 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn yield_until_fd_readable(int fd); |
35 | 26 | /** | |
36 | void monitor_cleanup(void) | 27 | * Increase coroutine pool size |
28 | */ | ||
29 | -void qemu_coroutine_increase_pool_batch_size(unsigned int additional_pool_size); | ||
30 | +void qemu_coroutine_inc_pool_size(unsigned int additional_pool_size); | ||
31 | |||
32 | /** | ||
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) | ||
37 | { | 75 | { |
38 | - /* | 76 | qatomic_add(&pool_batch_size, additional_pool_size); |
39 | - * We need to explicitly stop the I/O thread (but not destroy it), | 77 | } |
40 | - * clean up the monitor resources, then destroy the I/O thread since | 78 | |
41 | - * we need to unregister from chardev below in | 79 | -void qemu_coroutine_decrease_pool_batch_size(unsigned int removing_pool_size) |
42 | - * monitor_data_destroy(), and chardev is not thread-safe yet | 80 | +void qemu_coroutine_dec_pool_size(unsigned int removing_pool_size) |
43 | - */ | 81 | { |
44 | - if (mon_iothread) { | 82 | qatomic_sub(&pool_batch_size, removing_pool_size); |
45 | - iothread_stop(mon_iothread); | 83 | } |
46 | - } | ||
47 | - | ||
48 | /* | ||
49 | * The dispatcher needs to stop before destroying the monitor and | ||
50 | * the I/O thread. | ||
51 | @@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void) | ||
52 | * eventually terminates. qemu_aio_context is automatically | ||
53 | * polled by calling AIO_WAIT_WHILE on it, but we must poll | ||
54 | * iohandler_ctx manually. | ||
55 | + * | ||
56 | + * Letting the iothread continue while shutting down the dispatcher | ||
57 | + * means that new requests may still be coming in. This is okay, | ||
58 | + * we'll just leave them in the queue without sending a response | ||
59 | + * and monitor_data_destroy() will free them. | ||
60 | */ | ||
61 | qmp_dispatcher_co_shutdown = true; | ||
62 | if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { | ||
63 | @@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void) | ||
64 | (aio_poll(iohandler_get_aio_context(), false), | ||
65 | qatomic_mb_read(&qmp_dispatcher_co_busy))); | ||
66 | |||
67 | + /* | ||
68 | + * We need to explicitly stop the I/O thread (but not destroy it), | ||
69 | + * clean up the monitor resources, then destroy the I/O thread since | ||
70 | + * we need to unregister from chardev below in | ||
71 | + * monitor_data_destroy(), and chardev is not thread-safe yet | ||
72 | + */ | ||
73 | + if (mon_iothread) { | ||
74 | + iothread_stop(mon_iothread); | ||
75 | + } | ||
76 | + | ||
77 | /* Flush output buffers and destroy monitors */ | ||
78 | qemu_mutex_lock(&monitor_lock); | ||
79 | monitor_destroyed = true; | ||
80 | -- | 84 | -- |
81 | 2.29.2 | 85 | 2.35.3 |
82 | |||
83 | diff view generated by jsdifflib |
1 | From: Maxim Levitsky <mlevitsk@redhat.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 | If the qcow initialization fails, we should remove the file if it was | 7 | There are two important numbers here: Slightly simplified, when a |
4 | already created, to avoid leaving stale files around. | 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 | We already do this for luks raw images. | 14 | The problem after commit 4c41c69e is that it not only increases the |
15 | maximum pool size (which is the intended effect), but also the batch | ||
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. | ||
7 | 20 | ||
8 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | 21 | This is not only a waste of memory and allocations, but it actually |
9 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 22 | makes the QEMU process likely to hit the vm.max_map_count limit on Linux |
10 | Message-Id: <20201217170904.946013-4-mlevitsk@redhat.com> | 23 | because each coroutine requires two mappings (its stack and the guard |
11 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 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. | ||
26 | |||
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> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 45 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
13 | --- | 46 | --- |
14 | block/qcow2.c | 8 +++++--- | 47 | util/qemu-coroutine.c | 22 ++++++++++++++-------- |
15 | 1 file changed, 5 insertions(+), 3 deletions(-) | 48 | 1 file changed, 14 insertions(+), 8 deletions(-) |
16 | 49 | ||
17 | diff --git a/block/qcow2.c b/block/qcow2.c | 50 | diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c |
18 | index XXXXXXX..XXXXXXX 100644 | 51 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/block/qcow2.c | 52 | --- a/util/qemu-coroutine.c |
20 | +++ b/block/qcow2.c | 53 | +++ b/util/qemu-coroutine.c |
21 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, | 54 | @@ -XXX,XX +XXX,XX @@ |
22 | 55 | #include "qemu/coroutine-tls.h" | |
23 | /* Create the qcow2 image (format layer) */ | 56 | #include "block/aio.h" |
24 | ret = qcow2_co_create(create_options, errp); | 57 | |
25 | +finish: | 58 | -/** Initial batch size is 64, and is increased on demand */ |
26 | if (ret < 0) { | 59 | +/** |
27 | - goto finish; | 60 | + * The minimal batch size is always 64, coroutines from the release_pool are |
28 | + bdrv_co_delete_file_noerr(bs); | 61 | + * reused as soon as there are 64 coroutines in it. The maximum pool size starts |
29 | + bdrv_co_delete_file_noerr(data_bs); | 62 | + * with 64 and is increased on demand so that coroutines are not deleted even if |
30 | + } else { | 63 | + * they are not immediately reused. |
31 | + ret = 0; | 64 | + */ |
32 | } | 65 | enum { |
33 | 66 | - POOL_INITIAL_BATCH_SIZE = 64, | |
34 | - ret = 0; | 67 | + POOL_MIN_BATCH_SIZE = 64, |
35 | -finish: | 68 | + POOL_INITIAL_MAX_SIZE = 64, |
36 | qobject_unref(qdict); | 69 | }; |
37 | bdrv_unref(bs); | 70 | |
38 | bdrv_unref(data_bs); | 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 | } | ||
39 | -- | 115 | -- |
40 | 2.29.2 | 116 | 2.35.3 |
41 | |||
42 | diff view generated by jsdifflib |
1 | From: Roger Pau Monne <roger.pau@citrix.com> | 1 | From: Hanna Reitz <hreitz@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Linux blkfront expects both "discard-granularity" and | 3 | When stdout is not a terminal, the buffer may not be flushed at each end |
4 | "discard-alignment" present on xenbus in order to properly enable the | 4 | of line, so we should flush after each test is done. This is especially |
5 | feature, not exposing "discard-alignment" left some Linux blkfront | 5 | apparent when run by check-block, in two ways: |
6 | versions with a broken discard setup. This has also been addressed in | ||
7 | Linux with: | ||
8 | 6 | ||
9 | https://lore.kernel.org/lkml/20210118151528.81668-1-roger.pau@citrix.com/T/#u | 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. | ||
10 | 11 | ||
11 | Fix QEMU to report a "discard-alignment" of 0, in order for it to work | 12 | Second, sometimes make check-block failed altogether, with an error |
12 | with older Linux frontends. | 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. | ||
13 | 18 | ||
14 | Reported-by: Arthur Borsboom <arthurborsboom@gmail.com> | 19 | Signed-off-by: Hanna Reitz <hreitz@redhat.com> |
15 | Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> | 20 | Message-Id: <20220506134215.10086-1-hreitz@redhat.com> |
16 | Message-Id: <20210118153330.82324-1-roger.pau@citrix.com> | 21 | Reviewed-by: Eric Blake <eblake@redhat.com> |
17 | Reviewed-by: Paul Durrant <paul@xen.org> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 22 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
19 | --- | 23 | --- |
20 | hw/block/xen-block.c | 1 + | 24 | tests/qemu-iotests/testrunner.py | 1 + |
21 | 1 file changed, 1 insertion(+) | 25 | 1 file changed, 1 insertion(+) |
22 | 26 | ||
23 | diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c | 27 | diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py |
24 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/hw/block/xen-block.c | 29 | --- a/tests/qemu-iotests/testrunner.py |
26 | +++ b/hw/block/xen-block.c | 30 | +++ b/tests/qemu-iotests/testrunner.py |
27 | @@ -XXX,XX +XXX,XX @@ static void xen_block_realize(XenDevice *xendev, Error **errp) | 31 | @@ -XXX,XX +XXX,XX @@ def run_test(self, test: str, |
28 | xen_device_backend_printf(xendev, "feature-discard", "%u", 1); | 32 | else: |
29 | xen_device_backend_printf(xendev, "discard-granularity", "%u", | 33 | print(res.casenotrun) |
30 | conf->discard_granularity); | 34 | |
31 | + xen_device_backend_printf(xendev, "discard-alignment", "%u", 0); | 35 | + sys.stdout.flush() |
32 | } | 36 | return res |
33 | 37 | ||
34 | xen_device_backend_printf(xendev, "feature-flush-cache", "%u", 1); | 38 | def run_tests(self, tests: List[str], jobs: int = 1) -> bool: |
35 | -- | 39 | -- |
36 | 2.29.2 | 40 | 2.35.3 |
37 | |||
38 | diff view generated by jsdifflib |
1 | From: Maxim Levitsky <mlevitsk@redhat.com> | 1 | From: Daniel P. Berrangé <berrange@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | When the underlying block device doesn't support the | 3 | When running I/O tests using TAP output mode, we get a single TAP test |
4 | bdrv_co_delete_file interface, an 'Error' object was leaked. | 4 | with a sub-test reported for each I/O test that is run. The output looks |
5 | something like this: | ||
5 | 6 | ||
6 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | 7 | 1..123 |
7 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 8 | ok qcow2 011 |
8 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 9 | ok qcow2 012 |
9 | Message-Id: <20201217170904.946013-2-mlevitsk@redhat.com> | 10 | ok qcow2 013 |
11 | ok qcow2 217 | ||
12 | ... | ||
13 | |||
14 | If everything runs or fails normally this is fine, but periodically we | ||
15 | have been seeing the test harness abort early before all 123 tests have | ||
16 | been run, just leaving a fairly useless message like | ||
17 | |||
18 | TAP parsing error: Too few tests run (expected 123, got 107) | ||
19 | |||
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> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 39 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
11 | --- | 40 | --- |
12 | block/crypto.c | 2 ++ | 41 | tests/qemu-iotests/testrunner.py | 3 +++ |
13 | 1 file changed, 2 insertions(+) | 42 | 1 file changed, 3 insertions(+) |
14 | 43 | ||
15 | diff --git a/block/crypto.c b/block/crypto.c | 44 | diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py |
16 | index XXXXXXX..XXXXXXX 100644 | 45 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/block/crypto.c | 46 | --- a/tests/qemu-iotests/testrunner.py |
18 | +++ b/block/crypto.c | 47 | +++ b/tests/qemu-iotests/testrunner.py |
19 | @@ -XXX,XX +XXX,XX @@ fail: | 48 | @@ -XXX,XX +XXX,XX @@ def run_test(self, test: str, |
20 | */ | 49 | starttime=start, |
21 | if ((r_del < 0) && (r_del != -ENOTSUP)) { | 50 | lasttime=last_el, |
22 | error_report_err(local_delete_err); | 51 | end = '\n' if mp else '\r') |
23 | + } else { | 52 | + else: |
24 | + error_free(local_delete_err); | 53 | + testname = os.path.basename(test) |
25 | } | 54 | + print(f'# running {self.env.imgfmt} {testname}') |
26 | } | 55 | |
56 | res = self.do_run_test(test, mp) | ||
27 | 57 | ||
28 | -- | 58 | -- |
29 | 2.29.2 | 59 | 2.35.3 |
30 | 60 | ||
31 | 61 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | From: Daniel P. Berrangé <berrange@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Tests in the "auto" group should support qcow2 so that they can | 3 | When running 'make check' we only get a summary of progress on the |
4 | be run during "make check-block". Test 259 only supports "raw", so | 4 | console. Fortunately meson/ninja have saved the raw test output to a |
5 | it currently always gets skipped when running "make check-block". | 5 | logfile. Exposing this log will make it easier to debug failures that |
6 | Let's skip this unnecessary step and remove it from the auto group. | 6 | happen in CI. |
7 | 7 | ||
8 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 8 | Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> |
9 | Message-Id: <20210215103835.1129145-1-thuth@redhat.com> | 9 | Message-Id: <20220509124134.867431-3-berrange@redhat.com> |
10 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
11 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
11 | --- | 13 | --- |
12 | tests/qemu-iotests/259 | 2 +- | 14 | .gitlab-ci.d/buildtest-template.yml | 12 ++++++++++-- |
13 | 1 file changed, 1 insertion(+), 1 deletion(-) | 15 | 1 file changed, 10 insertions(+), 2 deletions(-) |
14 | 16 | ||
15 | diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259 | 17 | diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml |
16 | index XXXXXXX..XXXXXXX 100755 | 18 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/tests/qemu-iotests/259 | 19 | --- a/.gitlab-ci.d/buildtest-template.yml |
18 | +++ b/tests/qemu-iotests/259 | 20 | +++ b/.gitlab-ci.d/buildtest-template.yml |
19 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ |
20 | #!/usr/bin/env bash | 22 | make -j"$JOBS" $MAKE_CHECK_ARGS ; |
21 | -# group: rw auto quick | 23 | fi |
22 | +# group: rw quick | 24 | |
23 | # | 25 | -.native_test_job_template: |
24 | # Test generic image creation fallback (by using NBD) | 26 | +.common_test_job_template: |
25 | # | 27 | stage: test |
28 | image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest | ||
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 | ||
41 | + | ||
42 | .avocado_test_job_template: | ||
43 | - extends: .native_test_job_template | ||
44 | + extends: .common_test_job_template | ||
45 | cache: | ||
46 | key: "${CI_JOB_NAME}-cache" | ||
47 | paths: | ||
26 | -- | 48 | -- |
27 | 2.29.2 | 49 | 2.35.3 |
28 | 50 | ||
29 | 51 | diff view generated by jsdifflib |
1 | Before this patch, monitor_qmp_dispatcher_co() used to check whether | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | shutdown is requested only when it would have to wait for new requests. | ||
3 | If there were still some queued requests, it would try to execute all of | ||
4 | them before shutting down. | ||
5 | 2 | ||
6 | This can be surprising when the queued QMP commands take long or hang | 3 | Per the 82078 datasheet, if the end-of-track (EOT byte in |
7 | because Ctrl-C may not actually exit QEMU as soon as possible. | 4 | the FIFO) is more than the number of sectors per side, the |
5 | command is terminated unsuccessfully: | ||
8 | 6 | ||
9 | Change monitor_qmp_dispatcher_co() so that it additionally checks | 7 | * 5.2.5 DATA TRANSFER TERMINATION |
10 | whether shutdown is request before it gets a new request from the queue. | ||
11 | 8 | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 9 | The 82078 supports terminal count explicitly through |
13 | Message-Id: <20210212172028.288825-3-kwolf@redhat.com> | 10 | the TC pin and implicitly through the underrun/over- |
14 | Tested-by: Markus Armbruster <armbru@redhat.com> | 11 | run and end-of-track (EOT) functions. For full sector |
15 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | 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> | ||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 54 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
17 | --- | 55 | --- |
18 | monitor/qmp.c | 5 +++++ | 56 | hw/block/fdc.c | 8 ++++++++ |
19 | 1 file changed, 5 insertions(+) | 57 | 1 file changed, 8 insertions(+) |
20 | 58 | ||
21 | diff --git a/monitor/qmp.c b/monitor/qmp.c | 59 | diff --git a/hw/block/fdc.c b/hw/block/fdc.c |
22 | index XXXXXXX..XXXXXXX 100644 | 60 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/monitor/qmp.c | 61 | --- a/hw/block/fdc.c |
24 | +++ b/monitor/qmp.c | 62 | +++ b/hw/block/fdc.c |
25 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) | 63 | @@ -XXX,XX +XXX,XX @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction) |
26 | */ | 64 | int tmp; |
27 | qatomic_mb_set(&qmp_dispatcher_co_busy, false); | 65 | fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]); |
28 | 66 | tmp = (fdctrl->fifo[6] - ks + 1); | |
29 | + /* On shutdown, don't take any more requests from the queue */ | 67 | + if (tmp < 0) { |
30 | + if (qmp_dispatcher_co_shutdown) { | 68 | + FLOPPY_DPRINTF("invalid EOT: %d\n", tmp); |
69 | + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); | ||
70 | + fdctrl->fifo[3] = kt; | ||
71 | + fdctrl->fifo[4] = kh; | ||
72 | + fdctrl->fifo[5] = ks; | ||
31 | + return; | 73 | + return; |
32 | + } | 74 | + } |
33 | + | 75 | if (fdctrl->fifo[0] & 0x80) |
34 | while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) { | 76 | tmp += fdctrl->fifo[6]; |
35 | /* | 77 | fdctrl->data_len *= tmp; |
36 | * No more requests to process. Wait to be reentered from | ||
37 | -- | 78 | -- |
38 | 2.29.2 | 79 | 2.35.3 |
39 | 80 | ||
40 | 81 | diff view generated by jsdifflib |
1 | From: Maxim Levitsky <mlevitsk@redhat.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | This function wraps bdrv_co_delete_file for the common case of removing a file, | 3 | Add the reproducer from https://gitlab.com/qemu-project/qemu/-/issues/339 |
4 | which was just created by format driver, on an error condition. | ||
5 | 4 | ||
6 | It hides the -ENOTSUPP error, and reports all other errors otherwise. | 5 | Without the previous commit, when running 'make check-qtest-i386' |
6 | with QEMU configured with '--enable-sanitizers' we get: | ||
7 | 7 | ||
8 | Use it in luks driver | 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 | ||
9 | 23 | ||
10 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | 24 | 0x619000062a00 is located 0 bytes to the right of 512-byte region [0x619000062800,0x619000062a00) |
11 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 25 | allocated by thread T0 here: |
12 | Message-Id: <20201217170904.946013-3-mlevitsk@redhat.com> | 26 | #0 0x5626d03c66ec in posix_memalign (qemu-system-i386+0x1e676ec) |
13 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 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> | ||
14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 57 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
15 | --- | 58 | --- |
16 | include/block/block.h | 1 + | 59 | tests/qtest/fdc-test.c | 21 +++++++++++++++++++++ |
17 | block.c | 22 ++++++++++++++++++++++ | 60 | 1 file changed, 21 insertions(+) |
18 | block/crypto.c | 15 ++------------- | ||
19 | 3 files changed, 25 insertions(+), 13 deletions(-) | ||
20 | 61 | ||
21 | diff --git a/include/block/block.h b/include/block/block.h | 62 | diff --git a/tests/qtest/fdc-test.c b/tests/qtest/fdc-test.c |
22 | index XXXXXXX..XXXXXXX 100644 | 63 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/include/block/block.h | 64 | --- a/tests/qtest/fdc-test.c |
24 | +++ b/include/block/block.h | 65 | +++ b/tests/qtest/fdc-test.c |
25 | @@ -XXX,XX +XXX,XX @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, | 66 | @@ -XXX,XX +XXX,XX @@ static void test_cve_2021_20196(void) |
26 | Error **errp); | 67 | qtest_quit(s); |
27 | void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); | ||
28 | int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); | ||
29 | +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs); | ||
30 | |||
31 | |||
32 | typedef struct BdrvCheckResult { | ||
33 | diff --git a/block.c b/block.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/block.c | ||
36 | +++ b/block.c | ||
37 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) | ||
38 | return ret; | ||
39 | } | 68 | } |
40 | 69 | ||
41 | +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs) | 70 | +static void test_cve_2021_3507(void) |
42 | +{ | 71 | +{ |
43 | + Error *local_err = NULL; | 72 | + QTestState *s; |
44 | + int ret; | ||
45 | + | 73 | + |
46 | + if (!bs) { | 74 | + s = qtest_initf("-nographic -m 32M -nodefaults " |
47 | + return; | 75 | + "-drive file=%s,format=raw,if=floppy,snapshot=on", |
48 | + } | 76 | + test_image); |
49 | + | 77 | + qtest_outl(s, 0x9, 0x0a0206); |
50 | + ret = bdrv_co_delete_file(bs, &local_err); | 78 | + qtest_outw(s, 0x3f4, 0x1600); |
51 | + /* | 79 | + qtest_outw(s, 0x3f4, 0x0000); |
52 | + * ENOTSUP will happen if the block driver doesn't support | 80 | + qtest_outw(s, 0x3f4, 0x0000); |
53 | + * the 'bdrv_co_delete_file' interface. This is a predictable | 81 | + qtest_outw(s, 0x3f4, 0x0000); |
54 | + * scenario and shouldn't be reported back to the user. | 82 | + qtest_outw(s, 0x3f4, 0x0200); |
55 | + */ | 83 | + qtest_outw(s, 0x3f4, 0x0200); |
56 | + if (ret == -ENOTSUP) { | 84 | + qtest_outw(s, 0x3f4, 0x0000); |
57 | + error_free(local_err); | 85 | + qtest_outw(s, 0x3f4, 0x0000); |
58 | + } else if (ret < 0) { | 86 | + qtest_outw(s, 0x3f4, 0x0000); |
59 | + error_report_err(local_err); | 87 | + qtest_quit(s); |
60 | + } | ||
61 | +} | 88 | +} |
62 | + | 89 | + |
63 | /** | 90 | int main(int argc, char **argv) |
64 | * Try to get @bs's logical and physical block size. | 91 | { |
65 | * On success, store them in @bsz struct and return 0. | 92 | int fd; |
66 | diff --git a/block/crypto.c b/block/crypto.c | 93 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) |
67 | index XXXXXXX..XXXXXXX 100644 | 94 | qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19); |
68 | --- a/block/crypto.c | 95 | qtest_add_func("/fdc/fuzz-registers", fuzz_registers); |
69 | +++ b/block/crypto.c | 96 | qtest_add_func("/fdc/fuzz/cve_2021_20196", test_cve_2021_20196); |
70 | @@ -XXX,XX +XXX,XX @@ fail: | 97 | + qtest_add_func("/fdc/fuzz/cve_2021_3507", test_cve_2021_3507); |
71 | * If an error occurred, delete 'filename'. Even if the file existed | 98 | |
72 | * beforehand, it has been truncated and corrupted in the process. | 99 | ret = g_test_run(); |
73 | */ | 100 | |
74 | - if (ret && bs) { | ||
75 | - Error *local_delete_err = NULL; | ||
76 | - int r_del = bdrv_co_delete_file(bs, &local_delete_err); | ||
77 | - /* | ||
78 | - * ENOTSUP will happen if the block driver doesn't support | ||
79 | - * the 'bdrv_co_delete_file' interface. This is a predictable | ||
80 | - * scenario and shouldn't be reported back to the user. | ||
81 | - */ | ||
82 | - if ((r_del < 0) && (r_del != -ENOTSUP)) { | ||
83 | - error_report_err(local_delete_err); | ||
84 | - } else { | ||
85 | - error_free(local_delete_err); | ||
86 | - } | ||
87 | + if (ret) { | ||
88 | + bdrv_co_delete_file_noerr(bs); | ||
89 | } | ||
90 | |||
91 | bdrv_unref(bs); | ||
92 | -- | 101 | -- |
93 | 2.29.2 | 102 | 2.35.3 |
94 | 103 | ||
95 | 104 | diff view generated by jsdifflib |
1 | From: Alexander Bulekov <alxndr@bu.edu> | 1 | From: Eric Blake <eblake@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | cmd_fis is mapped as DMA_DIRECTION_FROM_DEVICE, however, it is read | 3 | The next patch wants to adjust whether the NBD server code advertises |
4 | from, and not written to anywhere. Fix the DMA_DIRECTION and mark | 4 | MULTI_CONN based on whether it is known if the server limits to |
5 | cmd_fis as read-only in the code. | 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. | ||
6 | 11 | ||
7 | Signed-off-by: Alexander Bulekov <alxndr@bu.edu> | 12 | Signed-off-by: Eric Blake <eblake@redhat.com> |
8 | Message-Id: <20210119164051.89268-1-alxndr@bu.edu> | 13 | Message-Id: <20220512004924.417153-2-eblake@redhat.com> |
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
10 | --- | 15 | --- |
11 | hw/ide/ahci.c | 12 ++++++------ | 16 | include/block/nbd.h | 2 +- |
12 | 1 file changed, 6 insertions(+), 6 deletions(-) | 17 | blockdev-nbd.c | 8 ++++---- |
18 | qemu-nbd.c | 2 +- | ||
19 | 3 files changed, 6 insertions(+), 6 deletions(-) | ||
13 | 20 | ||
14 | diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c | 21 | diff --git a/include/block/nbd.h b/include/block/nbd.h |
15 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/hw/ide/ahci.c | 23 | --- a/include/block/nbd.h |
17 | +++ b/hw/ide/ahci.c | 24 | +++ b/include/block/nbd.h |
18 | @@ -XXX,XX +XXX,XX @@ static void ahci_reset_port(AHCIState *s, int port) | 25 | @@ -XXX,XX +XXX,XX @@ void nbd_client_new(QIOChannelSocket *sioc, |
26 | void nbd_client_get(NBDClient *client); | ||
27 | void nbd_client_put(NBDClient *client); | ||
28 | |||
29 | -void nbd_server_is_qemu_nbd(bool value); | ||
30 | +void nbd_server_is_qemu_nbd(int max_connections); | ||
31 | bool nbd_server_is_running(void); | ||
32 | void nbd_server_start(SocketAddress *addr, const char *tls_creds, | ||
33 | const char *tls_authz, uint32_t max_connections, | ||
34 | diff --git a/blockdev-nbd.c b/blockdev-nbd.c | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/blockdev-nbd.c | ||
37 | +++ b/blockdev-nbd.c | ||
38 | @@ -XXX,XX +XXX,XX @@ typedef struct NBDServerData { | ||
39 | } NBDServerData; | ||
40 | |||
41 | static NBDServerData *nbd_server; | ||
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; | ||
19 | } | 52 | } |
20 | 53 | ||
21 | /* Buffer pretty output based on a raw FIS structure. */ | 54 | bool nbd_server_is_running(void) |
22 | -static char *ahci_pretty_buffer_fis(uint8_t *fis, int cmd_len) | ||
23 | +static char *ahci_pretty_buffer_fis(const uint8_t *fis, int cmd_len) | ||
24 | { | 55 | { |
25 | int i; | 56 | - return nbd_server || is_qemu_nbd; |
26 | GString *s = g_string_new("FIS:"); | 57 | + return nbd_server || qemu_nbd_connections >= 0; |
27 | @@ -XXX,XX +XXX,XX @@ static void execute_ncq_command(NCQTransferState *ncq_tfs) | ||
28 | } | 58 | } |
29 | 59 | ||
30 | 60 | static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) | |
31 | -static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, | 61 | diff --git a/qemu-nbd.c b/qemu-nbd.c |
32 | +static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, | 62 | index XXXXXXX..XXXXXXX 100644 |
33 | uint8_t slot) | 63 | --- a/qemu-nbd.c |
34 | { | 64 | +++ b/qemu-nbd.c |
35 | AHCIDevice *ad = &s->dev[port]; | 65 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) |
36 | - NCQFrame *ncq_fis = (NCQFrame*)cmd_fis; | 66 | |
37 | + const NCQFrame *ncq_fis = (NCQFrame *)cmd_fis; | 67 | bs->detect_zeroes = detect_zeroes; |
38 | uint8_t tag = ncq_fis->tag >> 3; | 68 | |
39 | NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag]; | 69 | - nbd_server_is_qemu_nbd(true); |
40 | size_t size; | 70 | + nbd_server_is_qemu_nbd(shared); |
41 | @@ -XXX,XX +XXX,XX @@ static AHCICmdHdr *get_cmd_header(AHCIState *s, uint8_t port, uint8_t slot) | 71 | |
42 | } | 72 | export_opts = g_new(BlockExportOptions, 1); |
43 | 73 | *export_opts = (BlockExportOptions) { | |
44 | static void handle_reg_h2d_fis(AHCIState *s, int port, | ||
45 | - uint8_t slot, uint8_t *cmd_fis) | ||
46 | + uint8_t slot, const uint8_t *cmd_fis) | ||
47 | { | ||
48 | IDEState *ide_state = &s->dev[port].port.ifs[0]; | ||
49 | AHCICmdHdr *cmd = get_cmd_header(s, port, slot); | ||
50 | @@ -XXX,XX +XXX,XX @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) | ||
51 | tbl_addr = le64_to_cpu(cmd->tbl_addr); | ||
52 | cmd_len = 0x80; | ||
53 | cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len, | ||
54 | - DMA_DIRECTION_FROM_DEVICE); | ||
55 | + DMA_DIRECTION_TO_DEVICE); | ||
56 | if (!cmd_fis) { | ||
57 | trace_handle_cmd_badfis(s, port); | ||
58 | return -1; | ||
59 | @@ -XXX,XX +XXX,XX @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) | ||
60 | } | ||
61 | |||
62 | out: | ||
63 | - dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE, | ||
64 | + dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_TO_DEVICE, | ||
65 | cmd_len); | ||
66 | |||
67 | if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { | ||
68 | -- | 74 | -- |
69 | 2.29.2 | 75 | 2.35.3 |
70 | |||
71 | diff view generated by jsdifflib |
1 | From: Michael Qiu <qiudayu@huayun.com> | 1 | From: Eric Blake <eblake@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Currently, if guest has workloads, IO thread will acquire aio_context | 3 | According to the NBD spec, a server that advertises |
4 | lock before do io_submit, it leads to segmentfault when do block commit | 4 | NBD_FLAG_CAN_MULTI_CONN promises that multiple client connections will |
5 | after snapshot. Just like below: | 5 | not see any cache inconsistencies: when properly separated by a single |
6 | 6 | flush, actions performed by one client will be visible to another | |
7 | Program received signal SIGSEGV, Segmentation fault. | 7 | client, regardless of which client did the flush. |
8 | 8 | ||
9 | [Switching to Thread 0x7f7c7d91f700 (LWP 99907)] | 9 | We always satisfy these conditions in qemu - even when we support |
10 | 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 | 10 | multiple clients, ALL clients go through a single point of reference |
11 | 1437 ../block/mirror.c: No such file or directory. | 11 | into the block layer, with no local caching. The effect of one client |
12 | (gdb) p s->job | 12 | is instantly visible to the next client. Even if our backend were a |
13 | $17 = (MirrorBlockJob *) 0x0 | 13 | network device, we argue that any multi-path caching effects that |
14 | (gdb) p s->stop | 14 | would cause inconsistencies in back-to-back actions not seeing the |
15 | $18 = false | 15 | effect of previous actions would be a bug in that backend, and not the |
16 | 16 | fault of caching in qemu. As such, it is safe to unconditionally | |
17 | Call trace of IO thread: | 17 | advertise CAN_MULTI_CONN for any qemu NBD server situation that |
18 | 0 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 | 18 | supports parallel clients. |
19 | 1 0x00005576d0f7f3ab in bdrv_driver_pwritev at ../block/io.c:1174 | 19 | |
20 | 2 0x00005576d0f8139d in bdrv_aligned_pwritev at ../block/io.c:1988 | 20 | Note, however, that we don't want to advertise CAN_MULTI_CONN when we |
21 | 3 0x00005576d0f81b65 in bdrv_co_pwritev_part at ../block/io.c:2156 | 21 | know that a second client cannot connect (for historical reasons, |
22 | 4 0x00005576d0f8e6b7 in blk_do_pwritev_part at ../block/block-backend.c:1260 | 22 | qemu-nbd defaults to a single connection while nbd-server-add and QMP |
23 | 5 0x00005576d0f8e84d in blk_aio_write_entry at ../block/block-backend.c:1476 | 23 | commands default to unlimited connections; but we already have |
24 | ... | 24 | existing means to let either style of NBD server creation alter those |
25 | 25 | defaults). This is visible by no longer advertising MULTI_CONN for | |
26 | Switch to qemu main thread: | 26 | 'qemu-nbd -r' without -e, as in the iotest nbd-qemu-allocation. |
27 | 0 0x00007f903be704ed in __lll_lock_wait at | 27 | |
28 | /lib/../lib64/libpthread.so.0 | 28 | The harder part of this patch is setting up an iotest to demonstrate |
29 | 1 0x00007f903be6bde6 in _L_lock_941 at /lib/../lib64/libpthread.so.0 | 29 | behavior of multiple NBD clients to a single server. It might be |
30 | 2 0x00007f903be6bcdf in pthread_mutex_lock at | 30 | possible with parallel qemu-io processes, but I found it easier to do |
31 | /lib/../lib64/libpthread.so.0 | 31 | in python with the help of libnbd, and help from Nir and Vladimir in |
32 | 3 0x0000564b21456889 in qemu_mutex_lock_impl at | 32 | writing the test. |
33 | ../util/qemu-thread-posix.c:79 | 33 | |
34 | 4 0x0000564b213af8a5 in block_job_add_bdrv at ../blockjob.c:224 | 34 | Signed-off-by: Eric Blake <eblake@redhat.com> |
35 | 5 0x0000564b213b00ad in block_job_create at ../blockjob.c:440 | 35 | Suggested-by: Nir Soffer <nsoffer@redhat.com> |
36 | 6 0x0000564b21357c0a in mirror_start_job at ../block/mirror.c:1622 | 36 | Suggested-by: Vladimir Sementsov-Ogievskiy <v.sementsov-og@mail.ru> |
37 | 7 0x0000564b2135a9af in commit_active_start at ../block/mirror.c:1867 | 37 | Message-Id: <20220512004924.417153-3-eblake@redhat.com> |
38 | 8 0x0000564b2133d132 in qmp_block_commit at ../blockdev.c:2768 | ||
39 | 9 0x0000564b2141fef3 in qmp_marshal_block_commit at | ||
40 | qapi/qapi-commands-block-core.c:346 | ||
41 | 10 0x0000564b214503c9 in do_qmp_dispatch_bh at | ||
42 | ../qapi/qmp-dispatch.c:110 | ||
43 | 11 0x0000564b21451996 in aio_bh_poll at ../util/async.c:164 | ||
44 | 12 0x0000564b2146018e in aio_dispatch at ../util/aio-posix.c:381 | ||
45 | 13 0x0000564b2145187e in aio_ctx_dispatch at ../util/async.c:306 | ||
46 | 14 0x00007f9040239049 in g_main_context_dispatch at | ||
47 | /lib/../lib64/libglib-2.0.so.0 | ||
48 | 15 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:232 | ||
49 | 16 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:255 | ||
50 | 17 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:531 | ||
51 | 18 0x0000564b212304e1 in qemu_main_loop at ../softmmu/runstate.c:721 | ||
52 | 19 0x0000564b20f7975e in main at ../softmmu/main.c:50 | ||
53 | |||
54 | In IO thread when do bdrv_mirror_top_pwritev, the job is NULL, and stop field | ||
55 | is false, this means the MirrorBDSOpaque "s" object has not been initialized | ||
56 | yet, and this object is initialized by block_job_create(), but the initialize | ||
57 | process is stuck in acquiring the lock. | ||
58 | |||
59 | In this situation, IO thread come to bdrv_mirror_top_pwritev(),which means that | ||
60 | mirror-top node is already inserted into block graph, but its bs->opaque->job | ||
61 | is not initialized. | ||
62 | |||
63 | The root cause is that qemu main thread do release/acquire when hold the lock, | ||
64 | at the same time, IO thread get the lock after release stage, and the crash | ||
65 | occured. | ||
66 | |||
67 | Actually, in this situation, job->job.aio_context will not equal to | ||
68 | qemu_get_aio_context(), and will be the same as bs->aio_context, | ||
69 | thus, no need to release the lock, becasue bdrv_root_attach_child() | ||
70 | will not change the context. | ||
71 | |||
72 | This patch fix this issue. | ||
73 | |||
74 | Fixes: 132ada80 "block: Adjust AioContexts when attaching nodes" | ||
75 | |||
76 | Signed-off-by: Michael Qiu <qiudayu@huayun.com> | ||
77 | Message-Id: <20210203024059.52683-1-08005325@163.com> | ||
78 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 38 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
79 | --- | 39 | --- |
80 | blockjob.c | 8 ++++++-- | 40 | qapi/block-export.json | 8 +- |
81 | 1 file changed, 6 insertions(+), 2 deletions(-) | 41 | docs/interop/nbd.txt | 1 + |
82 | 42 | docs/tools/qemu-nbd.rst | 3 +- | |
83 | diff --git a/blockjob.c b/blockjob.c | 43 | include/block/nbd.h | 3 +- |
84 | index XXXXXXX..XXXXXXX 100644 | 44 | blockdev-nbd.c | 5 + |
85 | --- a/blockjob.c | 45 | nbd/server.c | 10 +- |
86 | +++ b/blockjob.c | 46 | MAINTAINERS | 1 + |
87 | @@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, | 47 | tests/qemu-iotests/tests/nbd-multiconn | 145 ++++++++++++++++++ |
88 | uint64_t perm, uint64_t shared_perm, Error **errp) | 48 | tests/qemu-iotests/tests/nbd-multiconn.out | 5 + |
49 | .../tests/nbd-qemu-allocation.out | 2 +- | ||
50 | 10 files changed, 172 insertions(+), 11 deletions(-) | ||
51 | create mode 100755 tests/qemu-iotests/tests/nbd-multiconn | ||
52 | create mode 100644 tests/qemu-iotests/tests/nbd-multiconn.out | ||
53 | |||
54 | diff --git a/qapi/block-export.json b/qapi/block-export.json | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/qapi/block-export.json | ||
57 | +++ b/qapi/block-export.json | ||
58 | @@ -XXX,XX +XXX,XX @@ | ||
59 | # recreated on the fly while the NBD server is active. | ||
60 | # If missing, it will default to denying access (since 4.0). | ||
61 | # @max-connections: The maximum number of connections to allow at the same | ||
62 | -# time, 0 for unlimited. (since 5.2; default: 0) | ||
63 | +# time, 0 for unlimited. Setting this to 1 also stops | ||
64 | +# the server from advertising multiple client support | ||
65 | +# (since 5.2; default: 0) | ||
66 | # | ||
67 | # Since: 4.2 | ||
68 | ## | ||
69 | @@ -XXX,XX +XXX,XX @@ | ||
70 | # recreated on the fly while the NBD server is active. | ||
71 | # If missing, it will default to denying access (since 4.0). | ||
72 | # @max-connections: The maximum number of connections to allow at the same | ||
73 | -# time, 0 for unlimited. (since 5.2; default: 0) | ||
74 | +# time, 0 for unlimited. Setting this to 1 also stops | ||
75 | +# the server from advertising multiple client support | ||
76 | +# (since 5.2; default: 0). | ||
77 | # | ||
78 | # Returns: error if the server is already running. | ||
79 | # | ||
80 | diff --git a/docs/interop/nbd.txt b/docs/interop/nbd.txt | ||
81 | index XXXXXXX..XXXXXXX 100644 | ||
82 | --- a/docs/interop/nbd.txt | ||
83 | +++ b/docs/interop/nbd.txt | ||
84 | @@ -XXX,XX +XXX,XX @@ NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE | ||
85 | * 4.2: NBD_FLAG_CAN_MULTI_CONN for shareable read-only exports, | ||
86 | NBD_CMD_FLAG_FAST_ZERO | ||
87 | * 5.2: NBD_CMD_BLOCK_STATUS for "qemu:allocation-depth" | ||
88 | +* 7.1: NBD_FLAG_CAN_MULTI_CONN for shareable writable exports | ||
89 | diff --git a/docs/tools/qemu-nbd.rst b/docs/tools/qemu-nbd.rst | ||
90 | index XXXXXXX..XXXXXXX 100644 | ||
91 | --- a/docs/tools/qemu-nbd.rst | ||
92 | +++ b/docs/tools/qemu-nbd.rst | ||
93 | @@ -XXX,XX +XXX,XX @@ driver options if :option:`--image-opts` is specified. | ||
94 | .. option:: -e, --shared=NUM | ||
95 | |||
96 | Allow up to *NUM* clients to share the device (default | ||
97 | - ``1``), 0 for unlimited. Safe for readers, but for now, | ||
98 | - consistency is not guaranteed between multiple writers. | ||
99 | + ``1``), 0 for unlimited. | ||
100 | |||
101 | .. option:: -t, --persistent | ||
102 | |||
103 | diff --git a/include/block/nbd.h b/include/block/nbd.h | ||
104 | index XXXXXXX..XXXXXXX 100644 | ||
105 | --- a/include/block/nbd.h | ||
106 | +++ b/include/block/nbd.h | ||
107 | @@ -XXX,XX +XXX,XX @@ | ||
108 | /* | ||
109 | - * Copyright (C) 2016-2020 Red Hat, Inc. | ||
110 | + * Copyright (C) 2016-2022 Red Hat, Inc. | ||
111 | * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws> | ||
112 | * | ||
113 | * Network Block Device | ||
114 | @@ -XXX,XX +XXX,XX @@ void nbd_client_put(NBDClient *client); | ||
115 | |||
116 | void nbd_server_is_qemu_nbd(int max_connections); | ||
117 | bool nbd_server_is_running(void); | ||
118 | +int nbd_server_max_connections(void); | ||
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) | ||
89 | { | 136 | { |
90 | BdrvChild *c; | 137 | nbd_client_put(client); |
91 | + bool need_context_ops; | 138 | diff --git a/nbd/server.c b/nbd/server.c |
92 | 139 | index XXXXXXX..XXXXXXX 100644 | |
93 | bdrv_ref(bs); | 140 | --- a/nbd/server.c |
94 | - if (job->job.aio_context != qemu_get_aio_context()) { | 141 | +++ b/nbd/server.c |
95 | + | 142 | @@ -XXX,XX +XXX,XX @@ |
96 | + need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context; | 143 | /* |
97 | + | 144 | - * Copyright (C) 2016-2021 Red Hat, Inc. |
98 | + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { | 145 | + * Copyright (C) 2016-2022 Red Hat, Inc. |
99 | aio_context_release(job->job.aio_context); | 146 | * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws> |
100 | } | 147 | * |
101 | c = bdrv_root_attach_child(bs, name, &child_job, 0, | 148 | * Network Block Device Server Side |
102 | job->job.aio_context, perm, shared_perm, job, | 149 | @@ -XXX,XX +XXX,XX @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, |
103 | errp); | 150 | int64_t size; |
104 | - if (job->job.aio_context != qemu_get_aio_context()) { | 151 | uint64_t perm, shared_perm; |
105 | + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { | 152 | bool readonly = !exp_args->writable; |
106 | aio_context_acquire(job->job.aio_context); | 153 | - bool shared = !exp_args->writable; |
107 | } | 154 | BlockDirtyBitmapOrStrList *bitmaps; |
108 | if (c == NULL) { | 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 | ||
186 | new file mode 100755 | ||
187 | index XXXXXXX..XXXXXXX | ||
188 | --- /dev/null | ||
189 | +++ b/tests/qemu-iotests/tests/nbd-multiconn | ||
190 | @@ -XXX,XX +XXX,XX @@ | ||
191 | +#!/usr/bin/env python3 | ||
192 | +# group: rw auto quick | ||
193 | +# | ||
194 | +# Test cases for NBD multi-conn advertisement | ||
195 | +# | ||
196 | +# Copyright (C) 2022 Red Hat, Inc. | ||
197 | +# | ||
198 | +# This program is free software; you can redistribute it and/or modify | ||
199 | +# it under the terms of the GNU General Public License as published by | ||
200 | +# the Free Software Foundation; either version 2 of the License, or | ||
201 | +# (at your option) any later version. | ||
202 | +# | ||
203 | +# This program is distributed in the hope that it will be useful, | ||
204 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
205 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
206 | +# GNU General Public License for more details. | ||
207 | +# | ||
208 | +# You should have received a copy of the GNU General Public License | ||
209 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
210 | + | ||
211 | +import os | ||
212 | +from contextlib import contextmanager | ||
213 | +import iotests | ||
214 | +from iotests import qemu_img_create, qemu_io | ||
215 | + | ||
216 | + | ||
217 | +disk = os.path.join(iotests.test_dir, 'disk') | ||
218 | +size = '4M' | ||
219 | +nbd_sock = os.path.join(iotests.sock_dir, 'nbd_sock') | ||
220 | +nbd_uri = 'nbd+unix:///{}?socket=' + nbd_sock | ||
221 | + | ||
222 | + | ||
223 | +@contextmanager | ||
224 | +def open_nbd(export_name): | ||
225 | + h = nbd.NBD() | ||
226 | + try: | ||
227 | + h.connect_uri(nbd_uri.format(export_name)) | ||
228 | + yield h | ||
229 | + finally: | ||
230 | + h.shutdown() | ||
231 | + | ||
232 | +class TestNbdMulticonn(iotests.QMPTestCase): | ||
233 | + def setUp(self): | ||
234 | + qemu_img_create('-f', iotests.imgfmt, disk, size) | ||
235 | + qemu_io('-c', 'w -P 1 0 2M', '-c', 'w -P 2 2M 2M', disk) | ||
236 | + | ||
237 | + self.vm = iotests.VM() | ||
238 | + self.vm.launch() | ||
239 | + result = self.vm.qmp('blockdev-add', { | ||
240 | + 'driver': 'qcow2', | ||
241 | + 'node-name': 'n', | ||
242 | + 'file': {'driver': 'file', 'filename': disk} | ||
243 | + }) | ||
244 | + self.assert_qmp(result, 'return', {}) | ||
245 | + | ||
246 | + def tearDown(self): | ||
247 | + self.vm.shutdown() | ||
248 | + os.remove(disk) | ||
249 | + try: | ||
250 | + os.remove(nbd_sock) | ||
251 | + except OSError: | ||
252 | + pass | ||
253 | + | ||
254 | + @contextmanager | ||
255 | + def run_server(self, max_connections=None): | ||
256 | + args = { | ||
257 | + 'addr': { | ||
258 | + 'type': 'unix', | ||
259 | + 'data': {'path': nbd_sock} | ||
260 | + } | ||
261 | + } | ||
262 | + if max_connections is not None: | ||
263 | + args['max-connections'] = max_connections | ||
264 | + | ||
265 | + result = self.vm.qmp('nbd-server-start', args) | ||
266 | + self.assert_qmp(result, 'return', {}) | ||
267 | + yield | ||
268 | + | ||
269 | + result = self.vm.qmp('nbd-server-stop') | ||
270 | + self.assert_qmp(result, 'return', {}) | ||
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 | ||
337 | new file mode 100644 | ||
338 | index XXXXXXX..XXXXXXX | ||
339 | --- /dev/null | ||
340 | +++ b/tests/qemu-iotests/tests/nbd-multiconn.out | ||
341 | @@ -XXX,XX +XXX,XX @@ | ||
342 | +... | ||
343 | +---------------------------------------------------------------------- | ||
344 | +Ran 3 tests | ||
345 | + | ||
346 | +OK | ||
347 | diff --git a/tests/qemu-iotests/tests/nbd-qemu-allocation.out b/tests/qemu-iotests/tests/nbd-qemu-allocation.out | ||
348 | index XXXXXXX..XXXXXXX 100644 | ||
349 | --- a/tests/qemu-iotests/tests/nbd-qemu-allocation.out | ||
350 | +++ b/tests/qemu-iotests/tests/nbd-qemu-allocation.out | ||
351 | @@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 1048576 | ||
352 | exports available: 1 | ||
353 | export: '' | ||
354 | size: 4194304 | ||
355 | - flags: 0x58f ( readonly flush fua df multi cache ) | ||
356 | + flags: 0x48f ( readonly flush fua df cache ) | ||
357 | min block: 1 | ||
358 | opt block: 4096 | ||
359 | max block: 33554432 | ||
109 | -- | 360 | -- |
110 | 2.29.2 | 361 | 2.35.3 |
111 | |||
112 | diff view generated by jsdifflib |
1 | From: Max Reitz <mreitz@redhat.com> | 1 | From: Paolo Bonzini <pbonzini@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | To disallow certain refcount_bits values, some _unsupported_imgopts | 3 | common.rc has some complicated logic to find the common.config that |
4 | invocations look like "refcount_bits=1[^0-9]", i.e. they match an | 4 | dates back to xfstests and is completely unnecessary now. Just include |
5 | integer boundary with [^0-9]. This expression does not match the end of | 5 | the contents of the file. |
6 | the string, though, so it breaks down when refcount_bits is the last | ||
7 | option (which it tends to be after the rewrite of the check script in | ||
8 | Python). | ||
9 | 6 | ||
10 | Those invocations could use \b or \> instead, but those are not | 7 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
11 | portable. They could use something like \([^0-9]\|$\), but that would | 8 | Message-Id: <20220505094723.732116-1-pbonzini@redhat.com> |
12 | be cumbersome. To make it simple and keep the existing invocations | ||
13 | working, just let _unsupported_imgopts match the regex against $IMGOPTS | ||
14 | plus a trailing space. | ||
15 | |||
16 | Suggested-by: Eric Blake <eblake@redhat.com> | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
18 | Message-Id: <20210210095128.22732-1-mreitz@redhat.com> | ||
19 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
20 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
21 | --- | 10 | --- |
22 | tests/qemu-iotests/common.rc | 4 +++- | 11 | tests/qemu-iotests/common.config | 41 -------------------------------- |
23 | 1 file changed, 3 insertions(+), 1 deletion(-) | 12 | tests/qemu-iotests/common.rc | 31 ++++++++++++++---------- |
13 | 2 files changed, 19 insertions(+), 53 deletions(-) | ||
14 | delete mode 100644 tests/qemu-iotests/common.config | ||
24 | 15 | ||
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 | ||
25 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | 63 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc |
26 | index XXXXXXX..XXXXXXX 100644 | 64 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/tests/qemu-iotests/common.rc | 65 | --- a/tests/qemu-iotests/common.rc |
28 | +++ b/tests/qemu-iotests/common.rc | 66 | +++ b/tests/qemu-iotests/common.rc |
29 | @@ -XXX,XX +XXX,XX @@ _unsupported_imgopts() | 67 | @@ -XXX,XX +XXX,XX @@ |
68 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
69 | # | ||
70 | |||
71 | +export LANG=C | ||
72 | + | ||
73 | +PATH=".:$PATH" | ||
74 | + | ||
75 | +HOSTOS=$(uname -s) | ||
76 | +arch=$(uname -m) | ||
77 | +[[ "$arch" =~ "ppc64" ]] && qemu_arch=ppc64 || qemu_arch="$arch" | ||
78 | + | ||
79 | +# make sure we have a standard umask | ||
80 | +umask 022 | ||
81 | + | ||
82 | # bail out, setting up .notrun file | ||
83 | _notrun() | ||
30 | { | 84 | { |
31 | for bad_opt | 85 | @@ -XXX,XX +XXX,XX @@ peek_file_raw() |
32 | do | 86 | dd if="$1" bs=1 skip="$2" count="$3" status=none |
33 | - if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt" | 87 | } |
34 | + # Add a space so tests can match for whitespace that marks the | 88 | |
35 | + # end of an option (\b or \> are not portable) | 89 | -config=common.config |
36 | + if echo "$IMGOPTS " | grep -q 2>/dev/null "$bad_opt" | 90 | -test -f $config || config=../common.config |
37 | then | 91 | -if ! test -f $config |
38 | _notrun "not suitable for image option: $bad_opt" | 92 | -then |
39 | fi | 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. | ||
40 | -- | 112 | -- |
41 | 2.29.2 | 113 | 2.35.3 |
42 | |||
43 | diff view generated by jsdifflib |