[Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods

Juan Quintela posted 5 patches 8 years, 7 months ago
[Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods
Posted by Juan Quintela 8 years, 7 months ago
We need to do things at load time and at cleanup time.

Signed-off-by: Juan Quintela <quintela@redhat.com>

--

Move the printing of the error message so we can print the device
giving the error.
Add call to postcopy stuff
---
 include/migration/register.h |  2 ++
 migration/savevm.c           | 45 +++++++++++++++++++++++++++++++++++++++++++-
 migration/savevm.h           |  1 +
 migration/trace-events       |  2 ++
 4 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/include/migration/register.h b/include/migration/register.h
index 938ea2b..a0f1edd 100644
--- a/include/migration/register.h
+++ b/include/migration/register.h
@@ -39,6 +39,8 @@ typedef struct SaveVMHandlers {
                               uint64_t *non_postcopiable_pending,
                               uint64_t *postcopiable_pending);
     LoadStateHandler *load_state;
+    int (*load_setup)(QEMUFile *f, void *opaque);
+    int (*load_cleanup)(void *opaque);
 } SaveVMHandlers;
 
 int register_savevm_live(DeviceState *dev,
diff --git a/migration/savevm.c b/migration/savevm.c
index fee11c5..fdd15fa 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
      * got a bad migration state).
      */
     migration_incoming_state_destroy();
-
+    qemu_loadvm_state_cleanup();
 
     return NULL;
 }
@@ -1901,6 +1901,44 @@ qemu_loadvm_section_part_end(QEMUFile *f, MigrationIncomingState *mis)
     return 0;
 }
 
+static int qemu_loadvm_state_setup(QEMUFile *f)
+{
+    SaveStateEntry *se;
+    int ret;
+
+    trace_loadvm_state_setup();
+    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+        if (!se->ops || !se->ops->load_setup) {
+            continue;
+        }
+        if (se->ops && se->ops->is_active) {
+            if (!se->ops->is_active(se->opaque)) {
+                continue;
+            }
+        }
+
+        ret = se->ops->load_setup(f, se->opaque);
+        if (ret < 0) {
+            qemu_file_set_error(f, ret);
+            error_report("Load state of device %s failed", se->idstr);
+            return ret;
+        }
+    }
+    return 0;
+}
+
+void qemu_loadvm_state_cleanup(void)
+{
+    SaveStateEntry *se;
+
+    trace_loadvm_state_cleanup();
+    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+        if (se->ops && se->ops->load_cleanup) {
+            se->ops->load_cleanup(se->opaque);
+        }
+    }
+}
+
 static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis)
 {
     uint8_t section_type;
@@ -1973,6 +2011,10 @@ int qemu_loadvm_state(QEMUFile *f)
         return -ENOTSUP;
     }
 
+    if (qemu_loadvm_state_setup(f) != 0) {
+        return -EINVAL;
+    }
+
     if (migrate_get_current()->send_configuration) {
         if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) {
             error_report("Configuration section missing");
@@ -2036,6 +2078,7 @@ int qemu_loadvm_state(QEMUFile *f)
         }
     }
 
+    qemu_loadvm_state_cleanup();
     cpu_synchronize_all_post_init();
 
     return ret;
diff --git a/migration/savevm.h b/migration/savevm.h
index 6babc62..295c4a1 100644
--- a/migration/savevm.h
+++ b/migration/savevm.h
@@ -53,5 +53,6 @@ void qemu_savevm_send_postcopy_ram_discard(QEMUFile *f, const char *name,
                                            uint64_t *length_list);
 
 int qemu_loadvm_state(QEMUFile *f);
+void qemu_loadvm_state_cleanup(void);
 
 #endif
diff --git a/migration/trace-events b/migration/trace-events
index 9669e94..cb2c4b5 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -7,6 +7,8 @@ qemu_loadvm_state_section_partend(uint32_t section_id) "%u"
 qemu_loadvm_state_post_main(int ret) "%d"
 qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u"
 qemu_savevm_send_packaged(void) ""
+loadvm_state_setup(void) ""
+loadvm_state_cleanup(void) ""
 loadvm_handle_cmd_packaged(unsigned int length) "%u"
 loadvm_handle_cmd_packaged_main(int ret) "%d"
 loadvm_handle_cmd_packaged_received(int ret) "%d"
-- 
2.9.4


Re: [Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods
Posted by Dr. David Alan Gilbert 8 years, 7 months ago
* Juan Quintela (quintela@redhat.com) wrote:
> We need to do things at load time and at cleanup time.
> 
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> 
> --
> 
> Move the printing of the error message so we can print the device
> giving the error.
> Add call to postcopy stuff
> ---
>  include/migration/register.h |  2 ++
>  migration/savevm.c           | 45 +++++++++++++++++++++++++++++++++++++++++++-
>  migration/savevm.h           |  1 +
>  migration/trace-events       |  2 ++
>  4 files changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/include/migration/register.h b/include/migration/register.h
> index 938ea2b..a0f1edd 100644
> --- a/include/migration/register.h
> +++ b/include/migration/register.h
> @@ -39,6 +39,8 @@ typedef struct SaveVMHandlers {
>                                uint64_t *non_postcopiable_pending,
>                                uint64_t *postcopiable_pending);
>      LoadStateHandler *load_state;
> +    int (*load_setup)(QEMUFile *f, void *opaque);
> +    int (*load_cleanup)(void *opaque);
>  } SaveVMHandlers;
>  
>  int register_savevm_live(DeviceState *dev,
> diff --git a/migration/savevm.c b/migration/savevm.c
> index fee11c5..fdd15fa 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
>       * got a bad migration state).
>       */
>      migration_incoming_state_destroy();
> -
> +    qemu_loadvm_state_cleanup();

Is that order right? It seems wrong to call the cleanup
code after MIS is destroyed.
(The precopy path seems to call mis_destroy at the end of
process_incoming_migration_bh which is much later).

Dave

>      return NULL;
>  }
> @@ -1901,6 +1901,44 @@ qemu_loadvm_section_part_end(QEMUFile *f, MigrationIncomingState *mis)
>      return 0;
>  }
>  
> +static int qemu_loadvm_state_setup(QEMUFile *f)
> +{
> +    SaveStateEntry *se;
> +    int ret;
> +
> +    trace_loadvm_state_setup();
> +    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
> +        if (!se->ops || !se->ops->load_setup) {
> +            continue;
> +        }
> +        if (se->ops && se->ops->is_active) {
> +            if (!se->ops->is_active(se->opaque)) {
> +                continue;
> +            }
> +        }
> +
> +        ret = se->ops->load_setup(f, se->opaque);
> +        if (ret < 0) {
> +            qemu_file_set_error(f, ret);
> +            error_report("Load state of device %s failed", se->idstr);
> +            return ret;
> +        }
> +    }
> +    return 0;
> +}
> +
> +void qemu_loadvm_state_cleanup(void)
> +{
> +    SaveStateEntry *se;
> +
> +    trace_loadvm_state_cleanup();
> +    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
> +        if (se->ops && se->ops->load_cleanup) {
> +            se->ops->load_cleanup(se->opaque);
> +        }
> +    }
> +}
> +
>  static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis)
>  {
>      uint8_t section_type;
> @@ -1973,6 +2011,10 @@ int qemu_loadvm_state(QEMUFile *f)
>          return -ENOTSUP;
>      }
>  
> +    if (qemu_loadvm_state_setup(f) != 0) {
> +        return -EINVAL;
> +    }
> +
>      if (migrate_get_current()->send_configuration) {
>          if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) {
>              error_report("Configuration section missing");
> @@ -2036,6 +2078,7 @@ int qemu_loadvm_state(QEMUFile *f)
>          }
>      }
>  
> +    qemu_loadvm_state_cleanup();
>      cpu_synchronize_all_post_init();
>  
>      return ret;
> diff --git a/migration/savevm.h b/migration/savevm.h
> index 6babc62..295c4a1 100644
> --- a/migration/savevm.h
> +++ b/migration/savevm.h
> @@ -53,5 +53,6 @@ void qemu_savevm_send_postcopy_ram_discard(QEMUFile *f, const char *name,
>                                             uint64_t *length_list);
>  
>  int qemu_loadvm_state(QEMUFile *f);
> +void qemu_loadvm_state_cleanup(void);
>  
>  #endif
> diff --git a/migration/trace-events b/migration/trace-events
> index 9669e94..cb2c4b5 100644
> --- a/migration/trace-events
> +++ b/migration/trace-events
> @@ -7,6 +7,8 @@ qemu_loadvm_state_section_partend(uint32_t section_id) "%u"
>  qemu_loadvm_state_post_main(int ret) "%d"
>  qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u"
>  qemu_savevm_send_packaged(void) ""
> +loadvm_state_setup(void) ""
> +loadvm_state_cleanup(void) ""
>  loadvm_handle_cmd_packaged(unsigned int length) "%u"
>  loadvm_handle_cmd_packaged_main(int ret) "%d"
>  loadvm_handle_cmd_packaged_received(int ret) "%d"
> -- 
> 2.9.4
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

Re: [Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods
Posted by Juan Quintela 8 years, 7 months ago
"Dr. David Alan Gilbert" <dgilbert@redhat.com> wrote:
> * Juan Quintela (quintela@redhat.com) wrote:
>> We need to do things at load time and at cleanup time.
>> 
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> 
>> --
>> 
>> Move the printing of the error message so we can print the device
>> giving the error.
>> Add call to postcopy stuff
>> ---
>>  include/migration/register.h |  2 ++
>>  migration/savevm.c           | 45 +++++++++++++++++++++++++++++++++++++++++++-
>>  migration/savevm.h           |  1 +
>>  migration/trace-events       |  2 ++
>>  4 files changed, 49 insertions(+), 1 deletion(-)
>> 
>> diff --git a/include/migration/register.h b/include/migration/register.h
>> index 938ea2b..a0f1edd 100644
>> --- a/include/migration/register.h
>> +++ b/include/migration/register.h
>> @@ -39,6 +39,8 @@ typedef struct SaveVMHandlers {
>>                                uint64_t *non_postcopiable_pending,
>>                                uint64_t *postcopiable_pending);
>>      LoadStateHandler *load_state;
>> +    int (*load_setup)(QEMUFile *f, void *opaque);
>> +    int (*load_cleanup)(void *opaque);
>>  } SaveVMHandlers;
>>  
>>  int register_savevm_live(DeviceState *dev,
>> diff --git a/migration/savevm.c b/migration/savevm.c
>> index fee11c5..fdd15fa 100644
>> --- a/migration/savevm.c
>> +++ b/migration/savevm.c
>> @@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
>>       * got a bad migration state).
>>       */
>>      migration_incoming_state_destroy();
>> -
>> +    qemu_loadvm_state_cleanup();
>
> Is that order right? It seems wrong to call the cleanup
> code after MIS is destroyed.
> (The precopy path seems to call mis_destroy at the end of
> process_incoming_migration_bh which is much later).

we can do either way, for now it don't matters.

Once there, it got me thinking that we are doing things in a very
"interesting" way on the incoming side:

(postcopy)

postcopy_ram_incoming_cleanup()
migration_incoming_state_destroy()
qemu_loadvm_state_cleanup()

(Ok, probably it is better to exchange the last two).

But I *think* that we should move the postcopy_ram_incoming_cleanup()
inside ram_load_cleanup(), no?

And we don't have a postcopy_ram_incoming_setup() We could put there the
mmap of mis->postcopy_tmp_zero_page and mis->largest_page_size, no?

I am trying to understand if the postcopy_ram_incoming_init() can be
moved soon, but I think no.

Later, Juan.



Re: [Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods
Posted by Dr. David Alan Gilbert 8 years, 7 months ago
* Juan Quintela (quintela@redhat.com) wrote:
> "Dr. David Alan Gilbert" <dgilbert@redhat.com> wrote:
> > * Juan Quintela (quintela@redhat.com) wrote:
> >> We need to do things at load time and at cleanup time.
> >> 
> >> Signed-off-by: Juan Quintela <quintela@redhat.com>
> >> 
> >> --
> >> 
> >> Move the printing of the error message so we can print the device
> >> giving the error.
> >> Add call to postcopy stuff
> >> ---
> >>  include/migration/register.h |  2 ++
> >>  migration/savevm.c           | 45 +++++++++++++++++++++++++++++++++++++++++++-
> >>  migration/savevm.h           |  1 +
> >>  migration/trace-events       |  2 ++
> >>  4 files changed, 49 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/include/migration/register.h b/include/migration/register.h
> >> index 938ea2b..a0f1edd 100644
> >> --- a/include/migration/register.h
> >> +++ b/include/migration/register.h
> >> @@ -39,6 +39,8 @@ typedef struct SaveVMHandlers {
> >>                                uint64_t *non_postcopiable_pending,
> >>                                uint64_t *postcopiable_pending);
> >>      LoadStateHandler *load_state;
> >> +    int (*load_setup)(QEMUFile *f, void *opaque);
> >> +    int (*load_cleanup)(void *opaque);
> >>  } SaveVMHandlers;
> >>  
> >>  int register_savevm_live(DeviceState *dev,
> >> diff --git a/migration/savevm.c b/migration/savevm.c
> >> index fee11c5..fdd15fa 100644
> >> --- a/migration/savevm.c
> >> +++ b/migration/savevm.c
> >> @@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
> >>       * got a bad migration state).
> >>       */
> >>      migration_incoming_state_destroy();
> >> -
> >> +    qemu_loadvm_state_cleanup();
> >
> > Is that order right? It seems wrong to call the cleanup
> > code after MIS is destroyed.
> > (The precopy path seems to call mis_destroy at the end of
> > process_incoming_migration_bh which is much later).
> 
> we can do either way, for now it don't matters.
> 
> Once there, it got me thinking that we are doing things in a very
> "interesting" way on the incoming side:
> 
> (postcopy)
> 
> postcopy_ram_incoming_cleanup()
> migration_incoming_state_destroy()
> qemu_loadvm_state_cleanup()
> 
> (Ok, probably it is better to exchange the last two).
> 
> But I *think* that we should move the postcopy_ram_incoming_cleanup()
> inside ram_load_cleanup(), no?

postcopy_ram_incoming_cleanup shuts down a thread that's shared across
all RAMBlock's, so I don't think it can all be merged into
ram_load_cleanup.   You might be able to do the equivalent of the
cleanup_range function.

> And we don't have a postcopy_ram_incoming_setup() We could put there the
> mmap of mis->postcopy_tmp_zero_page and mis->largest_page_size, no?

Again that's a single shared zero page, not per RAMBlock.

> I am trying to understand if the postcopy_ram_incoming_init() can be
> moved soon, but I think no.

Dave

> 
> Later, Juan.
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

Re: [Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods
Posted by Dr. David Alan Gilbert 8 years, 7 months ago
* Dr. David Alan Gilbert (dgilbert@redhat.com) wrote:
> * Juan Quintela (quintela@redhat.com) wrote:
> > "Dr. David Alan Gilbert" <dgilbert@redhat.com> wrote:
> > > * Juan Quintela (quintela@redhat.com) wrote:
> > >> We need to do things at load time and at cleanup time.
> > >> 
> > >> Signed-off-by: Juan Quintela <quintela@redhat.com>
> > >> 
> > >> --
> > >> 
> > >> Move the printing of the error message so we can print the device
> > >> giving the error.
> > >> Add call to postcopy stuff
> > >> ---
> > >>  include/migration/register.h |  2 ++
> > >>  migration/savevm.c           | 45 +++++++++++++++++++++++++++++++++++++++++++-
> > >>  migration/savevm.h           |  1 +
> > >>  migration/trace-events       |  2 ++
> > >>  4 files changed, 49 insertions(+), 1 deletion(-)
> > >> 
> > >> diff --git a/include/migration/register.h b/include/migration/register.h
> > >> index 938ea2b..a0f1edd 100644
> > >> --- a/include/migration/register.h
> > >> +++ b/include/migration/register.h
> > >> @@ -39,6 +39,8 @@ typedef struct SaveVMHandlers {
> > >>                                uint64_t *non_postcopiable_pending,
> > >>                                uint64_t *postcopiable_pending);
> > >>      LoadStateHandler *load_state;
> > >> +    int (*load_setup)(QEMUFile *f, void *opaque);
> > >> +    int (*load_cleanup)(void *opaque);
> > >>  } SaveVMHandlers;
> > >>  
> > >>  int register_savevm_live(DeviceState *dev,
> > >> diff --git a/migration/savevm.c b/migration/savevm.c
> > >> index fee11c5..fdd15fa 100644
> > >> --- a/migration/savevm.c
> > >> +++ b/migration/savevm.c
> > >> @@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
> > >>       * got a bad migration state).
> > >>       */
> > >>      migration_incoming_state_destroy();
> > >> -
> > >> +    qemu_loadvm_state_cleanup();
> > >
> > > Is that order right? It seems wrong to call the cleanup
> > > code after MIS is destroyed.
> > > (The precopy path seems to call mis_destroy at the end of
> > > process_incoming_migration_bh which is much later).
> > 
> > we can do either way, for now it don't matters.
> > 
> > Once there, it got me thinking that we are doing things in a very
> > "interesting" way on the incoming side:
> > 
> > (postcopy)
> > 
> > postcopy_ram_incoming_cleanup()
> > migration_incoming_state_destroy()
> > qemu_loadvm_state_cleanup()
> > 
> > (Ok, probably it is better to exchange the last two).
> > 
> > But I *think* that we should move the postcopy_ram_incoming_cleanup()
> > inside ram_load_cleanup(), no?
> 
> postcopy_ram_incoming_cleanup shuts down a thread that's shared across
> all RAMBlock's, so I don't think it can all be merged into
> ram_load_cleanup.   You might be able to do the equivalent of the
> cleanup_range function.

Actually that's wrong, we only call ram_load_cleanup once - because
RAM is special and is only register_savevm_live once, not per device.

So yes you probably can do that.

Dave

> > And we don't have a postcopy_ram_incoming_setup() We could put there the
> > mmap of mis->postcopy_tmp_zero_page and mis->largest_page_size, no?
> 
> Again that's a single shared zero page, not per RAMBlock.
> 
> > I am trying to understand if the postcopy_ram_incoming_init() can be
> > moved soon, but I think no.
> 
> Dave
> 
> > 
> > Later, Juan.
> > 
> > 
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

Re: [Qemu-devel] [PATCH v4 3/5] migration: Create load_setup()/cleanup() methods
Posted by Dr. David Alan Gilbert 8 years, 7 months ago
* Juan Quintela (quintela@redhat.com) wrote:
> "Dr. David Alan Gilbert" <dgilbert@redhat.com> wrote:
> > * Juan Quintela (quintela@redhat.com) wrote:
> >> We need to do things at load time and at cleanup time.
> >> 
> >> Signed-off-by: Juan Quintela <quintela@redhat.com>
> >> 
> >> --
> >> 
> >> Move the printing of the error message so we can print the device
> >> giving the error.
> >> Add call to postcopy stuff
> >> ---
> >>  include/migration/register.h |  2 ++
> >>  migration/savevm.c           | 45 +++++++++++++++++++++++++++++++++++++++++++-
> >>  migration/savevm.h           |  1 +
> >>  migration/trace-events       |  2 ++
> >>  4 files changed, 49 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/include/migration/register.h b/include/migration/register.h
> >> index 938ea2b..a0f1edd 100644
> >> --- a/include/migration/register.h
> >> +++ b/include/migration/register.h
> >> @@ -39,6 +39,8 @@ typedef struct SaveVMHandlers {
> >>                                uint64_t *non_postcopiable_pending,
> >>                                uint64_t *postcopiable_pending);
> >>      LoadStateHandler *load_state;
> >> +    int (*load_setup)(QEMUFile *f, void *opaque);
> >> +    int (*load_cleanup)(void *opaque);
> >>  } SaveVMHandlers;
> >>  
> >>  int register_savevm_live(DeviceState *dev,
> >> diff --git a/migration/savevm.c b/migration/savevm.c
> >> index fee11c5..fdd15fa 100644
> >> --- a/migration/savevm.c
> >> +++ b/migration/savevm.c
> >> @@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
> >>       * got a bad migration state).
> >>       */
> >>      migration_incoming_state_destroy();
> >> -
> >> +    qemu_loadvm_state_cleanup();
> >
> > Is that order right? It seems wrong to call the cleanup
> > code after MIS is destroyed.
> > (The precopy path seems to call mis_destroy at the end of
> > process_incoming_migration_bh which is much later).
> 
> we can do either way, for now it don't matters.

OK, yes, for now it doesn't matter, so:

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>


> Once there, it got me thinking that we are doing things in a very
> "interesting" way on the incoming side:
> 
> (postcopy)
> 
> postcopy_ram_incoming_cleanup()
> migration_incoming_state_destroy()
> qemu_loadvm_state_cleanup()
> 
> (Ok, probably it is better to exchange the last two).
> 
> But I *think* that we should move the postcopy_ram_incoming_cleanup()
> inside ram_load_cleanup(), no?
> 
> And we don't have a postcopy_ram_incoming_setup() We could put there the
> mmap of mis->postcopy_tmp_zero_page and mis->largest_page_size, no?
> 
> I am trying to understand if the postcopy_ram_incoming_init() can be
> moved soon, but I think no.
> 
> Later, Juan.
> 
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK