Markus Armbruster <[email protected]> writes:
> Fabiano Rosas <[email protected]> writes:
>
>> Add capabilities to MigrationParameters. This structure will hold all
>> migration options. Capabilities will go away in the next patch.
>>
>> From this point on, both QMP and HMP versions of
>> migrate-set-parameters and query-migrate-parameters gain the ability
>> to work with capabilities.
>>
>> With MigrationParameters now having members for each capability, the
>> migration capabilities commands (query-migrate-capabilities,
>> migrate-set-capabilities) will soon be deprecated. Add a set of
>> helpers to convert between the old MigrationCapability representation
>> and the new representation as members of MigrationParameters.
>>
>> Acked-by: Peter Xu <[email protected]>
>> Signed-off-by: Fabiano Rosas <[email protected]>
>> ---
>> migration/migration.c | 8 +++
>> migration/options.c | 127 ++++++++++++++++++++++++++++++++++++++++++
>> migration/options.h | 5 ++
>> qapi/migration.json | 118 ++++++++++++++++++++++++++++++++++++++-
>> 4 files changed, 255 insertions(+), 3 deletions(-)
>>
>> diff --git a/migration/migration.c b/migration/migration.c
>> index dab282dd2f3..c8e7e86ea05 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -4086,6 +4086,14 @@ static bool migration_object_check(MigrationState
>> *ms, Error **errp)
>> return false;
>> }
>>
>> + /*
>> + * FIXME: Temporarily while -global capabilties are still using
>> + * s->capabilities. Will be gone by the end of the series.
>> + */
>> + for (int i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
>> + migrate_capability_set_compat(&ms->parameters, i,
>> ms->capabilities[i]);
>> + }
>> +
>> return migrate_caps_check(old_caps, ms->capabilities, errp);
>> }
>>
>> diff --git a/migration/options.c b/migration/options.c
>> index f988b181f0e..7c638e204a1 100644
>> --- a/migration/options.c
>> +++ b/migration/options.c
>> @@ -778,6 +778,108 @@ bool migrate_caps_check(bool *old_caps, bool
>> *new_caps, Error **errp)
>> return true;
>> }
>>
>> +static bool *migrate_capability_get_addr(MigrationParameters *params, int i)
>> +{
>> + bool *cap_addr = NULL;
>> +
>> + switch (i) {
>> + case MIGRATION_CAPABILITY_XBZRLE:
>> + cap_addr = ¶ms->xbzrle;
>> + break;
>> + case MIGRATION_CAPABILITY_RDMA_PIN_ALL:
>> + cap_addr = ¶ms->rdma_pin_all;
>> + break;
>> + case MIGRATION_CAPABILITY_AUTO_CONVERGE:
>> + cap_addr = ¶ms->auto_converge;
>> + break;
>> + case MIGRATION_CAPABILITY_EVENTS:
>> + cap_addr = ¶ms->events;
>> + break;
>> + case MIGRATION_CAPABILITY_POSTCOPY_RAM:
>> + cap_addr = ¶ms->postcopy_ram;
>> + break;
>> + case MIGRATION_CAPABILITY_X_COLO:
>> + cap_addr = ¶ms->x_colo;
>> + break;
>> + case MIGRATION_CAPABILITY_RELEASE_RAM:
>> + cap_addr = ¶ms->release_ram;
>> + break;
>> + case MIGRATION_CAPABILITY_RETURN_PATH:
>> + cap_addr = ¶ms->return_path;
>> + break;
>> + case MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER:
>> + cap_addr = ¶ms->pause_before_switchover;
>> + break;
>> + case MIGRATION_CAPABILITY_MULTIFD:
>> + cap_addr = ¶ms->multifd;
>> + break;
>> + case MIGRATION_CAPABILITY_DIRTY_BITMAPS:
>> + cap_addr = ¶ms->dirty_bitmaps;
>> + break;
>> + case MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME:
>> + cap_addr = ¶ms->postcopy_blocktime;
>> + break;
>> + case MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE:
>> + cap_addr = ¶ms->late_block_activate;
>> + break;
>> + case MIGRATION_CAPABILITY_X_IGNORE_SHARED:
>> + cap_addr = ¶ms->x_ignore_shared;
>> + break;
>> + case MIGRATION_CAPABILITY_VALIDATE_UUID:
>> + cap_addr = ¶ms->validate_uuid;
>> + break;
>> + case MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT:
>> + cap_addr = ¶ms->background_snapshot;
>> + break;
>> + case MIGRATION_CAPABILITY_ZERO_COPY_SEND:
>> + cap_addr = ¶ms->zero_copy_send;
>> + break;
>> + case MIGRATION_CAPABILITY_POSTCOPY_PREEMPT:
>> + cap_addr = ¶ms->postcopy_preempt;
>> + break;
>> + case MIGRATION_CAPABILITY_SWITCHOVER_ACK:
>> + cap_addr = ¶ms->switchover_ack;
>> + break;
>> + case MIGRATION_CAPABILITY_DIRTY_LIMIT:
>> + cap_addr = ¶ms->dirty_limit;
>> + break;
>> + case MIGRATION_CAPABILITY_MAPPED_RAM:
>> + cap_addr = ¶ms->mapped_ram;
>> + break;
>> + default:
>> + g_assert_not_reached();
>> + }
>
> I'd use an array instead of a switch. Matter of taste.
>
>> +
>> + return cap_addr;
>> +}
>> +
>> +/* Compatibility for code that reads capabilities in a loop */
>> +bool migrate_capability_get_compat(MigrationParameters *params, int i)
>> +{
>> + return *(migrate_capability_get_addr(params, i));
>> +}
>> +
>> +/* Compatibility for code that writes capabilities in a loop */
>> +void migrate_capability_set_compat(MigrationParameters *params, int i, bool
>> val)
>> +{
>> + *(migrate_capability_get_addr(params, i)) = val;
>> +}
>> +
>> +/*
>> + * Set capabilities for compatibility with the old
>> + * migrate-set-capabilities command.
>> + */
>> +void migrate_capabilities_set_compat(MigrationParameters *params,
>> + MigrationCapabilityStatusList *caps)
>> +{
>> + MigrationCapabilityStatusList *cap;
>> +
>> + for (cap = caps; cap; cap = cap->next) {
>> + migrate_capability_set_compat(params, cap->value->capability,
>> + cap->value->state);
>> + }
>> +}
>> +
>> MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
>> {
>> MigrationCapabilityStatusList *head = NULL, **tail = &head;
>> @@ -819,6 +921,8 @@ void
>> qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
>> for (cap = params; cap; cap = cap->next) {
>> s->capabilities[cap->value->capability] = cap->value->state;
>> }
>> +
>> + migrate_capabilities_set_compat(&s->parameters, params);
>> }
>>
>> /* parameters */
>> @@ -1141,6 +1245,15 @@ static void
>> migrate_mark_all_params_present(MigrationParameters *p)
>> &p->has_x_vcpu_dirty_limit_period, &p->has_vcpu_dirty_limit,
>> &p->has_mode, &p->has_zero_page_detection, &p->has_direct_io,
>> &p->has_x_rdma_chunk_size, &p->has_cpr_exec_command,
>> + &p->has_xbzrle, &p->has_rdma_pin_all,
>> + &p->has_auto_converge, &p->has_events,
>> + &p->has_postcopy_ram, &p->has_x_colo, &p->has_release_ram,
>> + &p->has_return_path, &p->has_pause_before_switchover,
>> &p->has_multifd,
>> + &p->has_dirty_bitmaps, &p->has_postcopy_blocktime,
>> + &p->has_late_block_activate, &p->has_x_ignore_shared,
>> + &p->has_validate_uuid, &p->has_background_snapshot,
>> + &p->has_zero_copy_send, &p->has_postcopy_preempt,
>> + &p->has_switchover_ack, &p->has_dirty_limit, &p->has_mapped_ram,
>> };
>>
>> for (int i = 0; i < ARRAY_SIZE(has_fields); i++) {
>> @@ -1465,6 +1578,20 @@ void qmp_migrate_set_parameters(MigrationParameters
>> *input, Error **errp)
>> tls_opt_to_str(input->tls_hostname);
>> tls_opt_to_str(input->tls_authz);
>>
>> + /*
>> + * FIXME: Temporarily while migrate_caps_check is not
>> + * converted to look at s->parameters. Will be gone the end of
>> + * the series.
>> + */
>> + bool new_caps[MIGRATION_CAPABILITY__MAX] = { 0 };
>> + for (int i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
>> + new_caps[i] = migrate_capability_get_compat(cur, i);
>> + }
>> + if (!migrate_caps_check(migrate_get_current()->capabilities, new_caps,
>> + errp)) {
>> + return;
>> + }
>> +
>> /* merge input on top of current */
>> if (!migrate_params_merge(cur, input, &new, errp)) {
>> return;
>> diff --git a/migration/options.h b/migration/options.h
>> index c7da2d0b5b0..eedd1aa1f93 100644
>> --- a/migration/options.h
>> +++ b/migration/options.h
>> @@ -94,4 +94,9 @@ uint64_t migrate_rdma_chunk_size(void);
>> bool migrate_params_check(MigrationParameters *params, Error **errp);
>> void migrate_params_init(MigrationParameters *params);
>> bool migrate_params_free(MigrationParameters *params, Error **errp);
>> +bool migrate_capability_get_compat(MigrationParameters *params, int i);
>> +void migrate_capability_set_compat(MigrationParameters *params, int i,
>> + bool val);
>> +void migrate_capabilities_set_compat(MigrationParameters *params,
>> + MigrationCapabilityStatusList *caps);
>> #endif
>> diff --git a/qapi/migration.json b/qapi/migration.json
>> index 78c6e933cf1..7952ef44db9 100644
>> --- a/qapi/migration.json
>> +++ b/qapi/migration.json
>> @@ -976,10 +976,101 @@
>> # Must be set to the same value on both source and destination
>> # before migration starts. (Since 11.1)
>> #
>> +# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length
>> +# Encoding). This feature allows us to minimize migration traffic
>> +# for certain work loads, by sending compressed difference of the
>> +# pages
>> +#
>> +# @rdma-pin-all: Controls whether or not the entire VM memory
>> +# footprint is mlock()'d on demand or all at once. Refer to
>> +# docs/rdma.txt for usage. Disabled by default. (since 2.0)
>> +#
>> +# @events: Generate events for each migration state change.
>> +# (since 2.4)
>> +#
>> +# @auto-converge: If enabled, QEMU will automatically throttle down
>> +# the guest to speed up convergence of RAM migration. (since 1.6)
>> +#
>> +# @postcopy-ram: Start executing on the migration target before all of
>> +# RAM has been migrated, pulling the remaining pages along as
>> +# needed. The capacity must have the same setting on both source
>> +# and target or migration will not even start. **Note:** If the
>> +# migration fails during postcopy the VM will fail. (since 2.6)
>> +#
>> +# @x-colo: If enabled, migration will never end, and the state of the
>> +# VM on the primary side will be migrated continuously to the VM
>> +# on secondary side, this process is called COarse-Grain LOck
>> +# Stepping (COLO) for Non-stop Service. (since 2.8)
>> +#
>> +# @release-ram: If enabled, QEMU will free the migrated ram pages on
>> +# the source during postcopy-ram migration. (since 2.9)
>> +#
>> +# @return-path: If enabled, migration will use the return path even
>> +# for precopy. (since 2.10)
>> +#
>> +# @pause-before-switchover: Pause outgoing migration before
>> +# serialising device state and before disabling block IO.
>> +# (since 2.11)
>> +#
>> +# @multifd: Use more than one fd for migration. (since 4.0)
>> +#
>> +# @dirty-bitmaps: If enabled, QEMU will migrate named dirty bitmaps.
>> +# (since 2.12)
>> +#
>> +# @postcopy-blocktime: Calculate downtime for postcopy live migration.
>> +# (since 3.0)
>> +#
>> +# @late-block-activate: If enabled, the destination will not activate
>> +# block devices (and thus take locks) immediately at the end of
>> +# migration. (since 3.0)
>> +#
>> +# @x-ignore-shared: If enabled, QEMU will not migrate shared memory
>> +# that is accessible on the destination machine. (since 4.0)
>> +#
>> +# @validate-uuid: Send the UUID of the source to allow the destination
>> +# to ensure it is the same. (since 4.2)
>> +#
>> +# @background-snapshot: If enabled, the migration stream will be a
>> +# snapshot of the VM exactly at the point when the migration
>> +# procedure starts. The VM RAM is saved with running VM.
>> +# (since 6.0)
>> +#
>> +# @zero-copy-send: Controls behavior on sending memory pages on
>> +# migration. When true, enables a zero-copy mechanism for sending
>> +# memory pages, if host supports it. Requires that QEMU be
>> +# permitted to use locked memory for guest RAM pages. (since 7.1)
>> +#
>> +# @postcopy-preempt: If enabled, the migration process will allow
>> +# postcopy requests to preempt precopy stream, so postcopy
>> +# requests will be handled faster. This is a performance feature
>> +# and should not affect the correctness of postcopy migration.
>> +# (since 7.1)
>> +#
>> +# @switchover-ack: If enabled, migration will not stop the source VM
>> +# and complete the migration until an ACK is received from the
>> +# destination that it's OK to do so. Exactly when this ACK is
>> +# sent depends on the migrated devices that use this feature. For
>> +# example, a device can use it to make sure some of its data is
>> +# sent and loaded in the destination before doing switchover.
>> +# This can reduce downtime if devices that support this capability
>> +# are present. 'return-path' capability must be enabled to use
>> +# it. (since 8.1)
>> +#
>> +# @dirty-limit: If enabled, migration will throttle vCPUs as needed to
>> +# keep their dirty page rate within @vcpu-dirty-limit. This can
>> +# improve responsiveness of large guests during live migration,
>> +# and can result in more stable read performance. Requires KVM
>> +# with accelerator property "dirty-ring-size" set. (Since 8.1)
>> +#
>> +# @mapped-ram: Migrate using fixed offsets in the migration file for
>> +# each RAM page. Requires a migration URI that supports seeking,
>> +# such as a file. (since 9.0)
>> +#
>> # Features:
>> #
>> -# @unstable: Members @x-checkpoint-delay, @x-rdma-chunk-size, and
>> -# @x-vcpu-dirty-limit-period are experimental.
>> +# @unstable: Members @x-checkpoint-delay, @x-vcpu-dirty-limit-period,
>> +# @x-colo, @x-ignore-shared and @x-rdma-chunk-size are
>> +# experimental.
>
> This isn't a clean copy from MigrationCapability. Why?
>
I blundered.
>> #
>> # Since: 2.4
>> ##
>> @@ -1017,7 +1108,28 @@
>> '*direct-io': 'bool',
>> '*x-rdma-chunk-size': { 'type': 'uint64',
>> 'features': [ 'unstable' ] },
>> - '*cpr-exec-command': [ 'str' ]} }
>> + '*cpr-exec-command': [ 'str' ],
>> + '*xbzrle': 'bool',
>> + '*rdma-pin-all': 'bool',
>> + '*auto-converge': 'bool',
>> + '*events': 'bool',
>> + '*postcopy-ram': 'bool',
>> + '*x-colo': { 'type': 'bool', 'features': [ 'unstable' ] },
>> + '*release-ram': 'bool',
>> + '*return-path': 'bool',
>> + '*pause-before-switchover': 'bool',
>> + '*multifd': 'bool',
>> + '*dirty-bitmaps': 'bool',
>> + '*postcopy-blocktime': 'bool',
>> + '*late-block-activate': 'bool',
>> + '*x-ignore-shared': { 'type': 'bool', 'features': [ 'unstable'
>> ] },
>> + '*validate-uuid': 'bool',
>> + '*background-snapshot': 'bool',
>> + '*zero-copy-send': 'bool',
>> + '*postcopy-preempt': 'bool',
>> + '*switchover-ack': 'bool',
>> + '*dirty-limit': 'bool',
>> + '*mapped-ram': 'bool' } }
>>
>> ##
>> # @query-migrate-parameters: