From: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: den@openvz.org, andrey.drobyshev@virtuozzo.com
Subject: [QEMU HCI-8.0 PATCH v3 5/5] vhost-blk: preserve the uevent socket across cpr-exec
Date: Tue, 8 Sep 2026 04:04:55 +0300 [thread overview]
Message-ID: <20260908010455.249679-6-andrey.zhadchenko@virtuozzo.com> (raw)
In-Reply-To: <20260908010455.249679-1-andrey.zhadchenko@virtuozzo.com>
qemu-update uses cpr-exec migration: QEMU re-execs itself in place.
A plain monitor fdset descriptor like our uevent socket does not
survive that (unlike the cpr_save_fd()'d tap/vhost fds), so without
help the resized-device notifications would silently stop until the
next full VM start.
Preserve it the same way the other devices do: on cold boot
cpr_save_fd() the socket under the "<proxy id>_ueventfd" key, and
on the re-exec'd (incoming) side adopt it with cpr_find_fd()
instead of reopening a command line fd that no longer resolves.
The management layer passes a placeholder for the "ueventfd"
property in that case. The restored socket is validated just like
a cold-boot one.
Since a unique device ID is mandatory for FD preservation, block
CPR migration modes when the proxy has no ID, as other devices do.
Drop the saved descriptor on teardown so it does not outlive the
device.
https://virtuozzo.atlassian.net/browse/VSTOR-143437
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
---
v2:
- old one dropped, setup moved to libvirt
- added new patch to support uevent socket cpr
v3:
- use the proxy ID for the CPR fd name and block CPR without an ID
- validate restored sockets and improve failure cleanup
hw/block/vhost-blk.c | 77 +++++++++++++++++++++++++++++++----
include/hw/virtio/vhost-blk.h | 1 +
2 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/hw/block/vhost-blk.c b/hw/block/vhost-blk.c
index a69bdcb551..fa951da47a 100644
--- a/hw/block/vhost-blk.c
+++ b/hw/block/vhost-blk.c
@@ -29,6 +29,8 @@
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <linux/netlink.h>
+#include "migration/blocker.h"
+#include "migration/cpr.h"
#include "system/runstate.h"
static int vhost_blk_start(VirtIODevice *vdev)
@@ -248,12 +250,27 @@ static void vhost_blk_resize_bh(void *opaque)
}
}
+static char *vhost_blk_cpr_name(VHostBlk *s)
+{
+ DeviceState *proxy = qdev_get_parent_bus(DEVICE(s))->parent;
+
+ return proxy->id ? g_strdup_printf("%s_ueventfd", proxy->id) : NULL;
+}
+
static void vhost_blk_uevent_detach(VHostBlk *s)
{
+ g_autofree char *cpr_name = NULL;
+
+ migrate_del_blocker(&s->migration_blocker);
+
if (s->uevent_fd < 0) {
return;
}
+ cpr_name = vhost_blk_cpr_name(s);
+ if (cpr_name) {
+ cpr_delete_fd(cpr_name, 0);
+ }
qemu_set_fd_handler(s->uevent_fd, NULL, NULL, NULL);
qemu_bh_delete(s->resize_bh);
s->resize_bh = NULL;
@@ -395,25 +412,71 @@ static bool vhost_blk_uevent_check(int fd, const char *src, Error **errp)
static bool vhost_blk_uevent_attach(VHostBlk *s, Error **errp)
{
+ g_autofree char *cpr_name = NULL;
+
if (!s->conf.ueventfd) {
return true;
}
- s->uevent_fd = monitor_fd_param(monitor_cur(), s->conf.ueventfd, errp);
- if (s->uevent_fd < 0) {
- error_prepend(errp, "vhost-blk: unable to obtain uevent socket: ");
- return false;
+ cpr_name = vhost_blk_cpr_name(s);
+
+ /*
+ * A unique ID is mandatory for preserving the uevent socket across
+ * CPR migration, so block CPR modes when it is absent.
+ */
+ if (!cpr_name) {
+ error_setg(&s->migration_blocker,
+ "vhost-blk: device ID is required for CPR migration");
+ if (migrate_add_blocker_modes(&s->migration_blocker, errp,
+ MIG_MODE_CPR_TRANSFER,
+ MIG_MODE_CPR_EXEC, -1) < 0) {
+ return false;
+ }
+ }
+
+ if (cpr_is_incoming()) {
+ if (!cpr_name) {
+ error_setg(errp,
+ "vhost-blk: device ID is required for CPR migration");
+ goto fail;
+ }
+ s->uevent_fd = cpr_find_fd(cpr_name, 0);
+ if (s->uevent_fd < 0) {
+ error_setg(errp,
+ "vhost-blk: no preserved uevent socket to restore");
+ goto fail;
+ }
+ } else {
+ s->uevent_fd = monitor_fd_param(monitor_cur(), s->conf.ueventfd, errp);
+ if (s->uevent_fd < 0) {
+ error_prepend(errp, "vhost-blk: unable to obtain uevent socket: ");
+ goto fail;
+ }
}
if (!vhost_blk_uevent_check(s->uevent_fd, s->conf.ueventfd, errp)) {
- qemu_close(s->uevent_fd);
- s->uevent_fd = -1;
- return false;
+ goto fail;
+ }
+
+ if (cpr_name && !cpr_is_incoming()) {
+ /* Preserve the socket across a future cpr-exec qemu-update. */
+ cpr_save_fd(cpr_name, 0, s->uevent_fd);
}
s->resize_bh = qemu_bh_new(vhost_blk_resize_bh, s);
qemu_set_fd_handler(s->uevent_fd, vhost_blk_uevent_read, NULL, s);
return true;
+
+fail:
+ if (s->uevent_fd >= 0) {
+ if (cpr_name && cpr_is_incoming()) {
+ cpr_delete_fd(cpr_name, 0);
+ }
+ qemu_close(s->uevent_fd);
+ s->uevent_fd = -1;
+ }
+ migrate_del_blocker(&s->migration_blocker);
+ return false;
}
static bool vhost_blk_open_backend(VHostBlk *s, Error **errp)
diff --git a/include/hw/virtio/vhost-blk.h b/include/hw/virtio/vhost-blk.h
index e3ad92bc6e..2d3f7a30f0 100644
--- a/include/hw/virtio/vhost-blk.h
+++ b/include/hw/virtio/vhost-blk.h
@@ -47,6 +47,7 @@ typedef struct VHostBlk {
uint64_t length;
uint64_t backend_rdev;
QEMUBH *resize_bh;
+ Error *migration_blocker; /* set when the device has no ID */
} VHostBlk;
#endif
--
2.43.5
next prev parent reply other threads:[~2026-09-08 1:07 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 1:04 [QEMU HCI-8.0 PATCH v3 0/5] vhost-blk change backend setup Andrey Zhadchenko
2026-09-08 1:04 ` [QEMU HCI-8.0 PATCH v3 1/5] vhost-blk: improve vhost_blk_device_realize cleanup Andrey Zhadchenko
2026-09-08 11:11 ` Andrey Drobyshev
2026-09-08 1:04 ` [QEMU HCI-8.0 PATCH v3 2/5] vhost-blk: change backend setup Andrey Zhadchenko
2026-09-08 11:11 ` Andrey Drobyshev
2026-09-08 1:04 ` [QEMU HCI-8.0 PATCH v3 3/5] vhost-blk: add read-only flag Andrey Zhadchenko
2026-09-08 11:11 ` Andrey Drobyshev
2026-09-08 1:04 ` [QEMU HCI-8.0 PATCH v3 4/5] vhost-blk: watch the device for resize events Andrey Zhadchenko
2026-09-08 11:11 ` Andrey Drobyshev
2026-09-08 1:04 ` Andrey Zhadchenko [this message]
2026-09-08 11:11 ` [QEMU HCI-8.0 PATCH v3 5/5] vhost-blk: preserve the uevent socket across cpr-exec Andrey Drobyshev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260908010455.249679-6-andrey.zhadchenko@virtuozzo.com \
--to=andrey.zhadchenko@virtuozzo.com \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=den@openvz.org \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.