From 15d40e9204eb3d89577187f117a1dde2237bdc4d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 4 Feb 2021 08:21:37 +0100 Subject: qemu-storage-daemon: Enable object-add MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we don't have a fully QAPIfied version of object-add yet and it still has 'gen': false in the schema, it needs to be registered explicitly in init_qmp_commands() to be available for users. Fixes: 2af282ec51a27116d0402cab237b8970800f870c Signed-off-by: Kevin Wolf Message-Id: <20210204072137.19663-1-kwolf@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Kevin Wolf --- storage-daemon/qemu-storage-daemon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c index d8d172c..9021a46 100644 --- a/storage-daemon/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -144,6 +144,8 @@ static void init_qmp_commands(void) qmp_init_marshal(&qmp_commands); qmp_register_command(&qmp_commands, "query-qmp-schema", qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); + qmp_register_command(&qmp_commands, "object-add", qmp_object_add, + QCO_NO_OPTIONS); QTAILQ_INIT(&qmp_cap_negotiation_commands); qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", -- cgit v1.1 From b34cdf32256e59e0183fe0f7ee5b5f4865d9ccc0 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Wed, 10 Feb 2021 10:51:28 +0100 Subject: iotests: Consistent $IMGOPTS boundary matching To disallow certain refcount_bits values, some _unsupported_imgopts invocations look like "refcount_bits=1[^0-9]", i.e. they match an integer boundary with [^0-9]. This expression does not match the end of the string, though, so it breaks down when refcount_bits is the last option (which it tends to be after the rewrite of the check script in Python). Those invocations could use \b or \> instead, but those are not portable. They could use something like \([^0-9]\|$\), but that would be cumbersome. To make it simple and keep the existing invocations working, just let _unsupported_imgopts match the regex against $IMGOPTS plus a trailing space. Suggested-by: Eric Blake Signed-off-by: Max Reitz Message-Id: <20210210095128.22732-1-mreitz@redhat.com> Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/common.rc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 77c37e8..65cdba5 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -885,7 +885,9 @@ _unsupported_imgopts() { for bad_opt do - if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt" + # Add a space so tests can match for whitespace that marks the + # end of an option (\b or \> are not portable) + if echo "$IMGOPTS " | grep -q 2>/dev/null "$bad_opt" then _notrun "not suitable for image option: $bad_opt" fi -- cgit v1.1 From 076d467aacdf6dc5d01e2e61740b1795f2aec2f6 Mon Sep 17 00:00:00 2001 From: Michael Qiu Date: Wed, 3 Feb 2021 10:40:59 +0800 Subject: blockjob: Fix crash with IOthread when block commit after snapshot Currently, if guest has workloads, IO thread will acquire aio_context lock before do io_submit, it leads to segmentfault when do block commit after snapshot. Just like below: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7f7c7d91f700 (LWP 99907)] 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 1437 ../block/mirror.c: No such file or directory. (gdb) p s->job $17 = (MirrorBlockJob *) 0x0 (gdb) p s->stop $18 = false Call trace of IO thread: 0 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 1 0x00005576d0f7f3ab in bdrv_driver_pwritev at ../block/io.c:1174 2 0x00005576d0f8139d in bdrv_aligned_pwritev at ../block/io.c:1988 3 0x00005576d0f81b65 in bdrv_co_pwritev_part at ../block/io.c:2156 4 0x00005576d0f8e6b7 in blk_do_pwritev_part at ../block/block-backend.c:1260 5 0x00005576d0f8e84d in blk_aio_write_entry at ../block/block-backend.c:1476 ... Switch to qemu main thread: 0 0x00007f903be704ed in __lll_lock_wait at /lib/../lib64/libpthread.so.0 1 0x00007f903be6bde6 in _L_lock_941 at /lib/../lib64/libpthread.so.0 2 0x00007f903be6bcdf in pthread_mutex_lock at /lib/../lib64/libpthread.so.0 3 0x0000564b21456889 in qemu_mutex_lock_impl at ../util/qemu-thread-posix.c:79 4 0x0000564b213af8a5 in block_job_add_bdrv at ../blockjob.c:224 5 0x0000564b213b00ad in block_job_create at ../blockjob.c:440 6 0x0000564b21357c0a in mirror_start_job at ../block/mirror.c:1622 7 0x0000564b2135a9af in commit_active_start at ../block/mirror.c:1867 8 0x0000564b2133d132 in qmp_block_commit at ../blockdev.c:2768 9 0x0000564b2141fef3 in qmp_marshal_block_commit at qapi/qapi-commands-block-core.c:346 10 0x0000564b214503c9 in do_qmp_dispatch_bh at ../qapi/qmp-dispatch.c:110 11 0x0000564b21451996 in aio_bh_poll at ../util/async.c:164 12 0x0000564b2146018e in aio_dispatch at ../util/aio-posix.c:381 13 0x0000564b2145187e in aio_ctx_dispatch at ../util/async.c:306 14 0x00007f9040239049 in g_main_context_dispatch at /lib/../lib64/libglib-2.0.so.0 15 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:232 16 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:255 17 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:531 18 0x0000564b212304e1 in qemu_main_loop at ../softmmu/runstate.c:721 19 0x0000564b20f7975e in main at ../softmmu/main.c:50 In IO thread when do bdrv_mirror_top_pwritev, the job is NULL, and stop field is false, this means the MirrorBDSOpaque "s" object has not been initialized yet, and this object is initialized by block_job_create(), but the initialize process is stuck in acquiring the lock. In this situation, IO thread come to bdrv_mirror_top_pwritev(),which means that mirror-top node is already inserted into block graph, but its bs->opaque->job is not initialized. The root cause is that qemu main thread do release/acquire when hold the lock, at the same time, IO thread get the lock after release stage, and the crash occured. Actually, in this situation, job->job.aio_context will not equal to qemu_get_aio_context(), and will be the same as bs->aio_context, thus, no need to release the lock, becasue bdrv_root_attach_child() will not change the context. This patch fix this issue. Fixes: 132ada80 "block: Adjust AioContexts when attaching nodes" Signed-off-by: Michael Qiu Message-Id: <20210203024059.52683-1-08005325@163.com> Signed-off-by: Kevin Wolf --- blockjob.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/blockjob.c b/blockjob.c index db3a216..f2feff0 100644 --- a/blockjob.c +++ b/blockjob.c @@ -212,15 +212,19 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, uint64_t perm, uint64_t shared_perm, Error **errp) { BdrvChild *c; + bool need_context_ops; bdrv_ref(bs); - if (job->job.aio_context != qemu_get_aio_context()) { + + need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context; + + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { aio_context_release(job->job.aio_context); } c = bdrv_root_attach_child(bs, name, &child_job, 0, job->job.aio_context, perm, shared_perm, job, errp); - if (job->job.aio_context != qemu_get_aio_context()) { + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { aio_context_acquire(job->job.aio_context); } if (c == NULL) { -- cgit v1.1 From 26941eb4ca485150494379cf8f0751f426208a5b Mon Sep 17 00:00:00 2001 From: Alexander Bulekov Date: Tue, 19 Jan 2021 11:40:51 -0500 Subject: hw/ide/ahci: map cmd_fis as DMA_DIRECTION_TO_DEVICE cmd_fis is mapped as DMA_DIRECTION_FROM_DEVICE, however, it is read from, and not written to anywhere. Fix the DMA_DIRECTION and mark cmd_fis as read-only in the code. Signed-off-by: Alexander Bulekov Message-Id: <20210119164051.89268-1-alxndr@bu.edu> Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 6d50482..f2c5157 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -700,7 +700,7 @@ static void ahci_reset_port(AHCIState *s, int port) } /* Buffer pretty output based on a raw FIS structure. */ -static char *ahci_pretty_buffer_fis(uint8_t *fis, int cmd_len) +static char *ahci_pretty_buffer_fis(const uint8_t *fis, int cmd_len) { int i; GString *s = g_string_new("FIS:"); @@ -1100,11 +1100,11 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs) } -static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, +static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, uint8_t slot) { AHCIDevice *ad = &s->dev[port]; - NCQFrame *ncq_fis = (NCQFrame*)cmd_fis; + const NCQFrame *ncq_fis = (NCQFrame *)cmd_fis; uint8_t tag = ncq_fis->tag >> 3; NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag]; size_t size; @@ -1185,7 +1185,7 @@ static AHCICmdHdr *get_cmd_header(AHCIState *s, uint8_t port, uint8_t slot) } static void handle_reg_h2d_fis(AHCIState *s, int port, - uint8_t slot, uint8_t *cmd_fis) + uint8_t slot, const uint8_t *cmd_fis) { IDEState *ide_state = &s->dev[port].port.ifs[0]; AHCICmdHdr *cmd = get_cmd_header(s, port, slot); @@ -1301,7 +1301,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) tbl_addr = le64_to_cpu(cmd->tbl_addr); cmd_len = 0x80; cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len, - DMA_DIRECTION_FROM_DEVICE); + DMA_DIRECTION_TO_DEVICE); if (!cmd_fis) { trace_handle_cmd_badfis(s, port); return -1; @@ -1326,7 +1326,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) } out: - dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE, + dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_TO_DEVICE, cmd_len); if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { -- cgit v1.1 From 7f22201ac85186dd476d5ff8da278ab603df72b6 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Mon, 18 Jan 2021 16:33:30 +0100 Subject: xen-block: fix reporting of discard feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux blkfront expects both "discard-granularity" and "discard-alignment" present on xenbus in order to properly enable the feature, not exposing "discard-alignment" left some Linux blkfront versions with a broken discard setup. This has also been addressed in Linux with: https://lore.kernel.org/lkml/20210118151528.81668-1-roger.pau@citrix.com/T/#u Fix QEMU to report a "discard-alignment" of 0, in order for it to work with older Linux frontends. Reported-by: Arthur Borsboom Signed-off-by: Roger Pau Monné Message-Id: <20210118153330.82324-1-roger.pau@citrix.com> Reviewed-by: Paul Durrant Signed-off-by: Kevin Wolf --- hw/block/xen-block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 0e7d66c..a3b69e2 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -253,6 +253,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) xen_device_backend_printf(xendev, "feature-discard", "%u", 1); xen_device_backend_printf(xendev, "discard-granularity", "%u", conf->discard_granularity); + xen_device_backend_printf(xendev, "discard-alignment", "%u", 0); } xen_device_backend_printf(xendev, "feature-flush-cache", "%u", 1); -- cgit v1.1 From f8b467b443fb3e1c531e0a8b3201104277401ee5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 15 Feb 2021 11:38:35 +0100 Subject: tests/qemu-iotests: Remove test 259 from the "auto" group Tests in the "auto" group should support qcow2 so that they can be run during "make check-block". Test 259 only supports "raw", so it currently always gets skipped when running "make check-block". Let's skip this unnecessary step and remove it from the auto group. Signed-off-by: Thomas Huth Message-Id: <20210215103835.1129145-1-thuth@redhat.com> Signed-off-by: Kevin Wolf --- tests/qemu-iotests/259 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259 index 76cde42..1b15e8f 100755 --- a/tests/qemu-iotests/259 +++ b/tests/qemu-iotests/259 @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# group: rw auto quick +# group: rw quick # # Test generic image creation fallback (by using NBD) # -- cgit v1.1 From dcb6699512b6235eac383fc84e8e27302e08d7e3 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Thu, 17 Dec 2020 19:09:02 +0200 Subject: crypto: luks: Fix tiny memory leak When the underlying block device doesn't support the bdrv_co_delete_file interface, an 'Error' object was leaked. Signed-off-by: Maxim Levitsky Reviewed-by: Alberto Garcia Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20201217170904.946013-2-mlevitsk@redhat.com> Signed-off-by: Kevin Wolf --- block/crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/crypto.c b/block/crypto.c index aef5a57..b3a5275 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -735,6 +735,8 @@ fail: */ if ((r_del < 0) && (r_del != -ENOTSUP)) { error_report_err(local_delete_err); + } else { + error_free(local_delete_err); } } -- cgit v1.1 From a890f08e586fd81946c51dae6a878d64486b1364 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Thu, 17 Dec 2020 19:09:03 +0200 Subject: block: add bdrv_co_delete_file_noerr This function wraps bdrv_co_delete_file for the common case of removing a file, which was just created by format driver, on an error condition. It hides the -ENOTSUPP error, and reports all other errors otherwise. Use it in luks driver Signed-off-by: Maxim Levitsky Reviewed-by: Alberto Garcia Message-Id: <20201217170904.946013-3-mlevitsk@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block.c | 22 ++++++++++++++++++++++ block/crypto.c | 15 ++------------- include/block/block.h | 1 + 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/block.c b/block.c index c682c3e..a1f3cec 100644 --- a/block.c +++ b/block.c @@ -706,6 +706,28 @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) return ret; } +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs) +{ + Error *local_err = NULL; + int ret; + + if (!bs) { + return; + } + + ret = bdrv_co_delete_file(bs, &local_err); + /* + * ENOTSUP will happen if the block driver doesn't support + * the 'bdrv_co_delete_file' interface. This is a predictable + * scenario and shouldn't be reported back to the user. + */ + if (ret == -ENOTSUP) { + error_free(local_err); + } else if (ret < 0) { + error_report_err(local_err); + } +} + /** * Try to get @bs's logical and physical block size. * On success, store them in @bsz struct and return 0. diff --git a/block/crypto.c b/block/crypto.c index b3a5275..1d30fde 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -725,19 +725,8 @@ fail: * If an error occurred, delete 'filename'. Even if the file existed * beforehand, it has been truncated and corrupted in the process. */ - if (ret && bs) { - Error *local_delete_err = NULL; - int r_del = bdrv_co_delete_file(bs, &local_delete_err); - /* - * ENOTSUP will happen if the block driver doesn't support - * the 'bdrv_co_delete_file' interface. This is a predictable - * scenario and shouldn't be reported back to the user. - */ - if ((r_del < 0) && (r_del != -ENOTSUP)) { - error_report_err(local_delete_err); - } else { - error_free(local_delete_err); - } + if (ret) { + bdrv_co_delete_file_noerr(bs); } bdrv_unref(bs); diff --git a/include/block/block.h b/include/block/block.h index a9b7f03..b3f6e50 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -441,6 +441,7 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, Error **errp); void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs); typedef struct BdrvCheckResult { -- cgit v1.1 From 6094cbeb72117204f3302a4581415ee1dc33a879 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Thu, 17 Dec 2020 19:09:04 +0200 Subject: block: qcow2: remove the created file on initialization error If the qcow initialization fails, we should remove the file if it was already created, to avoid leaving stale files around. We already do this for luks raw images. Signed-off-by: Maxim Levitsky Reviewed-by: Alberto Garcia Message-Id: <20201217170904.946013-4-mlevitsk@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/qcow2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 5d94f45..d9f49a5 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3846,12 +3846,14 @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, /* Create the qcow2 image (format layer) */ ret = qcow2_co_create(create_options, errp); +finish: if (ret < 0) { - goto finish; + bdrv_co_delete_file_noerr(bs); + bdrv_co_delete_file_noerr(data_bs); + } else { + ret = 0; } - ret = 0; -finish: qobject_unref(qdict); bdrv_unref(bs); bdrv_unref(data_bs); -- cgit v1.1 From c81219a7dd36a815bd85beed9932fc973d4f5d51 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 12 Feb 2021 18:20:27 +0100 Subject: monitor: Fix assertion failure on shutdown Commit 357bda95 already tried to fix the order in monitor_cleanup() by moving shutdown of the dispatcher coroutine further to the start. However, it didn't go far enough: iothread_stop() makes sure that all pending work (bottom halves) in the AioContext of the monitor iothread is completed. iothread_destroy() depends on this and fails an assertion if there is still a pending BH. While the dispatcher coroutine is running, it will try to resume the monitor after taking a request out of the queue, which involves a BH. The dispatcher is run until it terminates in the AIO_WAIT_WHILE() loop. However, adding new BHs between iothread_stop() and iothread_destroy() is forbidden. Fix this by stopping the dispatcher first before shutting down the other parts of the monitor. This means we can now receive requests that aren't handled any more when QEMU is shutting down, but this is unlikely to be a problem for QMP clients. Fixes: 357bda9590784ff75803d52de43150d4107ed98e Signed-off-by: Kevin Wolf Message-Id: <20210212172028.288825-2-kwolf@redhat.com> Tested-by: Markus Armbruster Reviewed-by: Markus Armbruster Signed-off-by: Kevin Wolf --- monitor/monitor.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/monitor/monitor.c b/monitor/monitor.c index 1e4a6b3..e94f532 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -619,16 +619,6 @@ void monitor_data_destroy(Monitor *mon) void monitor_cleanup(void) { /* - * We need to explicitly stop the I/O thread (but not destroy it), - * clean up the monitor resources, then destroy the I/O thread since - * we need to unregister from chardev below in - * monitor_data_destroy(), and chardev is not thread-safe yet - */ - if (mon_iothread) { - iothread_stop(mon_iothread); - } - - /* * The dispatcher needs to stop before destroying the monitor and * the I/O thread. * @@ -637,6 +627,11 @@ void monitor_cleanup(void) * eventually terminates. qemu_aio_context is automatically * polled by calling AIO_WAIT_WHILE on it, but we must poll * iohandler_ctx manually. + * + * Letting the iothread continue while shutting down the dispatcher + * means that new requests may still be coming in. This is okay, + * we'll just leave them in the queue without sending a response + * and monitor_data_destroy() will free them. */ qmp_dispatcher_co_shutdown = true; if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { @@ -647,6 +642,16 @@ void monitor_cleanup(void) (aio_poll(iohandler_get_aio_context(), false), qatomic_mb_read(&qmp_dispatcher_co_busy))); + /* + * We need to explicitly stop the I/O thread (but not destroy it), + * clean up the monitor resources, then destroy the I/O thread since + * we need to unregister from chardev below in + * monitor_data_destroy(), and chardev is not thread-safe yet + */ + if (mon_iothread) { + iothread_stop(mon_iothread); + } + /* Flush output buffers and destroy monitors */ qemu_mutex_lock(&monitor_lock); monitor_destroyed = true; -- cgit v1.1 From b248e61652e20c3353af4b0ccb90f17d76f4db21 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 12 Feb 2021 18:20:28 +0100 Subject: monitor/qmp: Stop processing requests when shutdown is requested Before this patch, monitor_qmp_dispatcher_co() used to check whether shutdown is requested only when it would have to wait for new requests. If there were still some queued requests, it would try to execute all of them before shutting down. This can be surprising when the queued QMP commands take long or hang because Ctrl-C may not actually exit QEMU as soon as possible. Change monitor_qmp_dispatcher_co() so that it additionally checks whether shutdown is request before it gets a new request from the queue. Signed-off-by: Kevin Wolf Message-Id: <20210212172028.288825-3-kwolf@redhat.com> Tested-by: Markus Armbruster Reviewed-by: Markus Armbruster Signed-off-by: Kevin Wolf --- monitor/qmp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/monitor/qmp.c b/monitor/qmp.c index 43880fa..2326bd7 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -227,6 +227,11 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) */ qatomic_mb_set(&qmp_dispatcher_co_busy, false); + /* On shutdown, don't take any more requests from the queue */ + if (qmp_dispatcher_co_shutdown) { + return; + } + while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) { /* * No more requests to process. Wait to be reentered from -- cgit v1.1