Vladimir Sementsov-Ogievskiy <[email protected]> writes: > 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.
Use case? > 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. Suggest # Return the devices that support backend-transfer migration. > +# > +# Features: > +# > +# @unstable: The command is experimental. The conventional text ist "This 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); > +} @errp is useless in this patch: the only caller passes NULL. Took me a minute to check it doesn't remain useless. The next patch puts it to use. > + > +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);
