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
