Add VHOST_USER_GET_VRING_BASE_SKIP_DRAIN protocol message that's tell backend to stops vring immediately without waiting for inflight I/O to complete. This new message can be used only with protocol feature VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHGT.
Signed-off-by: Alexandr Moshkov <[email protected]> --- docs/interop/vhost-user.rst | 38 +++++++++++++++++++++---------- hw/virtio/vhost-user.c | 37 ++++++++++++++++++++++++++---- include/hw/virtio/vhost-backend.h | 1 + 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst index c83ae2accb..27a80ae53b 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``. @@ -1320,17 +1321,8 @@ 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. In other case use, + ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN`` message. ``VHOST_USER_SET_VRING_KICK`` :id: 12 @@ -1833,6 +1825,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: ``VHOST_USER_GET_VRING_BASE_SKIP_DRAIN`` + :request payload: vring state description + :reply payload: vring descriptor index/indices + + This message requires the ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT`` + 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_INFLIGHT`` protocol feature + must only be negotiated if ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` is + also negotiated. + Back-end message types ---------------------- diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index d627351f45..2f71ede599 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,24 @@ 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_INFLIGHT); + 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) @@ -3409,6 +3435,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/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; -- 2.34.1
