Re: [PATCH v2 4/4] vhost-user: add skip_drain param to GET_VRING_BASE
Alexandr Moshkov <[email protected]> Fri, 27 Mar 2026 14:14:10 +0500
| Newsgroups | dev.linux.lists.virtio-fs,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On 3/26/26 20:52, Stefan Hajnoczi wrote: > On Wed, Mar 11, 2026 at 01:47:28PM +0500, Alexandr Moshkov wrote: >> In case of migration of QEMU from the new version (where the >> inllight-migration parameter is present), to the old one (where it is >> absent) there is no way to disable this feature on the backend during >> runtime. >> >> This commit slightly changes the semantics of the protocol feature >> VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT. Enabling this feature >> adds a new parameter for GET_VRING_BASE, which allows to control the >> drain in-flight requests on the backend. >> Thus, QEMU will be able to turn this feature on GET_VRING_BASE off and >> on anytime. >> >> In vhost-user-blk use inflight_migration param to enable skip_drain to >> suspend in-flight I/O requests, and then migrate them throught inflight >> subsection. >> >> Also now QEMU will always try to setup >> VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT protocol featrue with >> backend. This will allow to use skip_drain parameter on GET_VRING_BASE >> message. >> >> Signed-off-by: Alexandr Moshkov <[email protected]> >> --- >> docs/interop/vhost-user.rst | 6 ++---- >> hw/block/vhost-user-blk.c | 29 +++++++++++++++++++++++------ >> hw/virtio/vhost-user.c | 3 +-- >> hw/virtio/vhost.c | 4 +--- >> include/hw/virtio/vhost-user.h | 1 - >> 5 files changed, 27 insertions(+), 16 deletions(-) >> >> diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst >> index bfa75ff9a3..63efc87264 100644 >> --- a/docs/interop/vhost-user.rst >> +++ b/docs/interop/vhost-user.rst >> @@ -1255,14 +1255,12 @@ Front-end message types >> *suspended*, see :ref:`Suspended device state >> <suspended_device_state>`. >> >> - The request payload's *num* field is currently reserved and must be >> - set to 0. >> - >> By default, the back-end must complete all inflight I/O requests for the >> specified vring before stopping it. >> >> If the ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT`` protocol >> - feature has been negotiated, the back-end may suspend in-flight I/O >> + feature has been negotiated, using request payload's *num* field, >> + when *num* is set to 1, QEMU can tell the back-end to suspend in-flight I/O >> requests and record them as described in :ref:`Inflight I/O tracking >> <inflight_io_tracking>` instead of completing them before stopping the vring. >> How to suspend an in-flight request depends on the implementation of the back-end >> diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c >> index 1dc49c104e..8cc80eb0c3 100644 >> --- a/hw/block/vhost-user-blk.c >> +++ b/hw/block/vhost-user-blk.c >> @@ -134,10 +134,7 @@ static bool vhost_user_blk_inflight_needed(void *opaque) >> { >> struct VHostUserBlk *s = opaque; >> >> - bool inflight_migration = virtio_has_feature(s->dev.protocol_features, >> - VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT); >> - >> - return inflight_migration; >> + return s->inflight_migration; >> } >> >> >> @@ -232,11 +229,14 @@ static int vhost_user_blk_stop(VirtIODevice *vdev) >> return 0; >> } >> >> + bool skip_drain = vhost_user_blk_inflight_needed(s) && >> + runstate_check(RUN_STATE_FINISH_MIGRATE); >> + >> force_stop = s->skip_get_vring_base_on_force_shutdown && >> qemu_force_shutdown_requested(); >> >> ret = force_stop ? vhost_dev_force_stop(&s->dev, vdev, true) : >> - vhost_dev_stop(&s->dev, vdev, true, false); >> + vhost_dev_stop(&s->dev, vdev, true, skip_drain); >> >> if (k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false) < 0) { >> error_report("vhost guest notifier cleanup failed: %d", ret); >> @@ -364,7 +364,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp) >> vhost_dev_set_config_notifier(&s->dev, &blk_ops); >> >> s->vhost_user.supports_config = true; >> - s->vhost_user.supports_inflight_migration = s->inflight_migration; >> ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0, >> errp); >> if (ret < 0) { >> @@ -580,10 +579,28 @@ static struct vhost_dev *vhost_user_blk_get_vhost(VirtIODevice *vdev) >> return &s->dev; >> } >> >> +static bool vhost_user_blk_pre_save(void *opaqueue, Error **errp) >> +{ >> + VHostUserBlk *s = VHOST_USER_BLK(vdev); > This won't compile. "opaqueue" is unused and the vdev variable does not > exist. > >> + >> + bool inflight_migration_enabled = vhost_user_has_protocol_feature(&s->dev, > vhost_user_has_protocol_feature() does not exist. > >> + VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT); >> + if (vhost_user_blk_inflight_needed(s) && !inflight_migration_enabled) { >> + error_setg(errp, "can't migrate vhost-user-blk device: " >> + "backend doesn't support " >> + "VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT " >> + "protocol feature"); >> + return false; >> + } >> + >> + return true; >> +} >> + >> static const VMStateDescription vmstate_vhost_user_blk_inflight = { >> .name = "vhost-user-blk/inflight", >> .version_id = 1, >> .needed = vhost_user_blk_inflight_needed, >> + .pre_save_errp = vhost_user_blk_pre_save, >> .fields = (const VMStateField[]) { >> VMSTATE_VHOST_INFLIGHT_REGION(inflight, VHostUserBlk), >> VMSTATE_END_OF_LIST() >> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c >> index bb8f8eab77..ed95ec7523 100644 >> --- a/hw/virtio/vhost-user.c >> +++ b/hw/virtio/vhost-user.c >> @@ -2225,8 +2225,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, >> } >> } >> >> - if (!u->user->supports_inflight_migration || >> - !virtio_has_feature(protocol_features, >> + if (!virtio_has_feature(protocol_features, >> VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { >> protocol_features &= ~(1ULL << >> VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT); >> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c >> index 4e196fc773..c04bb53159 100644 >> --- a/hw/virtio/vhost.c >> +++ b/hw/virtio/vhost.c >> @@ -1390,12 +1390,10 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev, >> unsigned idx, bool force, >> bool skip_drain) >> { >> - /* TODO: support skip drain */ >> - assert(!skip_drain); > The following assertion would be useful: > > if (skip_drain) { > assert(virtio_has_feature(...protocol_features..., > VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT)); > } Thanks for reply! I'll fix it all >> - >> int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx); >> struct vhost_vring_state state = { >> .index = vhost_vq_index, >> + .num = skip_drain, >> }; >> int r = 0; >> >> diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h >> index 53fe996686..c95bad5ddc 100644 >> --- a/include/hw/virtio/vhost-user.h >> +++ b/include/hw/virtio/vhost-user.h >> @@ -69,7 +69,6 @@ typedef struct VhostUserState { >> GPtrArray *notifiers; >> int memory_slots; >> bool supports_config; >> - bool supports_inflight_migration; >> } VhostUserState; >> >> /** >> -- >> 2.34.1 >>