diff options
author | Yajun Wu <yajunw@nvidia.com> | 2022-10-18 10:36:51 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2022-11-07 13:12:20 -0500 |
commit | bd437c960f2b071f7e8ba9bd34af8e2537cd6627 (patch) | |
tree | 43b7160b5591edd0de5efba6ef52fa8bc0a4114b /hw | |
parent | 9ea02e8f13068d5f902c4bce909de2997fd77e41 (diff) |
vhost-user: Fix out of order vring host notification handling
vhost backend sends host notification for every VQ. If backend creates
VQs in parallel, the VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG may
arrive to QEMU in different order than incremental queue index order.
For example VQ 1's message arrive earlier than VQ 0's:
After alloc VhostUserHostNotifier for VQ 1. GPtrArray becomes
[ nil, VQ1 pointer ]
After alloc VhostUserHostNotifier for VQ 0. GPtrArray becomes
[ VQ0 pointer, nil, VQ1 pointer ]
This is wrong. fetch_notifier will return NULL for VQ 1 in
vhost_user_get_vring_base, causes host notifier miss removal(leak).
The fix is to remove current element from GPtrArray, make the right
position for element to insert.
Fixes: 503e355465 ("virtio/vhost-user: dynamically assign VhostUserHostNotifiers")
Signed-off-by: Yajun Wu <yajunw@nvidia.com>
Acked-by: Parav Pandit <parav@nvidia.com>
Message-Id: <20221018023651.1359420-1-yajunw@nvidia.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/virtio/vhost-user.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 03415b6c95..d256ce589b 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -1543,6 +1543,11 @@ static VhostUserHostNotifier *fetch_or_create_notifier(VhostUserState *u, n = g_ptr_array_index(u->notifiers, idx); if (!n) { + /* + * In case notification arrive out-of-order, + * make room for current index. + */ + g_ptr_array_remove_index(u->notifiers, idx); n = g_new0(VhostUserHostNotifier, 1); n->idx = idx; g_ptr_array_insert(u->notifiers, idx, n); |