We are going to implement backend-transfer feature: some devices
will be able to transfer their backend through migration stream
for local migration through UNIX domain socket. For example,
virtio-net will migrate its attached TAP netdev, with all its
connected file descriptors.

Let's add a command to list supporting devices (no one for now),
together with necessary infrastructure in qdev code.

Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]>
---
 include/hw/qdev-core.h |  7 +++++++
 qapi/qdev.json         | 26 +++++++++++++++++++++++++
 system/qdev-monitor.c  | 43 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 2caa0cbd26..0551fbaa6c 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -96,6 +96,7 @@ typedef void (*DeviceReset)(DeviceState *dev);
 typedef void (*BusRealize)(BusState *bus, Error **errp);
 typedef void (*BusUnrealize)(BusState *bus);
 typedef int (*DeviceSyncConfig)(DeviceState *dev, Error **errp);
+typedef bool (*DeviceSupportBackendTransfer)(DeviceState *dev, Error **errp);
 
 /**
  * struct DeviceClass - The base class for all devices.
@@ -174,6 +175,12 @@ struct DeviceClass {
     DeviceUnrealize unrealize;
     DeviceSyncConfig sync_config;
 
+    /**
+     * @backend_transfer_support: reports support for backend-transfer
+     * migration of the device.
+     */
+    DeviceSupportBackendTransfer backend_transfer_support;
+
     /**
      * @vmsd: device state serialisation description for
      * migration/save/restore
diff --git a/qapi/qdev.json b/qapi/qdev.json
index e14a0c9259..d7e878d58d 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -188,3 +188,29 @@
 { 'command': 'device-sync-config',
   'features': [ 'unstable' ],
   'data': {'id': 'str'} }
+
+##
+# @DevPath:
+#
+# @path: the device's QOM path
+#
+# Since: 10.2
+##
+{ 'struct': 'DevPath',
+  'data': { 'path': 'str' } }
+
+##
+# @query-backend-transfer-support:
+#
+# Returns list of devices, supporting backend-transfer
+# migration.
+#
+# Features:
+#
+# @unstable: The command is experimental.
+#
+# Since: 10.2
+##
+{ 'command': 'query-backend-transfer-support',
+  'features': [ 'unstable' ],
+  'returns': [ 'DevPath' ] }
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index ec4a2394ce..9d3d961c15 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -939,6 +939,49 @@ void qmp_device_del(const char *id, Error **errp)
     }
 }
 
+static bool qdev_backend_transfer_support(DeviceState *dev, Error **errp)
+{
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+    if (!dc->backend_transfer_support) {
+        error_setg(errp, "backend-transfer is not supported for '%s'",
+                   object_get_typename(OBJECT(dev)));
+        return false;
+    }
+
+    return dc->backend_transfer_support(dev, errp);
+}
+
+static int qdev_add_if_backend_transfer_supported(Object *obj, void *opaque)
+{
+    DevPathList **list = opaque;
+    DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
+
+    if (dev != NULL && qdev_backend_transfer_support(dev, NULL)) {
+        DevPath *el = g_new(DevPath, 1);
+        *el = (DevPath) {
+            .path = g_strdup(dev->canonical_path),
+        };
+        QAPI_LIST_PREPEND(*list, el);
+    }
+
+    /* Recursively check all children */
+    object_child_foreach(obj, qdev_add_if_backend_transfer_supported, opaque);
+
+    return 0;
+}
+
+DevPathList *qmp_query_backend_transfer_support(Error **errp)
+{
+    DevPathList *result = NULL;
+    Object *peripheral = machine_get_container("peripheral");
+
+    object_child_foreach(peripheral, qdev_add_if_backend_transfer_supported,
+                         &result);
+
+    return result;
+}
+
 int qdev_sync_config(DeviceState *dev, Error **errp)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
-- 
2.48.1


Reply via email to