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.

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);

-- 
2.47.1


Reply via email to