On 2026/10/01 17:25, 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.
Issue VHOST_RESET_OWNER in vhost_dev_cleanup() as the common teardown
for all those paths. That's safe in any case: the kernel refuses it
from a non-owner, and an owner is about to close the FD anyway.
There is one minor counterexample: if a second netdev receives a
duplicate of an already-used vhost-net FD, initialization fails with
EBUSY, but cleanup then resets the first device.
Regards,
Akihiko Odaki
Reported-by: Akihiko Odaki <[email protected]>
Suggested-by: Stefano Garzarella <[email protected]>
Signed-off-by: Andrey Drobyshev <[email protected]>
---
hw/virtio/vhost.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index c01ccc800cb..0bc6a0b6b00 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1864,6 +1864,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
g_free(hdev->mem);
g_free(hdev->mem_sections);
if (hdev->vhost_ops) {
+ /*
+ * Issue RESET_OWNER to drop device ownership. Needed e.g. for
+ * failing CPR target, so the source can re-acquire it.
+ * Should be a no-op for non-owner, and harmless for an owner who's
+ * about to close the device backend.
+ */
+ vhost_dev_reset_owner(hdev);
hdev->vhost_ops->vhost_cleanup(hdev);
}
assert(!hdev->log);