diff --git a/kvm-block-Avoid-processing-BDS-twice-in-bdrv_set_aio_con.patch b/kvm-block-Avoid-processing-BDS-twice-in-bdrv_set_aio_con.patch new file mode 100644 index 0000000..59376b8 --- /dev/null +++ b/kvm-block-Avoid-processing-BDS-twice-in-bdrv_set_aio_con.patch @@ -0,0 +1,96 @@ +From 0db52fa2553ba83454a347e0aca4896e1b0d9b41 Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Thu, 11 Feb 2021 14:42:06 -0300 +Subject: [PATCH 4/6] block: Avoid processing BDS twice in + bdrv_set_aio_context_ignore() + +RH-Author: Sergio Lopez Pascual +Message-id: <20210211144208.58930-4-slp@redhat.com> +Patchwork-id: 101050 +O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 3/5] block: Avoid processing BDS twice in bdrv_set_aio_context_ignore() +Bugzilla: 1918966 1918968 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Eric Blake + +Some graphs may contain an indirect reference to the first BDS in the +chain that can be reached while walking it bottom->up from one its +children. + +Doubling-processing of a BDS is especially problematic for the +aio_notifiers, as they might attempt to work on both the old and the +new AIO contexts. + +To avoid this problem, add every child and parent to the ignore list +before actually processing them. + +Suggested-by: Kevin Wolf +Signed-off-by: Sergio Lopez +Message-Id: <20210201125032.44713-2-slp@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 722d8e73d65cb54f39d360ecb2147ac58f43c399) +Signed-off-by: Sergio Lopez +Signed-off-by: Eduardo Lima (Etrunko) +--- + block.c | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/block.c b/block.c +index f1cedac362..8bfa446f9c 100644 +--- a/block.c ++++ b/block.c +@@ -6454,7 +6454,10 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, + AioContext *new_context, GSList **ignore) + { + AioContext *old_context = bdrv_get_aio_context(bs); +- BdrvChild *child; ++ GSList *children_to_process = NULL; ++ GSList *parents_to_process = NULL; ++ GSList *entry; ++ BdrvChild *child, *parent; + + g_assert(qemu_get_current_aio_context() == qemu_get_aio_context()); + +@@ -6469,16 +6472,33 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, + continue; + } + *ignore = g_slist_prepend(*ignore, child); +- bdrv_set_aio_context_ignore(child->bs, new_context, ignore); ++ children_to_process = g_slist_prepend(children_to_process, child); + } +- QLIST_FOREACH(child, &bs->parents, next_parent) { +- if (g_slist_find(*ignore, child)) { ++ ++ QLIST_FOREACH(parent, &bs->parents, next_parent) { ++ if (g_slist_find(*ignore, parent)) { + continue; + } +- assert(child->klass->set_aio_ctx); +- *ignore = g_slist_prepend(*ignore, child); +- child->klass->set_aio_ctx(child, new_context, ignore); ++ *ignore = g_slist_prepend(*ignore, parent); ++ parents_to_process = g_slist_prepend(parents_to_process, parent); ++ } ++ ++ for (entry = children_to_process; ++ entry != NULL; ++ entry = g_slist_next(entry)) { ++ child = entry->data; ++ bdrv_set_aio_context_ignore(child->bs, new_context, ignore); ++ } ++ g_slist_free(children_to_process); ++ ++ for (entry = parents_to_process; ++ entry != NULL; ++ entry = g_slist_next(entry)) { ++ parent = entry->data; ++ assert(parent->klass->set_aio_ctx); ++ parent->klass->set_aio_ctx(parent, new_context, ignore); + } ++ g_slist_free(parents_to_process); + + bdrv_detach_aio_context(bs); + +-- +2.27.0 + diff --git a/kvm-block-Honor-blk_set_aio_context-context-requirements.patch b/kvm-block-Honor-blk_set_aio_context-context-requirements.patch new file mode 100644 index 0000000..de75ecc --- /dev/null +++ b/kvm-block-Honor-blk_set_aio_context-context-requirements.patch @@ -0,0 +1,118 @@ +From bc284d49a00a1a716b380c2245aa0b897a259a5d Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Thu, 11 Feb 2021 14:42:04 -0300 +Subject: [PATCH 2/6] block: Honor blk_set_aio_context() context requirements + +RH-Author: Sergio Lopez Pascual +Message-id: <20210211144208.58930-2-slp@redhat.com> +Patchwork-id: 101049 +O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 1/5] block: Honor blk_set_aio_context() context requirements +Bugzilla: 1918966 1918968 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Eric Blake + +The documentation for bdrv_set_aio_context_ignore() states this: + + * The caller must own the AioContext lock for the old AioContext of bs, but it + * must not own the AioContext lock for new_context (unless new_context is the + * same as the current context of bs). + +As blk_set_aio_context() makes use of this function, this rule also +applies to it. + +Fix all occurrences where this rule wasn't honored. + +Suggested-by: Kevin Wolf +Signed-off-by: Sergio Lopez +Message-Id: <20201214170519.223781-2-slp@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Eric Blake +(cherry picked from commit c7040ff64ec93ee925a81d3547db925fe7d1f1c0) +Signed-off-by: Sergio Lopez +Signed-off-by: Eduardo Lima (Etrunko) +--- + hw/block/dataplane/virtio-blk.c | 4 ++++ + hw/block/dataplane/xen-block.c | 7 ++++++- + hw/scsi/virtio-scsi.c | 6 ++++-- + 3 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index 37499c5564..e9050c8987 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -172,6 +172,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) + VirtIOBlockDataPlane *s = vblk->dataplane; + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vblk))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); ++ AioContext *old_context; + unsigned i; + unsigned nvqs = s->conf->num_queues; + Error *local_err = NULL; +@@ -214,7 +215,10 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) + vblk->dataplane_started = true; + trace_virtio_blk_data_plane_start(s); + ++ old_context = blk_get_aio_context(s->conf->conf.blk); ++ aio_context_acquire(old_context); + r = blk_set_aio_context(s->conf->conf.blk, s->ctx, &local_err); ++ aio_context_release(old_context); + if (r < 0) { + error_report_err(local_err); + goto fail_guest_notifiers; +diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c +index 71c337c7b7..3675f8deaf 100644 +--- a/hw/block/dataplane/xen-block.c ++++ b/hw/block/dataplane/xen-block.c +@@ -725,6 +725,7 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, + { + ERRP_GUARD(); + XenDevice *xendev = dataplane->xendev; ++ AioContext *old_context; + unsigned int ring_size; + unsigned int i; + +@@ -808,10 +809,14 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, + goto stop; + } + +- aio_context_acquire(dataplane->ctx); ++ old_context = blk_get_aio_context(dataplane->blk); ++ aio_context_acquire(old_context); + /* If other users keep the BlockBackend in the iothread, that's ok */ + blk_set_aio_context(dataplane->blk, dataplane->ctx, NULL); ++ aio_context_release(old_context); ++ + /* Only reason for failure is a NULL channel */ ++ aio_context_acquire(dataplane->ctx); + xen_device_set_event_channel_context(xendev, dataplane->event_channel, + dataplane->ctx, &error_abort); + aio_context_release(dataplane->ctx); +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 82c025146d..66bdda5473 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -821,6 +821,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, + VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + SCSIDevice *sd = SCSI_DEVICE(dev); ++ AioContext *old_context; + int ret; + + /* XXX: Remove this check once block backend is capable of handling +@@ -836,9 +837,10 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, + if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { + return; + } +- virtio_scsi_acquire(s); ++ old_context = blk_get_aio_context(sd->conf.blk); ++ aio_context_acquire(old_context); + ret = blk_set_aio_context(sd->conf.blk, s->ctx, errp); +- virtio_scsi_release(s); ++ aio_context_release(old_context); + if (ret < 0) { + return; + } +-- +2.27.0 + diff --git a/kvm-block-move-blk_exp_close_all-to-qemu_cleanup.patch b/kvm-block-move-blk_exp_close_all-to-qemu_cleanup.patch new file mode 100644 index 0000000..dcda5bc --- /dev/null +++ b/kvm-block-move-blk_exp_close_all-to-qemu_cleanup.patch @@ -0,0 +1,101 @@ +From 661245e1baf416570295fad0db1fdd5ad8485e33 Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Thu, 11 Feb 2021 14:42:08 -0300 +Subject: [PATCH 6/6] block: move blk_exp_close_all() to qemu_cleanup() + +RH-Author: Sergio Lopez Pascual +Message-id: <20210211144208.58930-6-slp@redhat.com> +Patchwork-id: 101052 +O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 5/5] block: move blk_exp_close_all() to qemu_cleanup() +Bugzilla: 1918966 1918968 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Eric Blake + +Move blk_exp_close_all() from bdrv_close() to qemu_cleanup(), before +bdrv_drain_all_begin(). + +Export drivers may have coroutines yielding at some point in the block +layer, so we need to shut them down before draining the block layer, +as otherwise they may get stuck blk_wait_while_drained(). + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1900505 +Signed-off-by: Sergio Lopez +Message-Id: <20210201125032.44713-3-slp@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 1895b977f9a69419ae45cfc25805f71efae32eaf) +Signed-off-by: Sergio Lopez +Signed-off-by: Eduardo Lima (Etrunko) +--- + block.c | 1 - + qemu-nbd.c | 1 + + softmmu/vl.c | 9 +++++++++ + storage-daemon/qemu-storage-daemon.c | 1 + + 4 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/block.c b/block.c +index 8bfa446f9c..57c60efc7f 100644 +--- a/block.c ++++ b/block.c +@@ -4472,7 +4472,6 @@ static void bdrv_close(BlockDriverState *bs) + void bdrv_close_all(void) + { + assert(job_next(NULL) == NULL); +- blk_exp_close_all(); + + /* Drop references from requests still in flight, such as canceled block + * jobs whose AIO context has not been polled yet */ +diff --git a/qemu-nbd.c b/qemu-nbd.c +index a7075c5419..1d337b7504 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -509,6 +509,7 @@ static const char *socket_activation_validate_opts(const char *device, + static void qemu_nbd_shutdown(void) + { + job_cancel_sync_all(); ++ blk_exp_close_all(); + bdrv_close_all(); + } + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index 065d52e8dc..3244ee5e12 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -66,6 +66,7 @@ + #include "qemu/log.h" + #include "sysemu/blockdev.h" + #include "hw/block/block.h" ++#include "block/export.h" + #include "migration/misc.h" + #include "migration/snapshot.h" + #include "migration/global_state.h" +@@ -4526,6 +4527,14 @@ void qemu_cleanup(void) + */ + migration_shutdown(); + ++ /* ++ * Close the exports before draining the block layer. The export ++ * drivers may have coroutines yielding on it, so we need to clean ++ * them up before the drain, as otherwise they may be get stuck in ++ * blk_wait_while_drained(). ++ */ ++ blk_exp_close_all(); ++ + /* + * We must cancel all block jobs while the block layer is drained, + * or cancelling will be affected by throttling and thus may block +diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c +index e0c87edbdd..d8d172cc60 100644 +--- a/storage-daemon/qemu-storage-daemon.c ++++ b/storage-daemon/qemu-storage-daemon.c +@@ -314,6 +314,7 @@ int main(int argc, char *argv[]) + main_loop_wait(false); + } + ++ blk_exp_close_all(); + bdrv_drain_all_begin(); + bdrv_close_all(); + +-- +2.27.0 + diff --git a/kvm-nbd-server-Quiesce-coroutines-on-context-switch.patch b/kvm-nbd-server-Quiesce-coroutines-on-context-switch.patch new file mode 100644 index 0000000..d0080d2 --- /dev/null +++ b/kvm-nbd-server-Quiesce-coroutines-on-context-switch.patch @@ -0,0 +1,249 @@ +From 7cadf68c46abcd097fcbcecb11a4a04f264d0316 Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Thu, 11 Feb 2021 14:42:05 -0300 +Subject: [PATCH 3/6] nbd/server: Quiesce coroutines on context switch + +RH-Author: Sergio Lopez Pascual +Message-id: <20210211144208.58930-3-slp@redhat.com> +Patchwork-id: 101051 +O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 2/5] nbd/server: Quiesce coroutines on context switch +Bugzilla: 1918966 1918968 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Eric Blake + +When switching between AIO contexts we need to me make sure that both +recv_coroutine and send_coroutine are not scheduled to run. Otherwise, +QEMU may crash while attaching the new context with an error like +this one: + +aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule' + +To achieve this we need a local implementation of +'qio_channel_readv_all_eof' named 'nbd_read_eof' (a trick already done +by 'nbd/client.c') that allows us to interrupt the operation and to +know when recv_coroutine is yielding. + +With this in place, we delegate detaching the AIO context to the +owning context with a BH ('nbd_aio_detach_bh') scheduled using +'aio_wait_bh_oneshot'. This BH signals that we need to quiesce the +channel by setting 'client->quiescing' to 'true', and either waits for +the coroutine to finish using AIO_WAIT_WHILE or, if it's yielding in +'nbd_read_eof', actively enters the coroutine to interrupt it. + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1900326 +Signed-off-by: Sergio Lopez +Reviewed-by: Eric Blake +Message-Id: <20201214170519.223781-4-slp@redhat.com> +Signed-off-by: Eric Blake +(cherry picked from commit f148ae7d36cbb924447f4b528a94d7799836c749) +Signed-off-by: Sergio Lopez +Signed-off-by: Eduardo Lima (Etrunko) +--- + nbd/server.c | 120 +++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 106 insertions(+), 14 deletions(-) + +diff --git a/nbd/server.c b/nbd/server.c +index 613ed2634a..7229f487d2 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -132,6 +132,9 @@ struct NBDClient { + CoMutex send_lock; + Coroutine *send_coroutine; + ++ bool read_yielding; ++ bool quiescing; ++ + QTAILQ_ENTRY(NBDClient) next; + int nb_requests; + bool closing; +@@ -1352,14 +1355,60 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp) + return 0; + } + +-static int nbd_receive_request(QIOChannel *ioc, NBDRequest *request, ++/* nbd_read_eof ++ * Tries to read @size bytes from @ioc. This is a local implementation of ++ * qio_channel_readv_all_eof. We have it here because we need it to be ++ * interruptible and to know when the coroutine is yielding. ++ * Returns 1 on success ++ * 0 on eof, when no data was read (errp is not set) ++ * negative errno on failure (errp is set) ++ */ ++static inline int coroutine_fn ++nbd_read_eof(NBDClient *client, void *buffer, size_t size, Error **errp) ++{ ++ bool partial = false; ++ ++ assert(size); ++ while (size > 0) { ++ struct iovec iov = { .iov_base = buffer, .iov_len = size }; ++ ssize_t len; ++ ++ len = qio_channel_readv(client->ioc, &iov, 1, errp); ++ if (len == QIO_CHANNEL_ERR_BLOCK) { ++ client->read_yielding = true; ++ qio_channel_yield(client->ioc, G_IO_IN); ++ client->read_yielding = false; ++ if (client->quiescing) { ++ return -EAGAIN; ++ } ++ continue; ++ } else if (len < 0) { ++ return -EIO; ++ } else if (len == 0) { ++ if (partial) { ++ error_setg(errp, ++ "Unexpected end-of-file before all bytes were read"); ++ return -EIO; ++ } else { ++ return 0; ++ } ++ } ++ ++ partial = true; ++ size -= len; ++ buffer = (uint8_t *) buffer + len; ++ } ++ return 1; ++} ++ ++static int nbd_receive_request(NBDClient *client, NBDRequest *request, + Error **errp) + { + uint8_t buf[NBD_REQUEST_SIZE]; + uint32_t magic; + int ret; + +- ret = nbd_read(ioc, buf, sizeof(buf), "request", errp); ++ ret = nbd_read_eof(client, buf, sizeof(buf), errp); + if (ret < 0) { + return ret; + } +@@ -1480,11 +1529,37 @@ static void blk_aio_attached(AioContext *ctx, void *opaque) + + QTAILQ_FOREACH(client, &exp->clients, next) { + qio_channel_attach_aio_context(client->ioc, ctx); ++ ++ assert(client->recv_coroutine == NULL); ++ assert(client->send_coroutine == NULL); ++ ++ if (client->quiescing) { ++ client->quiescing = false; ++ nbd_client_receive_next_request(client); ++ } ++ } ++} ++ ++static void nbd_aio_detach_bh(void *opaque) ++{ ++ NBDExport *exp = opaque; ++ NBDClient *client; ++ ++ QTAILQ_FOREACH(client, &exp->clients, next) { ++ qio_channel_detach_aio_context(client->ioc); ++ client->quiescing = true; ++ + if (client->recv_coroutine) { +- aio_co_schedule(ctx, client->recv_coroutine); ++ if (client->read_yielding) { ++ qemu_aio_coroutine_enter(exp->common.ctx, ++ client->recv_coroutine); ++ } else { ++ AIO_WAIT_WHILE(exp->common.ctx, client->recv_coroutine != NULL); ++ } + } ++ + if (client->send_coroutine) { +- aio_co_schedule(ctx, client->send_coroutine); ++ AIO_WAIT_WHILE(exp->common.ctx, client->send_coroutine != NULL); + } + } + } +@@ -1492,13 +1567,10 @@ static void blk_aio_attached(AioContext *ctx, void *opaque) + static void blk_aio_detach(void *opaque) + { + NBDExport *exp = opaque; +- NBDClient *client; + + trace_nbd_blk_aio_detach(exp->name, exp->common.ctx); + +- QTAILQ_FOREACH(client, &exp->clients, next) { +- qio_channel_detach_aio_context(client->ioc); +- } ++ aio_wait_bh_oneshot(exp->common.ctx, nbd_aio_detach_bh, exp); + + exp->common.ctx = NULL; + } +@@ -2151,20 +2223,23 @@ static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle, + + /* nbd_co_receive_request + * Collect a client request. Return 0 if request looks valid, -EIO to drop +- * connection right away, and any other negative value to report an error to +- * the client (although the caller may still need to disconnect after reporting +- * the error). ++ * connection right away, -EAGAIN to indicate we were interrupted and the ++ * channel should be quiesced, and any other negative value to report an error ++ * to the client (although the caller may still need to disconnect after ++ * reporting the error). + */ + static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request, + Error **errp) + { + NBDClient *client = req->client; + int valid_flags; ++ int ret; + + g_assert(qemu_in_coroutine()); + assert(client->recv_coroutine == qemu_coroutine_self()); +- if (nbd_receive_request(client->ioc, request, errp) < 0) { +- return -EIO; ++ ret = nbd_receive_request(client, request, errp); ++ if (ret < 0) { ++ return ret; + } + + trace_nbd_co_receive_request_decode_type(request->handle, request->type, +@@ -2507,6 +2582,17 @@ static coroutine_fn void nbd_trip(void *opaque) + return; + } + ++ if (client->quiescing) { ++ /* ++ * We're switching between AIO contexts. Don't attempt to receive a new ++ * request and kick the main context which may be waiting for us. ++ */ ++ nbd_client_put(client); ++ client->recv_coroutine = NULL; ++ aio_wait_kick(); ++ return; ++ } ++ + req = nbd_request_get(client); + ret = nbd_co_receive_request(req, &request, &local_err); + client->recv_coroutine = NULL; +@@ -2519,6 +2605,11 @@ static coroutine_fn void nbd_trip(void *opaque) + goto done; + } + ++ if (ret == -EAGAIN) { ++ assert(client->quiescing); ++ goto done; ++ } ++ + nbd_client_receive_next_request(client); + if (ret == -EIO) { + goto disconnect; +@@ -2565,7 +2656,8 @@ disconnect: + + static void nbd_client_receive_next_request(NBDClient *client) + { +- if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) { ++ if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS && ++ !client->quiescing) { + nbd_client_get(client); + client->recv_coroutine = qemu_coroutine_create(nbd_trip, client); + aio_co_schedule(client->exp->common.ctx, client->recv_coroutine); +-- +2.27.0 + diff --git a/kvm-storage-daemon-Call-bdrv_close_all-on-exit.patch b/kvm-storage-daemon-Call-bdrv_close_all-on-exit.patch new file mode 100644 index 0000000..7b0472c --- /dev/null +++ b/kvm-storage-daemon-Call-bdrv_close_all-on-exit.patch @@ -0,0 +1,48 @@ +From b1883ddf10c2ec31ac72866494687d8897535a82 Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Thu, 11 Feb 2021 14:42:07 -0300 +Subject: [PATCH 5/6] storage-daemon: Call bdrv_close_all() on exit + +RH-Author: Sergio Lopez Pascual +Message-id: <20210211144208.58930-5-slp@redhat.com> +Patchwork-id: 101048 +O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 4/5] storage-daemon: Call bdrv_close_all() on exit +Bugzilla: 1918966 1918968 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Eric Blake + +From: Max Reitz + +Otherwise, exports and block devices are not properly shut down and +closed, unless the users explicitly issues blockdev-del and +block-export-del commands for each of them. + +Signed-off-by: Max Reitz +Reviewed-by: Kevin Wolf +Message-Id: <20201027190600.192171-17-mreitz@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit b55a3c8860b763b62b2cc2f4a6f55379977bbde5) +Signed-off-by: Sergio Lopez +Signed-off-by: Eduardo Lima (Etrunko) +--- + storage-daemon/qemu-storage-daemon.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c +index 7c914b0dc1..e0c87edbdd 100644 +--- a/storage-daemon/qemu-storage-daemon.c ++++ b/storage-daemon/qemu-storage-daemon.c +@@ -314,6 +314,9 @@ int main(int argc, char *argv[]) + main_loop_wait(false); + } + ++ bdrv_drain_all_begin(); ++ bdrv_close_all(); ++ + monitor_cleanup(); + qemu_chr_cleanup(); + user_creatable_cleanup(); +-- +2.27.0 + diff --git a/kvm-virtio-Add-corresponding-memory_listener_unregister-.patch b/kvm-virtio-Add-corresponding-memory_listener_unregister-.patch new file mode 100644 index 0000000..46c96b0 --- /dev/null +++ b/kvm-virtio-Add-corresponding-memory_listener_unregister-.patch @@ -0,0 +1,234 @@ +From ac9e40a75eba0019fb9930835804e8daceead981 Mon Sep 17 00:00:00 2001 +From: eperezma +Date: Tue, 9 Feb 2021 10:38:16 -0300 +Subject: [PATCH 1/6] virtio: Add corresponding memory_listener_unregister to + unrealize +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: eperezma +Message-id: <20210209103816.1636200-2-eperezma@redhat.com> +Patchwork-id: 101009 +O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 1/1] virtio: Add corresponding memory_listener_unregister to unrealize +Bugzilla: 1903521 +RH-Acked-by: Peter Xu +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +Address space is destroyed without proper removal of its listeners with +current code. They are expected to be removed in +virtio_device_instance_finalize [1], but qemu calls it through +object_deinit, after address_space_destroy call through +device_set_realized [2]. + +Move it to virtio_device_unrealize, called before device_set_realized +[3] and making it symmetric with memory_listener_register in +virtio_device_realize. + +v2: Delete no-op call of virtio_device_instance_finalize. + Add backtraces. + +[1] + + #0 virtio_device_instance_finalize (obj=0x555557de5120) + at /home/qemu/include/hw/virtio/virtio.h:71 + #1 0x0000555555b703c9 in object_deinit (type=0x555556639860, + obj=) at ../qom/object.c:671 + #2 object_finalize (data=0x555557de5120) at ../qom/object.c:685 + #3 object_unref (objptr=0x555557de5120) at ../qom/object.c:1184 + #4 0x0000555555b4de9d in bus_free_bus_child (kid=0x555557df0660) + at ../hw/core/qdev.c:55 + #5 0x0000555555c65003 in call_rcu_thread (opaque=opaque@entry=0x0) + at ../util/rcu.c:281 + +Queued by: + + #0 bus_remove_child (bus=0x555557de5098, + child=child@entry=0x555557de5120) at ../hw/core/qdev.c:60 + #1 0x0000555555b4ee31 in device_unparent (obj=) + at ../hw/core/qdev.c:984 + #2 0x0000555555b70465 in object_finalize_child_property ( + obj=, name=, opaque=0x555557de5120) + at ../qom/object.c:1725 + #3 0x0000555555b6fa17 in object_property_del_child ( + child=0x555557de5120, obj=0x555557ddcf90) at ../qom/object.c:645 + #4 object_unparent (obj=0x555557de5120) at ../qom/object.c:664 + #5 0x0000555555b4c071 in bus_unparent (obj=) + at ../hw/core/bus.c:147 + #6 0x0000555555b70465 in object_finalize_child_property ( + obj=, name=, opaque=0x555557de5098) + at ../qom/object.c:1725 + #7 0x0000555555b6fa17 in object_property_del_child ( + child=0x555557de5098, obj=0x555557ddcf90) at ../qom/object.c:645 + #8 object_unparent (obj=0x555557de5098) at ../qom/object.c:664 + #9 0x0000555555b4ee19 in device_unparent (obj=) + at ../hw/core/qdev.c:981 + #10 0x0000555555b70465 in object_finalize_child_property ( + obj=, name=, opaque=0x555557ddcf90) + at ../qom/object.c:1725 + #11 0x0000555555b6fa17 in object_property_del_child ( + child=0x555557ddcf90, obj=0x55555685da10) at ../qom/object.c:645 + #12 object_unparent (obj=0x555557ddcf90) at ../qom/object.c:664 + #13 0x00005555558dc331 in pci_for_each_device_under_bus ( + opaque=, fn=, bus=) + at ../hw/pci/pci.c:1654 + +[2] + +Optimizer omits pci_qdev_unrealize, called by device_set_realized, and +do_pci_unregister_device, called by pci_qdev_unrealize and caller of +address_space_destroy. + + #0 address_space_destroy (as=0x555557ddd1b8) + at ../softmmu/memory.c:2840 + #1 0x0000555555b4fc53 in device_set_realized (obj=0x555557ddcf90, + value=, errp=0x7fffeea8f1e0) + at ../hw/core/qdev.c:850 + #2 0x0000555555b6eaa6 in property_set_bool (obj=0x555557ddcf90, + v=, name=, opaque=0x555556650ba0, + errp=0x7fffeea8f1e0) at ../qom/object.c:2255 + #3 0x0000555555b70e07 in object_property_set ( + obj=obj@entry=0x555557ddcf90, + name=name@entry=0x555555db99df "realized", + v=v@entry=0x7fffe46b7500, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/object.c:1400 + #4 0x0000555555b73c5f in object_property_set_qobject ( + obj=obj@entry=0x555557ddcf90, + name=name@entry=0x555555db99df "realized", + value=value@entry=0x7fffe44f6180, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/qom-qobject.c:28 + #5 0x0000555555b71044 in object_property_set_bool ( + obj=0x555557ddcf90, name=0x555555db99df "realized", + value=, errp=0x5555565bbf38 ) + at ../qom/object.c:1470 + #6 0x0000555555921cb7 in pcie_unplug_device (bus=, + dev=0x555557ddcf90, + opaque=) at /home/qemu/include/hw/qdev-core.h:17 + #7 0x00005555558dc331 in pci_for_each_device_under_bus ( + opaque=, fn=, + bus=) at ../hw/pci/pci.c:1654 + +[3] + + #0 virtio_device_unrealize (dev=0x555557de5120) + at ../hw/virtio/virtio.c:3680 + #1 0x0000555555b4fc63 in device_set_realized (obj=0x555557de5120, + value=, errp=0x7fffee28df90) + at ../hw/core/qdev.c:850 + #2 0x0000555555b6eab6 in property_set_bool (obj=0x555557de5120, + v=, name=, opaque=0x555556650ba0, + errp=0x7fffee28df90) at ../qom/object.c:2255 + #3 0x0000555555b70e17 in object_property_set ( + obj=obj@entry=0x555557de5120, + name=name@entry=0x555555db99ff "realized", + v=v@entry=0x7ffdd8035040, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/object.c:1400 + #4 0x0000555555b73c6f in object_property_set_qobject ( + obj=obj@entry=0x555557de5120, + name=name@entry=0x555555db99ff "realized", + value=value@entry=0x7ffdd8035020, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/qom-qobject.c:28 + #5 0x0000555555b71054 in object_property_set_bool ( + obj=0x555557de5120, name=name@entry=0x555555db99ff "realized", + value=value@entry=false, errp=0x5555565bbf38 ) + at ../qom/object.c:1470 + #6 0x0000555555b4edc5 in qdev_unrealize (dev=) + at ../hw/core/qdev.c:403 + #7 0x0000555555b4c2a9 in bus_set_realized (obj=, + value=, errp=) + at ../hw/core/bus.c:204 + #8 0x0000555555b6eab6 in property_set_bool (obj=0x555557de5098, + v=, name=, opaque=0x555557df04c0, + errp=0x7fffee28e0a0) at ../qom/object.c:2255 + #9 0x0000555555b70e17 in object_property_set ( + obj=obj@entry=0x555557de5098, + name=name@entry=0x555555db99ff "realized", + v=v@entry=0x7ffdd8034f50, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/object.c:1400 + #10 0x0000555555b73c6f in object_property_set_qobject ( + obj=obj@entry=0x555557de5098, + name=name@entry=0x555555db99ff "realized", + value=value@entry=0x7ffdd8020630, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/qom-qobject.c:28 + #11 0x0000555555b71054 in object_property_set_bool ( + obj=obj@entry=0x555557de5098, + name=name@entry=0x555555db99ff "realized", + value=value@entry=false, errp=0x5555565bbf38 ) + at ../qom/object.c:1470 + #12 0x0000555555b4c725 in qbus_unrealize ( + bus=bus@entry=0x555557de5098) at ../hw/core/bus.c:178 + #13 0x0000555555b4fc00 in device_set_realized (obj=0x555557ddcf90, + value=, errp=0x7fffee28e1e0) + at ../hw/core/qdev.c:844 + #14 0x0000555555b6eab6 in property_set_bool (obj=0x555557ddcf90, + v=, name=, opaque=0x555556650ba0, + errp=0x7fffee28e1e0) at ../qom/object.c:2255 + #15 0x0000555555b70e17 in object_property_set ( + obj=obj@entry=0x555557ddcf90, + name=name@entry=0x555555db99ff "realized", + v=v@entry=0x7ffdd8020560, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/object.c:1400 + #16 0x0000555555b73c6f in object_property_set_qobject ( + obj=obj@entry=0x555557ddcf90, + name=name@entry=0x555555db99ff "realized", + value=value@entry=0x7ffdd8020540, + errp=errp@entry=0x5555565bbf38 ) + at ../qom/qom-qobject.c:28 + #17 0x0000555555b71054 in object_property_set_bool ( + obj=0x555557ddcf90, name=0x555555db99ff "realized", + value=, errp=0x5555565bbf38 ) + at ../qom/object.c:1470 + #18 0x0000555555921cb7 in pcie_unplug_device (bus=, + dev=0x555557ddcf90, opaque=) + at /home/qemu/include/hw/qdev-core.h:17 + #19 0x00005555558dc331 in pci_for_each_device_under_bus ( + opaque=, fn=, bus=) + at ../hw/pci/pci.c:1654 + +Fixes: c611c76417f ("virtio: add MemoryListener to cache ring translations") +Buglink: https://bugs.launchpad.net/qemu/+bug/1912846 +Signed-off-by: Eugenio Pérez +Message-Id: <20210125192505.390554-1-eperezma@redhat.com> +Reviewed-by: Peter Xu +Acked-by: Jason Wang +Reviewed-by: Stefano Garzarella +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit f6ab64c05f8a6229bf6569d3791c23abb9f6eee4) +Signed-off-by: Eugenio Pérez +Signed-off-by: Eduardo Lima (Etrunko) +--- + hw/virtio/virtio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index ceb58fda6c..9312e7191b 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3677,6 +3677,7 @@ static void virtio_device_unrealize(DeviceState *dev) + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev); + ++ memory_listener_unregister(&vdev->listener); + virtio_bus_device_unplugged(vdev); + + if (vdc->unrealize != NULL) { +@@ -3707,7 +3708,6 @@ static void virtio_device_instance_finalize(Object *obj) + { + VirtIODevice *vdev = VIRTIO_DEVICE(obj); + +- memory_listener_unregister(&vdev->listener); + virtio_device_free_virtqueues(vdev); + + g_free(vdev->config); +-- +2.27.0 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 0d479b1..15cb799 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -64,7 +64,7 @@ Requires: %{name}-block-ssh = %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 5.2.0 -Release: 6%{?dist} +Release: 7%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -165,6 +165,23 @@ Patch63: kvm-hw-arm-smmuv3-Fix-addr_mask-for-range-based-invalida.patch Patch65: kvm-vhost-Unbreak-SMMU-and-virtio-iommu-on-dev-iotlb-sup.patch # For bz#1902537 - The default fsfreeze-hook path from man page and qemu-ga --help command are different Patch66: kvm-docs-set-CONFDIR-when-running-sphinx.patch +# For bz#1903521 - hot unplug vhost-user cause qemu crash: qemu-kvm: ../softmmu/memory.c:2818: do_address_space_destroy: Assertion `QTAILQ_EMPTY(&as->listeners)' failed. +Patch67: kvm-virtio-Add-corresponding-memory_listener_unregister-.patch +# For bz#1918966 - [incremental_backup] qemu aborts if guest reboot during backup when using virtio-blk: "aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule'" +# For bz#1918968 - [incremental_backup] qemu deadlock after poweroff in guest during backup in nbd_export_close_all() +Patch68: kvm-block-Honor-blk_set_aio_context-context-requirements.patch +# For bz#1918966 - [incremental_backup] qemu aborts if guest reboot during backup when using virtio-blk: "aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule'" +# For bz#1918968 - [incremental_backup] qemu deadlock after poweroff in guest during backup in nbd_export_close_all() +Patch69: kvm-nbd-server-Quiesce-coroutines-on-context-switch.patch +# For bz#1918966 - [incremental_backup] qemu aborts if guest reboot during backup when using virtio-blk: "aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule'" +# For bz#1918968 - [incremental_backup] qemu deadlock after poweroff in guest during backup in nbd_export_close_all() +Patch70: kvm-block-Avoid-processing-BDS-twice-in-bdrv_set_aio_con.patch +# For bz#1918966 - [incremental_backup] qemu aborts if guest reboot during backup when using virtio-blk: "aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule'" +# For bz#1918968 - [incremental_backup] qemu deadlock after poweroff in guest during backup in nbd_export_close_all() +Patch71: kvm-storage-daemon-Call-bdrv_close_all-on-exit.patch +# For bz#1918966 - [incremental_backup] qemu aborts if guest reboot during backup when using virtio-blk: "aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule'" +# For bz#1918968 - [incremental_backup] qemu deadlock after poweroff in guest during backup in nbd_export_close_all() +Patch72: kvm-block-move-blk_exp_close_all-to-qemu_cleanup.patch BuildRequires: wget BuildRequires: rpm-build @@ -1354,6 +1371,21 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog +* Fri Feb 12 2021 Eduardo Lima (Etrunko) - 5.2.0-7.el8 +- kvm-virtio-Add-corresponding-memory_listener_unregister-.patch [bz#1903521] +- kvm-block-Honor-blk_set_aio_context-context-requirements.patch [bz#1918966 bz#1918968] +- kvm-nbd-server-Quiesce-coroutines-on-context-switch.patch [bz#1918966 bz#1918968] +- kvm-block-Avoid-processing-BDS-twice-in-bdrv_set_aio_con.patch [bz#1918966 bz#1918968] +- kvm-storage-daemon-Call-bdrv_close_all-on-exit.patch [bz#1918966 bz#1918968] +- kvm-block-move-blk_exp_close_all-to-qemu_cleanup.patch [bz#1918966 bz#1918968] +- Resolves: bz#1903521 + (hot unplug vhost-user cause qemu crash: qemu-kvm: ../softmmu/memory.c:2818: do_address_space_destroy: Assertion `QTAILQ_EMPTY(&as->listeners)' failed.) +- Resolves: bz#1918966 + ([incremental_backup] qemu aborts if guest reboot during backup when using virtio-blk: "aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule'") +- Resolves: bz#1918968 + ([incremental_backup] qemu deadlock after poweroff in guest during backup in nbd_export_close_all()) + + * Fri Feb 12 2021 Miroslav Rezanina - 5.2.0-6.el8 - kvm-scsi-fix-device-removal-race-vs-IO-restart-callback-.patch [bz#1854811] - kvm-tracetool-also-strip-l-and-ll-from-systemtap-format-.patch [bz#1907264]