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.
In this commit we introduce a migration parameter, which pick devices for backend-transfer migration in context of next outgoing or incoming migration. Of course, user is responsible to pick same set of devices on source and target. QMP command query-backend-transfer-support command may help to prepare such set as intersection of query-backend-transfer-support results on source and target. With this commit, no device yet support backend-transfer, so passing something other then empty list to backend-transfer migration parameter will fail. Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]> --- include/hw/qdev-core.h | 3 +++ include/migration/misc.h | 2 ++ migration/options.c | 31 +++++++++++++++++++++++++++++++ qapi/migration.json | 35 +++++++++++++++++++++++++++++------ system/qdev-monitor.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 6 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 0551fbaa6c..9ed0b3f04d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -1168,4 +1168,7 @@ typedef enum MachineInitPhase { bool phase_check(MachineInitPhase phase); void phase_advance(MachineInitPhase phase); +bool migrate_backend_transfer(DeviceState *dev); +bool migrate_backend_transfer_check_list(const strList *list, Error **errp); + #endif diff --git a/include/migration/misc.h b/include/migration/misc.h index 592b93021e..7f931bed17 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -152,4 +152,6 @@ bool multifd_device_state_save_thread_should_exit(void); void multifd_abort_device_state_save_threads(void); bool multifd_join_device_state_save_threads(void); +const strList *migrate_backend_transfer_list(void); + #endif diff --git a/migration/options.c b/migration/options.c index 5183112775..1644728ed7 100644 --- a/migration/options.c +++ b/migration/options.c @@ -13,6 +13,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qapi/util.h" #include "exec/target_page.h" #include "qapi/clone-visitor.h" #include "qapi/error.h" @@ -24,6 +25,7 @@ #include "migration/colo.h" #include "migration/cpr.h" #include "migration/misc.h" +#include "migration/options.h" #include "migration.h" #include "migration-stats.h" #include "qemu-file.h" @@ -262,6 +264,12 @@ bool migrate_mapped_ram(void) return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM]; } +const strList *migrate_backend_transfer_list(void) +{ + MigrationState *s = migrate_get_current(); + return s->parameters.backend_transfer; +} + bool migrate_ignore_shared(void) { MigrationState *s = migrate_get_current(); @@ -963,6 +971,12 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->cpr_exec_command = QAPI_CLONE(strList, s->parameters.cpr_exec_command); + if (s->parameters.backend_transfer) { + params->has_backend_transfer = true; + params->backend_transfer = QAPI_CLONE(strList, + s->parameters.backend_transfer); + } + return params; } @@ -997,6 +1011,7 @@ void migrate_params_init(MigrationParameters *params) params->has_zero_page_detection = true; params->has_direct_io = true; params->has_cpr_exec_command = true; + params->has_backend_transfer = true; } /* @@ -1183,6 +1198,11 @@ bool migrate_params_check(MigrationParameters *params, Error **errp) return false; } + if (params->has_backend_transfer && + !migrate_backend_transfer_check_list(params->backend_transfer, errp)) { + return false; + } + return true; } @@ -1305,6 +1325,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params, if (params->has_cpr_exec_command) { dest->cpr_exec_command = params->cpr_exec_command; } + + if (params->has_backend_transfer) { + dest->backend_transfer = params->backend_transfer; + } } static void migrate_params_apply(MigrateSetParameters *params, Error **errp) @@ -1443,6 +1467,13 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) s->parameters.cpr_exec_command = QAPI_CLONE(strList, params->cpr_exec_command); } + + if (params->has_backend_transfer) { + qapi_free_strList(s->parameters.backend_transfer); + + s->parameters.backend_transfer = QAPI_CLONE(strList, + params->backend_transfer); + } } void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) diff --git a/qapi/migration.json b/qapi/migration.json index be0f3fcc12..9478c4ddab 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -951,9 +951,15 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: List of devices (IDs or QOM paths) for +# backend-transfer migration. When enabled, device backends +# including opened fds will be passed to the destination in the +# migration channel (which must be a UNIX domain socket). Default +# is no backend-transfer migration. (Since 10.2) +# # Features: # -# @unstable: Members @x-checkpoint-delay and +# @unstable: Members @backend-transfer, @x-checkpoint-delay and # @x-vcpu-dirty-limit-period are experimental. # # Since: 2.4 @@ -978,7 +984,8 @@ 'mode', 'zero-page-detection', 'direct-io', - 'cpr-exec-command'] } + 'cpr-exec-command', + { 'name': 'backend-transfer', 'features': ['unstable'] } ] } ## # @MigrateSetParameters: @@ -1137,9 +1144,15 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: List of devices (IDs or QOM paths) for +# backend-transfer migration. When enabled, device backends +# including opened fds will be passed to the destination in the +# migration channel (which must be a UNIX domain socket). Default +# is no backend-transfer migration. (Since 10.2) +# # Features: # -# @unstable: Members @x-checkpoint-delay and +# @unstable: Members @backend-transfer, @x-checkpoint-delay and # @x-vcpu-dirty-limit-period are experimental. # # TODO: either fuse back into `MigrationParameters`, or make @@ -1179,7 +1192,9 @@ '*mode': 'MigMode', '*zero-page-detection': 'ZeroPageDetection', '*direct-io': 'bool', - '*cpr-exec-command': [ 'str' ]} } + '*cpr-exec-command': [ 'str' ], + '*backend-transfer': { 'type': [ 'str' ], + 'features': [ 'unstable' ] } } } ## # @migrate-set-parameters: @@ -1352,9 +1367,15 @@ # is @cpr-exec. The first list element is the program's filename, # the remainder its arguments. (Since 10.2) # +# @backend-transfer: List of devices (IDs or QOM paths) for +# backend-transfer migration. When enabled, device backends +# including opened fds will be passed to the destination in the +# migration channel (which must be a UNIX domain socket). Default +# is no backend-transfer migration. (Since 10.2) +# # Features: # -# @unstable: Members @x-checkpoint-delay and +# @unstable: Members @backend-transfer, @x-checkpoint-delay and # @x-vcpu-dirty-limit-period are experimental. # # Since: 2.4 @@ -1391,7 +1412,9 @@ '*mode': 'MigMode', '*zero-page-detection': 'ZeroPageDetection', '*direct-io': 'bool', - '*cpr-exec-command': [ 'str' ]} } + '*cpr-exec-command': [ 'str' ], + '*backend-transfer': { 'type': [ 'str' ], + 'features': [ 'unstable' ] } } } ## # @query-migrate-parameters: diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 9d3d961c15..549c77b2f0 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -939,6 +939,19 @@ void qmp_device_del(const char *id, Error **errp) } } +bool migrate_backend_transfer(DeviceState *dev) +{ + const strList *el = migrate_backend_transfer_list(); + + for ( ; el; el = el->next) { + if (find_device_state(el->value, false, NULL) == dev) { + return true; + } + } + + return false; +} + static bool qdev_backend_transfer_support(DeviceState *dev, Error **errp) { DeviceClass *dc = DEVICE_GET_CLASS(dev); @@ -952,6 +965,24 @@ static bool qdev_backend_transfer_support(DeviceState *dev, Error **errp) return dc->backend_transfer_support(dev, errp); } +bool migrate_backend_transfer_check_list(const strList *list, Error **errp) +{ + const strList *el = list; + + for ( ; el; el = el->next) { + DeviceState *dev = find_device_state(el->value, true, errp); + if (!dev) { + return false; + } + + if (!qdev_backend_transfer_support(dev, errp)) { + return false; + } + } + + return true; +} + static int qdev_add_if_backend_transfer_supported(Object *obj, void *opaque) { DevPathList **list = opaque; -- 2.48.1
