Re: [PATCH v5 2/6] vhost-user: add GET_VRING_BASE_SKIP_DRAIN message
"Michael S. Tsirkin" <[email protected]> Wed, 29 Jul 2026 05:14:53 -0400
| Newsgroups | dev.linux.lists.virtio-fs,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Jul 28, 2026 at 03:08:37PM +0500, Alexandr Moshkov wrote: > VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT was introduced to allow > the back-end to suspend in-flight I/O during GET_VRING_BASE instead of > draining it, enabling live migration of in-flight requests. However, > this behaviour is tied to the protocol feature itself — once negotiated, Can we please avoid em-dashes and all kind of unicode fanciness in commit log? I worry if we do this the next step is emojis) Let's stick to ASCII with the exception of UTF-8 in contributor names. Thanks. > there is no way for the front-end to tell the back-end to fall back to > the normal drain behaviour on a per-stop basis. This makes it impossible > to selectively use suspend semantics only during live migration while > keeping drain semantics in other cases. So what are the "other cases"? > > Introduce a separate message VHOST_USER_GET_VRING_BASE_SKIP_DRAIN (id=45) > guarded by a new protocol feature > VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN. The message is identical > to GET_VRING_BASE except that the back-end must immediately suspend all > in-flight I/O and record it in the inflight region. This way the front-end > has explicit per-call control: send GET_VRING_BASE for normal drain, send > GET_VRING_BASE_SKIP_DRAIN when immediate suspend is needed. > > The new feature requires both VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT > and VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD to be negotiated. > > Signed-off-by: Alexandr Moshkov <[email protected]> > --- > docs/interop/vhost-user.rst | 88 +++++++++++++++++++------------ > hw/virtio/vhost-user.c | 44 ++++++++++++++-- > hw/virtio/vhost.c | 2 +- > include/hw/virtio/vhost-backend.h | 1 + > include/hw/virtio/vhost-user.h | 1 + > 5 files changed, 95 insertions(+), 41 deletions(-) > > diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst > index c83ae2accb..d2e0efaeaa 100644 > --- a/docs/interop/vhost-user.rst > +++ b/docs/interop/vhost-user.rst > @@ -445,6 +445,7 @@ replies, except for the following requests: > * ``VHOST_USER_GET_FEATURES`` > * ``VHOST_USER_GET_PROTOCOL_FEATURES`` > * ``VHOST_USER_GET_VRING_BASE`` > +* ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN`` > * ``VHOST_USER_SET_LOG_BASE`` (if ``VHOST_USER_PROTOCOL_F_LOG_SHMFD``) > * ``VHOST_USER_GET_INFLIGHT_FD`` (if ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD``) > > @@ -523,7 +524,7 @@ must start a ring upon receiving a kick (that is, detecting that file > descriptor is readable) on the descriptor specified by > ``VHOST_USER_SET_VRING_KICK`` or receiving the in-band message > ``VHOST_USER_VRING_KICK`` if negotiated, and stop a ring upon receiving > -``VHOST_USER_GET_VRING_BASE``. > +``VHOST_USER_GET_VRING_BASE`` or ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN``. > > Rings can be enabled or disabled by ``VHOST_USER_SET_VRING_ENABLE``. > > @@ -1101,29 +1102,30 @@ Protocol features > > .. code:: c > > - #define VHOST_USER_PROTOCOL_F_MQ 0 > - #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 > - #define VHOST_USER_PROTOCOL_F_RARP 2 > - #define VHOST_USER_PROTOCOL_F_REPLY_ACK 3 > - #define VHOST_USER_PROTOCOL_F_MTU 4 > - #define VHOST_USER_PROTOCOL_F_BACKEND_REQ 5 > - #define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6 > - #define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7 > - #define VHOST_USER_PROTOCOL_F_PAGEFAULT 8 > - #define VHOST_USER_PROTOCOL_F_CONFIG 9 > - #define VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD 10 > - #define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11 > - #define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12 > - #define VHOST_USER_PROTOCOL_F_RESET_DEVICE 13 > - #define VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS 14 > - #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS 15 > - #define VHOST_USER_PROTOCOL_F_STATUS 16 > - #define VHOST_USER_PROTOCOL_F_XEN_MMAP 17 > - #define VHOST_USER_PROTOCOL_F_SHARED_OBJECT 18 > - #define VHOST_USER_PROTOCOL_F_DEVICE_STATE 19 > - #define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT 20 > - #define VHOST_USER_PROTOCOL_F_GPA_ADDRESSES 21 > - #define VHOST_USER_PROTOCOL_F_SHMEM_MAP 22 > + #define VHOST_USER_PROTOCOL_F_MQ 0 > + #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 > + #define VHOST_USER_PROTOCOL_F_RARP 2 > + #define VHOST_USER_PROTOCOL_F_REPLY_ACK 3 > + #define VHOST_USER_PROTOCOL_F_MTU 4 > + #define VHOST_USER_PROTOCOL_F_BACKEND_REQ 5 > + #define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6 > + #define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7 > + #define VHOST_USER_PROTOCOL_F_PAGEFAULT 8 > + #define VHOST_USER_PROTOCOL_F_CONFIG 9 > + #define VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD 10 > + #define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11 > + #define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12 > + #define VHOST_USER_PROTOCOL_F_RESET_DEVICE 13 > + #define VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS 14 > + #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS 15 > + #define VHOST_USER_PROTOCOL_F_STATUS 16 > + #define VHOST_USER_PROTOCOL_F_XEN_MMAP 17 > + #define VHOST_USER_PROTOCOL_F_SHARED_OBJECT 18 > + #define VHOST_USER_PROTOCOL_F_DEVICE_STATE 19 > + #define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT 20 > + #define VHOST_USER_PROTOCOL_F_GPA_ADDRESSES 21 > + #define VHOST_USER_PROTOCOL_F_SHMEM_MAP 22 > + #define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN 23 > > Front-end message types > ----------------------- > @@ -1320,17 +1322,11 @@ Front-end message types > 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 > - 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 > - but it typically can be done by aborting or cancelling the underlying I/O > - request. The ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT`` > - protocol feature must only be negotiated if > - ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` is also negotiated. > + specified vring before stopping it. If the > + ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN`` protocol feature has > + been negotiated, the front-end may instead use > + ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN`` to request the back-end to > + suspend in-flight I/O immediately. > > ``VHOST_USER_SET_VRING_KICK`` > :id: 12 > @@ -1833,6 +1829,28 @@ Front-end message types > > * The size may be 0 if the region is unused. > > +``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN`` > + :id: 45 > + :equivalent ioctl: N/A > + :request payload: vring state description > + :reply payload: vring descriptor index/indices > + > + This message requires the ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN`` > + protocol feature to be negotiated. > + > + Identical to ``VHOST_USER_GET_VRING_BASE`` except that the back-end > + must not wait for inflight I/O requests to complete before stopping > + the vring. Instead, the back-end must immediately suspend all > + in-flight I/O requests and record them as described in > + :ref:`Inflight I/O tracking <inflight_io_tracking>`. How to suspend > + an in-flight request depends on the implementation of the back-end, > + but it typically can be done by aborting or cancelling the underlying > + I/O request. > + > + The ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN`` protocol feature > + must only be negotiated if both ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT`` > + and ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` are also negotiated. > + > Back-end message types > ---------------------- > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c > index d627351f45..bf455daa44 100644 > --- a/hw/virtio/vhost-user.c > +++ b/hw/virtio/vhost-user.c > @@ -101,6 +101,7 @@ typedef enum VhostUserRequest { > VHOST_USER_SET_DEVICE_STATE_FD = 42, > VHOST_USER_CHECK_DEVICE_STATE = 43, > VHOST_USER_GET_SHMEM_CONFIG = 44, > + VHOST_USER_GET_VRING_BASE_SKIP_DRAIN = 45, > VHOST_USER_MAX > } VhostUserRequest; > > @@ -167,6 +168,7 @@ static const char *vhost_req_name(VhostUserRequest req) > VHOST_USER_CASE(GET_SHARED_OBJECT) > VHOST_USER_CASE(SET_DEVICE_STATE_FD) > VHOST_USER_CASE(CHECK_DEVICE_STATE) > + VHOST_USER_CASE(GET_VRING_BASE_SKIP_DRAIN) > default: > return "<unknown>"; > } > @@ -1399,12 +1401,18 @@ static VhostUserHostNotifier *fetch_notifier(VhostUserState *u, > return g_ptr_array_index(u->notifiers, idx); > } > > -static int vhost_user_get_vring_base(struct vhost_dev *dev, > - struct vhost_vring_state *ring) > +static int get_vring_base(struct vhost_dev *dev, > + struct vhost_vring_state *ring, > + bool skip_drain) > { > int ret; > + int request = VHOST_USER_GET_VRING_BASE; > + if (skip_drain) { > + request = VHOST_USER_GET_VRING_BASE_SKIP_DRAIN; > + } > + > VhostUserMsg msg = { > - .hdr.request = VHOST_USER_GET_VRING_BASE, > + .hdr.request = request, > .hdr.flags = VHOST_USER_VERSION, > .payload.state = *ring, > .hdr.size = sizeof(msg.payload.state), > @@ -1424,9 +1432,9 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, > return ret; > } > > - if (msg.hdr.request != VHOST_USER_GET_VRING_BASE) { > + if (msg.hdr.request != request) { > error_report("Received unexpected msg type. Expected %d received %d", > - VHOST_USER_GET_VRING_BASE, msg.hdr.request); > + request, msg.hdr.request); > return -EPROTO; > } > > @@ -1440,6 +1448,25 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, > return 0; > } > > +static int vhost_user_get_vring_base(struct vhost_dev *dev, > + struct vhost_vring_state *ring) > +{ > + return get_vring_base(dev, ring, false); > +} > + > +static int vhost_user_get_vring_base_skip_drain(struct vhost_dev *dev, > + struct vhost_vring_state *ring) > +{ > + bool skip_drain_supported = vhost_user_has_protocol_feature(dev, > + VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN); > + > + if (!skip_drain_supported) { > + return 0; > + } > + > + return get_vring_base(dev, ring, true); > +} > + > static int vhost_set_vring_file(struct vhost_dev *dev, > VhostUserRequest request, > struct vhost_vring_file *file) > @@ -2551,6 +2578,12 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, > VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT); > } > > + if (!virtio_has_feature(protocol_features, > + VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT)) { > + protocol_features &= ~(1ULL << > + VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN); > + } > + > /* final set of protocol features */ > u->protocol_features = protocol_features; > err = vhost_user_set_protocol_features(dev, u->protocol_features); > @@ -3409,6 +3442,7 @@ const VhostOps user_ops = { > .vhost_set_vring_num = vhost_user_set_vring_num, > .vhost_set_vring_base = vhost_user_set_vring_base, > .vhost_get_vring_base = vhost_user_get_vring_base, > + .vhost_get_vring_base_skip_drain = vhost_user_get_vring_base_skip_drain, > .vhost_set_vring_kick = vhost_user_set_vring_kick, > .vhost_set_vring_call = vhost_user_set_vring_call, > .vhost_set_vring_err = vhost_user_set_vring_err, > diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c > index 2a62550222..2c7f464d55 100644 > --- a/hw/virtio/vhost.c > +++ b/hw/virtio/vhost.c > @@ -1502,7 +1502,7 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev, > { > if (skip_drain) { > assert(vhost_user_has_protocol_feature(dev, > - VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT)); > + VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN)); > } > int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx); > struct vhost_vring_state state = { > diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h > index d878d7b733..daa979a1aa 100644 > --- a/include/hw/virtio/vhost-backend.h > +++ b/include/hw/virtio/vhost-backend.h > @@ -190,6 +190,7 @@ typedef struct VhostOps { > vhost_set_vring_num_op vhost_set_vring_num; > vhost_set_vring_base_op vhost_set_vring_base; > vhost_get_vring_base_op vhost_get_vring_base; > + vhost_get_vring_base_op vhost_get_vring_base_skip_drain; > vhost_set_vring_kick_op vhost_set_vring_kick; > vhost_set_vring_call_op vhost_set_vring_call; > vhost_set_vring_err_op vhost_set_vring_err; > diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h > index 06c360af18..47c13f8677 100644 > --- a/include/hw/virtio/vhost-user.h > +++ b/include/hw/virtio/vhost-user.h > @@ -36,6 +36,7 @@ enum VhostUserProtocolFeature { > VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT = 20, > VHOST_USER_PROTOCOL_F_GPA_ADDRESSES = 21, > VHOST_USER_PROTOCOL_F_SHMEM = 22, > + VHOST_USER_PROTOCOL_F_GET_VRING_BASE_SKIP_DRAIN = 23, > VHOST_USER_PROTOCOL_F_MAX > }; > > -- > 2.34.1