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
