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

Reply via email to