Re: [PATCH RFC v2 09/13] hw/virtio/vhost-user: add shadow virtqueues and eventfd intercepts
Connor Kite <[email protected]>
| Newsgroups | dev.linux.lists.virtio-fs,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CA+spn3qzO_d5n9AOLyhRRu1Tz-ANyh5OfQJgCJP4Dn1+wDptug@mail.gmail.com> |
On Tue, Aug 18, 2026 at 5:35 AM Akihiko Odaki <[email protected]> wrote: > > > A whitespace problem remains here. > Got it! This is fixed now > > } IsolationModeCtx; > > > > struct vhost_user { > > @@ -1128,15 +1130,38 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, > > return 0; > > } > > > > -static void cleanup_isolation_regions(struct vhost_dev *dev) > > +static void vhost_user_svq_cleanup(struct vhost_user *u, bool reset) > > +{ > > + VhostShadowVirtqueue *svq; > > + for (int i = 0; i < u->iso_mem_ctx.shadow_vqs->len; i++) { > > + svq = g_ptr_array_index(u->iso_mem_ctx.shadow_vqs, i); > > + vhost_svq_stop(svq); > > + event_notifier_cleanup(&svq->hdev_call); > > + event_notifier_cleanup(&svq->hdev_kick); > > + } > > + > > + if (!reset) { > > + g_ptr_array_free(u->iso_mem_ctx.shadow_vqs, true); > > + } > > +} > > + > > +static void cleanup_isolation_regions(struct vhost_dev *dev, bool reset) > > { > > struct vhost_user *u = dev->opaque; > > if (u->iso_mem_ctx.shared_mem_addr) { > > If vhost_dev_init() fails after vhost_user_init_svq(), shadow_vqs is > present but shared_mem_addr is not because init_isolation_regions() is > not called yet. shadow_vqs will be leaked then. > Good catch! The call to vhost_user_svq_cleanup will be moved out of the conditional statement so it always runs during cleanup. I also realized that it is possible for an error to occur after the call to qemu_memfd_alloc but before the iova tree is allocated, so I am adding a check before calling vhost_iova_tree_delete. > > + vhost_user_svq_cleanup(u, reset); > > vhost_iova_tree_delete(u->iso_mem_ctx.tree); > > qemu_memfd_free(u->iso_mem_ctx.shared_mem_addr, > > u->iso_mem_ctx.size, > > u->iso_mem_ctx.fd); > > + > > + GPtrArray *temp = u->iso_mem_ctx.shadow_vqs; > > This is a mixed declaration prohibited in docs/devel/style.rst Got it! I will fix this. > > > memset(&u->iso_mem_ctx, 0, sizeof(IsolationModeCtx)); > > + > > + if (!reset) { > > This condition is inverted. When reset is true, vhost_user_svq_cleanup() > retains the array so the pointer to it should be kept. > You are right! This is now fixed ... > > static int vhost_user_set_vring_kick(struct vhost_dev *dev, > > struct vhost_vring_file *file) > > { > > - int ret = vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file); > > + struct vhost_user *u = dev->opaque; > > + int svq_idx = file->index - dev->vq_index; > > + VhostShadowVirtqueue *svq = NULL; > > + struct vhost_vring_file vr_file = *file; > > + int ret; > > + > > + vhost_user_get_vq_index(dev, file->index); /* bounds checking */ > > + > > + if (u->user->memory_isolation) { > > + svq = g_ptr_array_index(u->iso_mem_ctx.shadow_vqs, svq_idx); > > + vhost_svq_set_svq_kick_fd(svq, file->fd); > > The svq->svq_kick EventNotifier is left set in the error paths. > I did not want to close the svq_kick notifier, since it shares its fd with the host notifier in the underlying vq, and closing that from here might be unexpected. However, a safer alternative is probably to call vhost_svq_set_svq_kck_fd with -1 to simply unbind the notifier, which I suspect is what you are actually recommending here. > Regards, > Akihiko Odaki > ... > > @@ -1769,7 +1835,35 @@ static int vhost_user_set_vring_kick(struct vhost_dev *dev, > > static int vhost_user_set_vring_call(struct vhost_dev *dev, > > struct vhost_vring_file *file) > > { > > - return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file); > > + struct vhost_user *u = dev->opaque; > > + int svq_idx = file->index - dev->vq_index; > > + VhostShadowVirtqueue *svq = NULL; > > + struct vhost_vring_file vr_file = *file; > > + int ret; > > + > > + vhost_user_get_vq_index(dev, file->index); /* bounds checking */ > > + > > + if (u->user->memory_isolation) { > > + svq = g_ptr_array_index(u->iso_mem_ctx.shadow_vqs, svq_idx); > > + vhost_svq_set_svq_call_fd(svq, file->fd); > > + > > + if (file->fd != -1) { > > + if (!svq->hdev_call.initialized) { > > + ret = event_notifier_init(&svq->hdev_call, 0); > > + if (ret < 0) { > > + event_notifier_cleanup(&svq->hdev_call); > > + error_report("Failed to create call event notifier"); > > + return ret; > > + } > > + } > > + > > + vr_file.fd = event_notifier_get_fd(&svq->hdev_call); > > + } else { > > + event_notifier_cleanup(&svq->hdev_call); > > + } > > + } > > + > > + return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, &vr_file); > > Clean up svq->hdev_call when this fails. > Did you mean cleanup svq->svq_call, similar to your feedback on svq->svq_kick? I believe svq->hdev_call already gets cleaned up on failure. I'll go ahead and add a call to vhost_svq_set_svq_call_fd with fd=-1 here as well. Thank you! Connor