diff mbox series

[16/18] migration: Add capabilities into MigrationParameters

Message ID 20260902221547.1812481-17-farosas@suse.de
State New
Headers show
Series migration: MigrationParameters changes | expand

Commit Message

Fabiano Rosas Sept. 2, 2026, 10:15 p.m. UTC
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 <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
 migration/migration.c |   8 +++
 migration/options.c   | 127 ++++++++++++++++++++++++++++++++++++++++++
 migration/options.h   |   5 ++
 qapi/migration.json   | 118 ++++++++++++++++++++++++++++++++++++++-
 4 files changed, 255 insertions(+), 3 deletions(-)

Comments

Markus Armbruster Sept. 4, 2026, 9:53 a.m. UTC | #1
Fabiano Rosas <farosas@suse.de> 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 <peterx@redhat.com>
> Signed-off-by: Fabiano Rosas <farosas@suse.de>
> ---
>  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 = &params->xbzrle;
> +        break;
> +    case MIGRATION_CAPABILITY_RDMA_PIN_ALL:
> +        cap_addr = &params->rdma_pin_all;
> +        break;
> +    case MIGRATION_CAPABILITY_AUTO_CONVERGE:
> +        cap_addr = &params->auto_converge;
> +        break;
> +    case MIGRATION_CAPABILITY_EVENTS:
> +        cap_addr = &params->events;
> +        break;
> +    case MIGRATION_CAPABILITY_POSTCOPY_RAM:
> +        cap_addr = &params->postcopy_ram;
> +        break;
> +    case MIGRATION_CAPABILITY_X_COLO:
> +        cap_addr = &params->x_colo;
> +        break;
> +    case MIGRATION_CAPABILITY_RELEASE_RAM:
> +        cap_addr = &params->release_ram;
> +        break;
> +    case MIGRATION_CAPABILITY_RETURN_PATH:
> +        cap_addr = &params->return_path;
> +        break;
> +    case MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER:
> +        cap_addr = &params->pause_before_switchover;
> +        break;
> +    case MIGRATION_CAPABILITY_MULTIFD:
> +        cap_addr = &params->multifd;
> +        break;
> +    case MIGRATION_CAPABILITY_DIRTY_BITMAPS:
> +        cap_addr = &params->dirty_bitmaps;
> +        break;
> +    case MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME:
> +        cap_addr = &params->postcopy_blocktime;
> +        break;
> +    case MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE:
> +        cap_addr = &params->late_block_activate;
> +        break;
> +    case MIGRATION_CAPABILITY_X_IGNORE_SHARED:
> +        cap_addr = &params->x_ignore_shared;
> +        break;
> +    case MIGRATION_CAPABILITY_VALIDATE_UUID:
> +        cap_addr = &params->validate_uuid;
> +        break;
> +    case MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT:
> +        cap_addr = &params->background_snapshot;
> +        break;
> +    case MIGRATION_CAPABILITY_ZERO_COPY_SEND:
> +        cap_addr = &params->zero_copy_send;
> +        break;
> +    case MIGRATION_CAPABILITY_POSTCOPY_PREEMPT:
> +        cap_addr = &params->postcopy_preempt;
> +        break;
> +    case MIGRATION_CAPABILITY_SWITCHOVER_ACK:
> +        cap_addr = &params->switchover_ack;
> +        break;
> +    case MIGRATION_CAPABILITY_DIRTY_LIMIT:
> +        cap_addr = &params->dirty_limit;
> +        break;
> +    case MIGRATION_CAPABILITY_MAPPED_RAM:
> +        cap_addr = &params->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?

>  #
>  # 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:
Fabiano Rosas Sept. 4, 2026, 1:58 p.m. UTC | #2
Markus Armbruster <armbru@redhat.com> writes:

> Fabiano Rosas <farosas@suse.de> 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 <peterx@redhat.com>
>> Signed-off-by: Fabiano Rosas <farosas@suse.de>
>> ---
>>  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 = &params->xbzrle;
>> +        break;
>> +    case MIGRATION_CAPABILITY_RDMA_PIN_ALL:
>> +        cap_addr = &params->rdma_pin_all;
>> +        break;
>> +    case MIGRATION_CAPABILITY_AUTO_CONVERGE:
>> +        cap_addr = &params->auto_converge;
>> +        break;
>> +    case MIGRATION_CAPABILITY_EVENTS:
>> +        cap_addr = &params->events;
>> +        break;
>> +    case MIGRATION_CAPABILITY_POSTCOPY_RAM:
>> +        cap_addr = &params->postcopy_ram;
>> +        break;
>> +    case MIGRATION_CAPABILITY_X_COLO:
>> +        cap_addr = &params->x_colo;
>> +        break;
>> +    case MIGRATION_CAPABILITY_RELEASE_RAM:
>> +        cap_addr = &params->release_ram;
>> +        break;
>> +    case MIGRATION_CAPABILITY_RETURN_PATH:
>> +        cap_addr = &params->return_path;
>> +        break;
>> +    case MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER:
>> +        cap_addr = &params->pause_before_switchover;
>> +        break;
>> +    case MIGRATION_CAPABILITY_MULTIFD:
>> +        cap_addr = &params->multifd;
>> +        break;
>> +    case MIGRATION_CAPABILITY_DIRTY_BITMAPS:
>> +        cap_addr = &params->dirty_bitmaps;
>> +        break;
>> +    case MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME:
>> +        cap_addr = &params->postcopy_blocktime;
>> +        break;
>> +    case MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE:
>> +        cap_addr = &params->late_block_activate;
>> +        break;
>> +    case MIGRATION_CAPABILITY_X_IGNORE_SHARED:
>> +        cap_addr = &params->x_ignore_shared;
>> +        break;
>> +    case MIGRATION_CAPABILITY_VALIDATE_UUID:
>> +        cap_addr = &params->validate_uuid;
>> +        break;
>> +    case MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT:
>> +        cap_addr = &params->background_snapshot;
>> +        break;
>> +    case MIGRATION_CAPABILITY_ZERO_COPY_SEND:
>> +        cap_addr = &params->zero_copy_send;
>> +        break;
>> +    case MIGRATION_CAPABILITY_POSTCOPY_PREEMPT:
>> +        cap_addr = &params->postcopy_preempt;
>> +        break;
>> +    case MIGRATION_CAPABILITY_SWITCHOVER_ACK:
>> +        cap_addr = &params->switchover_ack;
>> +        break;
>> +    case MIGRATION_CAPABILITY_DIRTY_LIMIT:
>> +        cap_addr = &params->dirty_limit;
>> +        break;
>> +    case MIGRATION_CAPABILITY_MAPPED_RAM:
>> +        cap_addr = &params->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:
diff mbox series

Patch

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 = &params->xbzrle;
+        break;
+    case MIGRATION_CAPABILITY_RDMA_PIN_ALL:
+        cap_addr = &params->rdma_pin_all;
+        break;
+    case MIGRATION_CAPABILITY_AUTO_CONVERGE:
+        cap_addr = &params->auto_converge;
+        break;
+    case MIGRATION_CAPABILITY_EVENTS:
+        cap_addr = &params->events;
+        break;
+    case MIGRATION_CAPABILITY_POSTCOPY_RAM:
+        cap_addr = &params->postcopy_ram;
+        break;
+    case MIGRATION_CAPABILITY_X_COLO:
+        cap_addr = &params->x_colo;
+        break;
+    case MIGRATION_CAPABILITY_RELEASE_RAM:
+        cap_addr = &params->release_ram;
+        break;
+    case MIGRATION_CAPABILITY_RETURN_PATH:
+        cap_addr = &params->return_path;
+        break;
+    case MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER:
+        cap_addr = &params->pause_before_switchover;
+        break;
+    case MIGRATION_CAPABILITY_MULTIFD:
+        cap_addr = &params->multifd;
+        break;
+    case MIGRATION_CAPABILITY_DIRTY_BITMAPS:
+        cap_addr = &params->dirty_bitmaps;
+        break;
+    case MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME:
+        cap_addr = &params->postcopy_blocktime;
+        break;
+    case MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE:
+        cap_addr = &params->late_block_activate;
+        break;
+    case MIGRATION_CAPABILITY_X_IGNORE_SHARED:
+        cap_addr = &params->x_ignore_shared;
+        break;
+    case MIGRATION_CAPABILITY_VALIDATE_UUID:
+        cap_addr = &params->validate_uuid;
+        break;
+    case MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT:
+        cap_addr = &params->background_snapshot;
+        break;
+    case MIGRATION_CAPABILITY_ZERO_COPY_SEND:
+        cap_addr = &params->zero_copy_send;
+        break;
+    case MIGRATION_CAPABILITY_POSTCOPY_PREEMPT:
+        cap_addr = &params->postcopy_preempt;
+        break;
+    case MIGRATION_CAPABILITY_SWITCHOVER_ACK:
+        cap_addr = &params->switchover_ack;
+        break;
+    case MIGRATION_CAPABILITY_DIRTY_LIMIT:
+        cap_addr = &params->dirty_limit;
+        break;
+    case MIGRATION_CAPABILITY_MAPPED_RAM:
+        cap_addr = &params->mapped_ram;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    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.
 #
 # 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: