diff mbox series

[RFC,V1,05/12] iommufd: preserve device fd

Message ID 1721502937-87102-6-git-send-email-steven.sistare@oracle.com (mailing list archive)
State New, archived
Headers show
Series Live update: iommufd | expand

Commit Message

Steven Sistare July 20, 2024, 7:15 p.m. UTC
Save the iommu and vfio device fd in CPR state when it is created, and fetch
the fd from that state after CPR.  Save the devid as the fd id.  Remember
that the fd was reused, for subsequent patches.

Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
---
 backends/iommufd.c       | 12 +++++++++++-
 hw/vfio/iommufd.c        | 17 ++++++++++++++++-
 include/sysemu/iommufd.h |  1 +
 3 files changed, 28 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/backends/iommufd.c b/backends/iommufd.c
index fc37386..4bdbad2 100644
--- a/backends/iommufd.c
+++ b/backends/iommufd.c
@@ -16,6 +16,7 @@ 
 #include "qemu/module.h"
 #include "qom/object_interfaces.h"
 #include "qemu/error-report.h"
+#include "migration/cpr.h"
 #include "monitor/monitor.h"
 #include "trace.h"
 #include <sys/ioctl.h>
@@ -77,11 +78,17 @@  bool iommufd_backend_connect(IOMMUFDBackend *be, const char *name, Error **errp)
     int fd;
 
     if (be->owned && !be->users) {
-        fd = qemu_open_old("/dev/iommu", O_RDWR);
+        g_autofree char *iname = g_strdup_printf("%s_iommu", name);
+        fd = cpr_find_fd(iname, 0);
+        be->reused = (fd >= 0);
+        if (!be->reused) {
+            fd = qemu_open_old("/dev/iommu", O_RDWR);
+        }
         if (fd < 0) {
             error_setg_errno(errp, errno, "/dev/iommu opening failed");
             return false;
         }
+        cpr_resave_fd(iname, 0, fd);
         be->fd = fd;
     }
     be->users++;
@@ -92,6 +99,8 @@  bool iommufd_backend_connect(IOMMUFDBackend *be, const char *name, Error **errp)
 
 void iommufd_backend_disconnect(IOMMUFDBackend *be, const char *name)
 {
+    g_autofree char *iname = g_strdup_printf("%s_iommu", name);
+
     if (!be->users) {
         goto out;
     }
@@ -101,6 +110,7 @@  void iommufd_backend_disconnect(IOMMUFDBackend *be, const char *name)
         be->fd = -1;
     }
 out:
+    cpr_delete_fd(iname, 0);
     trace_iommufd_backend_disconnect(be->fd, be->users);
 }
 
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 255966a..cefc9e0 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -24,6 +24,7 @@ 
 #include "sysemu/reset.h"
 #include "qemu/cutils.h"
 #include "qemu/chardev_open.h"
+#include "migration/cpr.h"
 #include "pci.h"
 
 static int iommufd_cdev_map(const VFIOContainerBase *bcontainer, hwaddr iova,
@@ -84,6 +85,11 @@  static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
         goto err_kvm_device_add;
     }
 
+    if (vbasedev->reused) {
+        /* Already bound, and devid was set in iommufd_cdev_attach */
+        goto skip_bind;
+    }
+
     /* Bind device to iommufd */
     bind.iommufd = iommufd->fd;
     if (ioctl(vbasedev->fd, VFIO_DEVICE_BIND_IOMMUFD, &bind)) {
@@ -95,6 +101,8 @@  static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
     vbasedev->devid = bind.out_devid;
     trace_iommufd_cdev_connect_and_bind(bind.iommufd, vbasedev->name,
                                         vbasedev->fd, vbasedev->devid);
+
+skip_bind:
     return true;
 err_bind:
     iommufd_cdev_kvm_device_del(vbasedev);
@@ -305,13 +313,18 @@  static bool iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
         VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD));
 
     if (vbasedev->fd < 0) {
-        devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp);
+        devfd = cpr_find_fd_any(vbasedev->name, (int *)&vbasedev->devid);
+        vbasedev->reused = (devfd >= 0);
+        if (!vbasedev->reused) {
+            devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp);
+        }
         if (devfd < 0) {
             return false;
         }
         vbasedev->fd = devfd;
     } else {
         devfd = vbasedev->fd;
+        vbasedev->reused = false;
     }
 
     if (!iommufd_cdev_connect_and_bind(vbasedev, errp)) {
@@ -413,6 +426,7 @@  found_container:
     vbasedev->bcontainer = bcontainer;
     QLIST_INSERT_HEAD(&bcontainer->device_list, vbasedev, container_next);
     QLIST_INSERT_HEAD(&vfio_device_list, vbasedev, global_next);
+    cpr_resave_fd(vbasedev->name, vbasedev->devid, devfd);
 
     trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev->num_irqs,
                                    vbasedev->num_regions, vbasedev->flags);
@@ -452,6 +466,7 @@  static void iommufd_cdev_detach(VFIODevice *vbasedev)
     iommufd_cdev_container_destroy(container);
     vfio_put_address_space(space);
 
+    cpr_delete_fd(vbasedev->name, vbasedev->devid);
     iommufd_cdev_unbind_and_disconnect(vbasedev);
     close(vbasedev->fd);
 }
diff --git a/include/sysemu/iommufd.h b/include/sysemu/iommufd.h
index aa195d1..6955ebd 100644
--- a/include/sysemu/iommufd.h
+++ b/include/sysemu/iommufd.h
@@ -32,6 +32,7 @@  struct IOMMUFDBackend {
     /*< protected >*/
     int fd;            /* /dev/iommu file descriptor */
     bool owned;        /* is the /dev/iommu opened internally */
+    bool reused;       /* fd is reused after CPR */
     uint32_t users;
 
     /*< public >*/