On 10/7/26 6:37 PM, Akihiko Odaki wrote:
> On 2026/10/07 17:40, Andrey Drobyshev wrote:
>> vhost_dev_cleanup() closes the backend FD, but that doesn't release the
>> device ownership taken with VHOST_SET_OWNER if the same file is open
>> elsewhere.  That's the case on a CPR target: the source keeps the FD,
>> so if the target fails after SET_OWNER, either inside vhost_dev_init()
>> or later in its caller, the ownership stays with the target.  Once the
>> source is resumed it can't take the device back, SET_OWNER fails with
>> EBUSY.
>>
>> Track the ownership with a new 'owner' flag in struct vhost_dev, set and
>> cleared by vhost_dev_set_owner() and vhost_dev_reset_owner(), and issue
>> VHOST_RESET_OWNER in vhost_dev_cleanup() if it's set, as the common
>> teardown for all those paths.  That should be safe in any case: the kernel
>> refuses it from a non-owner, and an owner is about to close the FD anyway.
>>
>> Reported-by: Akihiko Odaki <[email protected]>
>> Suggested-by: Stefano Garzarella <[email protected]>
>> Signed-off-by: Andrey Drobyshev <[email protected]>
>> ---
>>   hw/virtio/vhost.c         | 24 ++++++++++++++++++++++--
>>   include/hw/virtio/vhost.h |  5 +++++
>>   2 files changed, 27 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
>> index c01ccc800cb..3432b9a43c8 100644
>> --- a/hw/virtio/vhost.c
>> +++ b/hw/virtio/vhost.c
>> @@ -1705,20 +1705,32 @@ int vhost_dev_init_backend(struct vhost_dev *hdev, 
>> void *opaque,
>>   
>>   int vhost_dev_set_owner(struct vhost_dev *hdev)
>>   {
>> +    int r;
>> +
>>       assert(hdev->vhost_ops);
>>       if (!hdev->vhost_ops->vhost_set_owner) {
>>           return -ENOSYS;
>>       }
>> -    return hdev->vhost_ops->vhost_set_owner(hdev);
>> +    r = hdev->vhost_ops->vhost_set_owner(hdev);
>> +    if (!r) {
>> +        hdev->owner = true;
>> +    }
>> +    return r;
>>   }
>>   
>>   int vhost_dev_reset_owner(struct vhost_dev *hdev)
>>   {
>> +    int r;
>> +
>>       assert(hdev->vhost_ops);
>>       if (!hdev->vhost_ops->vhost_reset_owner) {
>>           return -ENOSYS;
>>       }
>> -    return hdev->vhost_ops->vhost_reset_owner(hdev);
>> +    r = hdev->vhost_ops->vhost_reset_owner(hdev);
>> +    if (!r) {
>> +        hdev->owner = false;
>> +    }
>> +    return r;
>>   }
>>   
>>   int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
>> @@ -1864,6 +1876,14 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
>>       g_free(hdev->mem);
>>       g_free(hdev->mem_sections);
>>       if (hdev->vhost_ops) {
>> +        /*
>> +         * Release the device ownership if we hold it.  Needed e.g. for
>> +         * failing CPR target, so the source can re-acquire it.
>> +         */
>> +        if (hdev->owner && vhost_dev_reset_owner(hdev) < 0) {
>> +            error_report("vhost: cannot release device ownership on "
>> +                         "cleanup");
> 
> Normal teardown produces a misleading ownership error. vhost-user and 
> vDPA set owner=true but do not implement vhost_reset_owner, so the 
> helper returns -ENOSYS. The new cleanup diagnostic therefore reports 
> ordinary cleanup as a failure. I reproduced the message with the 
> following test command even though it passes:
> 
> meson test -C build --no-rebuild -v \
>    --suite qtest-x86_64 '*qos-test*' \
>    --test-args '-p 
> /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-net-pci/virtio-net/virtio-net-tests/vhost-user/read-guest-mem/memfd'
> 
> Regards,
> Akihiko Odaki
Ah, looks you're right again.  I just noticed that the error goes silent
here and we better somehow flag it, even though we can't do anything
about it at this point.  I guess we can just ignore the cases where
either the backend doesn't have the reset_owner() callback (in this case
we get -ENOSYS) and when the kernel driver itself doesn't support
RESET_OWNER operation (in this case we get -ENOTTY).  So smth like:

    r = vhost_dev_reset_owner(hdev);
    if (r < 0 && r != -ENOSYS && r != -ENOTTY) {
        error_report(...);
    }

I'll post this if you don't have any objections.

Thanks,
Andrey

Reply via email to