diff mbox series

[4/6] migration: Add ram-only capability

Message ID 20211224111148.345438-5-nikita.lapshin@virtuozzo.com (mailing list archive)
State New, archived
Headers show
Series migration: Add 'no-ram' and 'ram-only' cpabilities | expand

Commit Message

Nikta Lapshin Dec. 24, 2021, 11:11 a.m. UTC
If this capability is enabled migration stream
will have RAM section only.

Signed-off-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>
---
 migration/migration.c | 20 +++++++++++++++++++-
 migration/migration.h |  1 +
 migration/savevm.c    | 11 ++++++++++-
 qapi/migration.json   |  7 +++++--
 4 files changed, 35 insertions(+), 4 deletions(-)

Comments

Vladimir Sementsov-Ogievskiy Dec. 28, 2021, 1:16 p.m. UTC | #1
24.12.2021 14:11, Nikita Lapshin wrote:
> If this capability is enabled migration stream
> will have RAM section only.
> 
> Signed-off-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>
> ---
>   migration/migration.c | 20 +++++++++++++++++++-
>   migration/migration.h |  1 +
>   migration/savevm.c    | 11 ++++++++++-
>   qapi/migration.json   |  7 +++++--
>   4 files changed, 35 insertions(+), 4 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index 006447d00a..4d7ef9d8dc 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -1257,6 +1257,14 @@ static bool migrate_caps_check(bool *cap_list,
>           return false;
>       }
>   
> +    if (cap_list[MIGRATION_CAPABILITY_NO_RAM] &&
> +        cap_list[MIGRATION_CAPABILITY_RAM_ONLY]) {
> +        error_setg(errp, "ram-only and no-ram aren't "
> +                         "compatible with each other");
> +
> +        return false;
> +    }
> +
>       return true;
>   }
>   
> @@ -2619,6 +2627,15 @@ bool migrate_no_ram(void)
>       return s->enabled_capabilities[MIGRATION_CAPABILITY_NO_RAM];
>   }
>   
> +bool migrate_ram_only(void)
> +{
> +    MigrationState *s;
> +
> +    s = migrate_get_current();
> +
> +    return s->enabled_capabilities[MIGRATION_CAPABILITY_RAM_ONLY];
> +}
> +
>   /* migration thread support */
>   /*
>    * Something bad happened to the RP stream, mark an error
> @@ -3973,7 +3990,8 @@ static void *bg_migration_thread(void *opaque)
>        * save their state to channel-buffer along with devices.
>        */
>       cpu_synchronize_all_states();
> -    if (qemu_savevm_state_complete_precopy_non_iterable(fb, false, false)) {
> +    if (!migrate_ram_only() &&
> +        qemu_savevm_state_complete_precopy_non_iterable(fb, false, false)) {

Here... [*]

>           goto fail;
>       }
>       /*
> diff --git a/migration/migration.h b/migration/migration.h
> index 43f7bf8eba..d5a077e00d 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -359,6 +359,7 @@ bool migrate_use_events(void);
>   bool migrate_postcopy_blocktime(void);
>   bool migrate_background_snapshot(void);
>   bool migrate_no_ram(void);
> +bool migrate_ram_only(void);
>   
>   /* Sending on the return path - generic and then for each message type */
>   void migrate_send_rp_shut(MigrationIncomingState *mis,
> diff --git a/migration/savevm.c b/migration/savevm.c
> index ba644083ab..e41ca76000 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -249,6 +249,7 @@ typedef struct SaveStateEntry {
>       void *opaque;
>       CompatEntry *compat;
>       int is_iterable;
> +    bool is_ram;
>   } SaveStateEntry;
>   
>   typedef struct SaveState {
> @@ -802,6 +803,10 @@ int register_savevm_live(const char *idstr,
>           se->is_iterable = 1;
>       }
>   
> +    if (!strcmp("ram", idstr)) {
> +        se->is_ram = true;
> +    }
> +
>       pstrcat(se->idstr, sizeof(se->idstr), idstr);
>   
>       if (instance_id == VMSTATE_INSTANCE_ID_ANY) {
> @@ -949,6 +954,10 @@ static bool should_skip(SaveStateEntry *se)
>           return true;
>       }
>   
> +    if (migrate_ram_only() && !se->is_ram) {
> +        return true;
> +    }
> +
>       return false;
>   }
>   
> @@ -1486,7 +1495,7 @@ int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
>           }
>       }
>   
> -    if (iterable_only) {
> +    if (iterable_only || migrate_ram_only()) {
>           goto flush;
>       }

[*] ... and here you care to avoid calling same qemu_savevm_state_complete_precopy_non_iterable()

Seems better to check migrate_ram_only at start of qemu_savevm_state_complete_precopy_non_iterable() and do early return from it.

>   
> diff --git a/qapi/migration.json b/qapi/migration.json
> index d53956852c..626fc59d14 100644
> --- a/qapi/migration.json
> +++ b/qapi/migration.json
> @@ -454,6 +454,8 @@
>   #
>   # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
>   #
> +# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
> +#
>   # Features:
>   # @unstable: Members @x-colo and @x-ignore-shared are experimental.
>   #
> @@ -467,7 +469,7 @@
>              'block', 'return-path', 'pause-before-switchover', 'multifd',
>              'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
>              { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
> -           'validate-uuid', 'background-snapshot', 'no-ram'] }
> +           'validate-uuid', 'background-snapshot', 'no-ram', 'ram-only'] }
>   ##
>   # @MigrationCapabilityStatus:
>   #
> @@ -521,7 +523,8 @@
>   #       {"state": true, "capability": "events"},
>   #       {"state": false, "capability": "postcopy-ram"},
>   #       {"state": false, "capability": "x-colo"},
> -#       {"state": false, "capability": "no-ram"}
> +#       {"state": false, "capability": "no-ram"},
> +#       {"state": false, "capability": "ram-only"}
>   #    ]}
>   #
>   ##
>
Markus Armbruster Jan. 14, 2022, 11:22 a.m. UTC | #2
Nikita Lapshin <nikita.lapshin@virtuozzo.com> writes:

> If this capability is enabled migration stream
> will have RAM section only.
>
> Signed-off-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>

[...]

> diff --git a/qapi/migration.json b/qapi/migration.json
> index d53956852c..626fc59d14 100644
> --- a/qapi/migration.json
> +++ b/qapi/migration.json
> @@ -454,6 +454,8 @@
>  #
>  # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
>  #
> +# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
> +#

What happens when I ask for 'no-ram': true, 'ram-only': true?

>  # Features:
>  # @unstable: Members @x-colo and @x-ignore-shared are experimental.
>  #
> @@ -467,7 +469,7 @@
>             'block', 'return-path', 'pause-before-switchover', 'multifd',
>             'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
>             { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
> -           'validate-uuid', 'background-snapshot', 'no-ram'] }
> +           'validate-uuid', 'background-snapshot', 'no-ram', 'ram-only'] }
>  ##
>  # @MigrationCapabilityStatus:
>  #
> @@ -521,7 +523,8 @@
>  #       {"state": true, "capability": "events"},
>  #       {"state": false, "capability": "postcopy-ram"},
>  #       {"state": false, "capability": "x-colo"},
> -#       {"state": false, "capability": "no-ram"}
> +#       {"state": false, "capability": "no-ram"},
> +#       {"state": false, "capability": "ram-only"}
>  #    ]}
>  #
>  ##
Daniel P. Berrangé Jan. 14, 2022, 11:38 a.m. UTC | #3
On Fri, Jan 14, 2022 at 12:22:13PM +0100, Markus Armbruster wrote:
> Nikita Lapshin <nikita.lapshin@virtuozzo.com> writes:
> 
> > If this capability is enabled migration stream
> > will have RAM section only.
> >
> > Signed-off-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>
> 
> [...]
> 
> > diff --git a/qapi/migration.json b/qapi/migration.json
> > index d53956852c..626fc59d14 100644
> > --- a/qapi/migration.json
> > +++ b/qapi/migration.json
> > @@ -454,6 +454,8 @@
> >  #
> >  # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
> >  #
> > +# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
> > +#
> 
> What happens when I ask for 'no-ram': true, 'ram-only': true?

So IIUC

  no-ram=false, ram-only=false =>  RAM + vmstate
  no-ram=true, ram-only=false => vmstate
  no-ram=false, ram-only=true =>  RAM
  no-ram=true, ram-only=true => nothing to send ?

I find that the fact that one flag is a negative request and
the other flag is a positive request to be confusing.

If we must have two flags then could we at least use the same
style for both. ie either

  @no-ram
  @no-vmstate

Or

  @ram-only
  @vmstate-only

Since the code enforces these flags are mutually exclusive
though, it might point towards being handled by a enum

  { 'enum': 'MigrationStreamContent',
    'data': ['both', 'ram', 'vmstate'] }

none of these approaches are especially future proof if we ever
need fine grained control over sending a sub-set of the non-RAM
vmstate. Not sure if that matters in the end.


Regards,
Daniel
Markus Armbruster Jan. 14, 2022, 3:55 p.m. UTC | #4
Daniel P. Berrangé <berrange@redhat.com> writes:

> On Fri, Jan 14, 2022 at 12:22:13PM +0100, Markus Armbruster wrote:
>> Nikita Lapshin <nikita.lapshin@virtuozzo.com> writes:
>> 
>> > If this capability is enabled migration stream
>> > will have RAM section only.
>> >
>> > Signed-off-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>
>> 
>> [...]
>> 
>> > diff --git a/qapi/migration.json b/qapi/migration.json
>> > index d53956852c..626fc59d14 100644
>> > --- a/qapi/migration.json
>> > +++ b/qapi/migration.json
>> > @@ -454,6 +454,8 @@
>> >  #
>> >  # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
>> >  #
>> > +# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
>> > +#
>> 
>> What happens when I ask for 'no-ram': true, 'ram-only': true?
>
> So IIUC
>
>   no-ram=false, ram-only=false =>  RAM + vmstate
>   no-ram=true, ram-only=false => vmstate
>   no-ram=false, ram-only=true =>  RAM
>   no-ram=true, ram-only=true => nothing to send ?
>
> I find that the fact that one flag is a negative request and
> the other flag is a positive request to be confusing.

Me too.

> If we must have two flags then could we at least use the same
> style for both. ie either
>
>   @no-ram
>   @no-vmstate
>
> Or
>
>   @ram-only
>   @vmstate-only

I strongly prefer "positive" names for booleans, avoiding double
negation.

> Since the code enforces these flags are mutually exclusive
> though, it might point towards being handled by a enum
>
>   { 'enum': 'MigrationStreamContent',
>     'data': ['both', 'ram', 'vmstate'] }

Enumerating the combinations that are actually valid is often nicer than
a set of flags that look independent, but aren't.

MigrationCapability can only do flags.  For an enum, we'd have to use
MigrationParameters & friends.  For an example, check out
@multifd-compression there.

> none of these approaches are especially future proof if we ever
> need fine grained control over sending a sub-set of the non-RAM
> vmstate. Not sure if that matters in the end.
>
>
> Regards,
> Daniel
Nikta Lapshin Jan. 17, 2022, 8:12 a.m. UTC | #5
On 1/14/22 14:22, Markus Armbruster wrote:
> Nikita Lapshin<nikita.lapshin@virtuozzo.com>  writes:
>
>> If this capability is enabled migration stream
>> will have RAM section only.
>>
>> Signed-off-by: Nikita Lapshin<nikita.lapshin@virtuozzo.com>
> [...]
>
>> diff --git a/qapi/migration.json b/qapi/migration.json
>> index d53956852c..626fc59d14 100644
>> --- a/qapi/migration.json
>> +++ b/qapi/migration.json
>> @@ -454,6 +454,8 @@
>>   #
>>   # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
>>   #
>> +# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
>> +#
> What happens when I ask for 'no-ram': true, 'ram-only': true?


migrate_caps_check() will return false and print error message that these
capabilities are not compatible.


>
>>   # Features:
>>   # @unstable: Members @x-colo and @x-ignore-shared are experimental.
>>   #
>> @@ -467,7 +469,7 @@
>>              'block', 'return-path', 'pause-before-switchover', 'multifd',
>>              'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
>>              { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
>> -           'validate-uuid', 'background-snapshot', 'no-ram'] }
>> +           'validate-uuid', 'background-snapshot', 'no-ram', 'ram-only'] }
>>   ##
>>   # @MigrationCapabilityStatus:
>>   #
>> @@ -521,7 +523,8 @@
>>   #       {"state": true, "capability": "events"},
>>   #       {"state": false, "capability": "postcopy-ram"},
>>   #       {"state": false, "capability": "x-colo"},
>> -#       {"state": false, "capability": "no-ram"}
>> +#       {"state": false, "capability": "no-ram"},
>> +#       {"state": false, "capability": "ram-only"}
>>   #    ]}
>>   #
>>   ##
Vladimir Sementsov-Ogievskiy Jan. 17, 2022, 9:04 a.m. UTC | #6
14.01.2022 18:55, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
>> On Fri, Jan 14, 2022 at 12:22:13PM +0100, Markus Armbruster wrote:
>>> Nikita Lapshin <nikita.lapshin@virtuozzo.com> writes:
>>>
>>>> If this capability is enabled migration stream
>>>> will have RAM section only.
>>>>
>>>> Signed-off-by: Nikita Lapshin <nikita.lapshin@virtuozzo.com>
>>>
>>> [...]
>>>
>>>> diff --git a/qapi/migration.json b/qapi/migration.json
>>>> index d53956852c..626fc59d14 100644
>>>> --- a/qapi/migration.json
>>>> +++ b/qapi/migration.json
>>>> @@ -454,6 +454,8 @@
>>>>   #
>>>>   # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
>>>>   #
>>>> +# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
>>>> +#
>>>
>>> What happens when I ask for 'no-ram': true, 'ram-only': true?
>>
>> So IIUC
>>
>>    no-ram=false, ram-only=false =>  RAM + vmstate
>>    no-ram=true, ram-only=false => vmstate
>>    no-ram=false, ram-only=true =>  RAM
>>    no-ram=true, ram-only=true => nothing to send ?
>>
>> I find that the fact that one flag is a negative request and
>> the other flag is a positive request to be confusing.
> 
> Me too.
> 
>> If we must have two flags then could we at least use the same
>> style for both. ie either
>>
>>    @no-ram
>>    @no-vmstate
>>
>> Or
>>
>>    @ram-only
>>    @vmstate-only
> 
> I strongly prefer "positive" names for booleans, avoiding double
> negation.
> 
>> Since the code enforces these flags are mutually exclusive
>> though, it might point towards being handled by a enum
>>
>>    { 'enum': 'MigrationStreamContent',
>>      'data': ['both', 'ram', 'vmstate'] }
> 
> Enumerating the combinations that are actually valid is often nicer than
> a set of flags that look independent, but aren't.
> 
> MigrationCapability can only do flags.  For an enum, we'd have to use
> MigrationParameters & friends.  For an example, check out
> @multifd-compression there.
> 

Remember, that we also have block-dirty-bitmaps in migration stream. And we also may have block devices data (should it be deprecated?).

So, what about an optional migration parameter stream-content, which would be a *list* of MigrationStreamContent enum values?

Than we can deprecate dirty-bitmaps and block capabilities in favor of new migration parameter.

{ 'enum': 'MigrationStreamContent', 'data': ['block-dirty-bitmpas', 'block', 'ram', 'vmstate'] }

...

Migration parameters:

...
'stream-content': ['MigrationStreamContent']
diff mbox series

Patch

diff --git a/migration/migration.c b/migration/migration.c
index 006447d00a..4d7ef9d8dc 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1257,6 +1257,14 @@  static bool migrate_caps_check(bool *cap_list,
         return false;
     }
 
+    if (cap_list[MIGRATION_CAPABILITY_NO_RAM] &&
+        cap_list[MIGRATION_CAPABILITY_RAM_ONLY]) {
+        error_setg(errp, "ram-only and no-ram aren't "
+                         "compatible with each other");
+
+        return false;
+    }
+
     return true;
 }
 
@@ -2619,6 +2627,15 @@  bool migrate_no_ram(void)
     return s->enabled_capabilities[MIGRATION_CAPABILITY_NO_RAM];
 }
 
+bool migrate_ram_only(void)
+{
+    MigrationState *s;
+
+    s = migrate_get_current();
+
+    return s->enabled_capabilities[MIGRATION_CAPABILITY_RAM_ONLY];
+}
+
 /* migration thread support */
 /*
  * Something bad happened to the RP stream, mark an error
@@ -3973,7 +3990,8 @@  static void *bg_migration_thread(void *opaque)
      * save their state to channel-buffer along with devices.
      */
     cpu_synchronize_all_states();
-    if (qemu_savevm_state_complete_precopy_non_iterable(fb, false, false)) {
+    if (!migrate_ram_only() &&
+        qemu_savevm_state_complete_precopy_non_iterable(fb, false, false)) {
         goto fail;
     }
     /*
diff --git a/migration/migration.h b/migration/migration.h
index 43f7bf8eba..d5a077e00d 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -359,6 +359,7 @@  bool migrate_use_events(void);
 bool migrate_postcopy_blocktime(void);
 bool migrate_background_snapshot(void);
 bool migrate_no_ram(void);
+bool migrate_ram_only(void);
 
 /* Sending on the return path - generic and then for each message type */
 void migrate_send_rp_shut(MigrationIncomingState *mis,
diff --git a/migration/savevm.c b/migration/savevm.c
index ba644083ab..e41ca76000 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -249,6 +249,7 @@  typedef struct SaveStateEntry {
     void *opaque;
     CompatEntry *compat;
     int is_iterable;
+    bool is_ram;
 } SaveStateEntry;
 
 typedef struct SaveState {
@@ -802,6 +803,10 @@  int register_savevm_live(const char *idstr,
         se->is_iterable = 1;
     }
 
+    if (!strcmp("ram", idstr)) {
+        se->is_ram = true;
+    }
+
     pstrcat(se->idstr, sizeof(se->idstr), idstr);
 
     if (instance_id == VMSTATE_INSTANCE_ID_ANY) {
@@ -949,6 +954,10 @@  static bool should_skip(SaveStateEntry *se)
         return true;
     }
 
+    if (migrate_ram_only() && !se->is_ram) {
+        return true;
+    }
+
     return false;
 }
 
@@ -1486,7 +1495,7 @@  int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
         }
     }
 
-    if (iterable_only) {
+    if (iterable_only || migrate_ram_only()) {
         goto flush;
     }
 
diff --git a/qapi/migration.json b/qapi/migration.json
index d53956852c..626fc59d14 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -454,6 +454,8 @@ 
 #
 # @no-ram: If enabled, migration stream won't contain any ram in it. (since 7.0)
 #
+# @ram-only: If enabled, only RAM sections will be sent. (since 7.0)
+#
 # Features:
 # @unstable: Members @x-colo and @x-ignore-shared are experimental.
 #
@@ -467,7 +469,7 @@ 
            'block', 'return-path', 'pause-before-switchover', 'multifd',
            'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
            { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
-           'validate-uuid', 'background-snapshot', 'no-ram'] }
+           'validate-uuid', 'background-snapshot', 'no-ram', 'ram-only'] }
 ##
 # @MigrationCapabilityStatus:
 #
@@ -521,7 +523,8 @@ 
 #       {"state": true, "capability": "events"},
 #       {"state": false, "capability": "postcopy-ram"},
 #       {"state": false, "capability": "x-colo"},
-#       {"state": false, "capability": "no-ram"}
+#       {"state": false, "capability": "no-ram"},
+#       {"state": false, "capability": "ram-only"}
 #    ]}
 #
 ##