qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Xu <peterx@redhat.com>
To: qemu-devel@nongnu.org
Cc: peterx@redhat.com, Juraj Marcin <jmarcin@redhat.com>,
	Julia Suvorova <jusual@redhat.com>,
	Prasad Pandit <ppandit@redhat.com>,
	Fabiano Rosas <farosas@suse.de>
Subject: [PATCH 02/16] migration: Do not construct JSON description if suppressed
Date: Tue, 14 Jan 2025 18:07:32 -0500	[thread overview]
Message-ID: <20250114230746.3268797-3-peterx@redhat.com> (raw)
In-Reply-To: <20250114230746.3268797-1-peterx@redhat.com>

QEMU machine has a property "suppress-vmdesc". When it is enabled, QEMU
will stop attaching JSON VM description at the end of the precopy migration
stream (postcopy is never affected because postcopy never attach that).

However even if it's suppressed by the user, the source QEMU will still
construct the JSON descriptions, which is a complete waste of CPU and
memory resources.

To avoid it, only create the JSON writer object if suppress-vmdesc is not
specified.

Luckily, vmstate_save() already supports vmdesc==NULL, so only a few spots
that are left to be prepared that vmdesc can be NULL now.

When at it, move the init / destroy of the JSON writer object to start /
end of the migration - the JSON writer object is a sub-struct of migration
state, and that looks like the only object that was dynamically allocated /
destroyed within migration process.  Make it the same as the rest objects
that migration uses.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 migration/migration.h |  1 +
 migration/migration.c |  9 +++++---
 migration/savevm.c    | 49 +++++++++++++++++++++++--------------------
 3 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/migration/migration.h b/migration/migration.h
index 0df2a187af..3f1927f79c 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -552,6 +552,7 @@ void migration_bitmap_sync_precopy(bool last_stage);
 
 /* migration/block-dirty-bitmap.c */
 void dirty_bitmap_mig_init(void);
+bool should_send_vmdesc(void);
 
 /* migration/block-active.c */
 void migration_block_active_setup(bool active);
diff --git a/migration/migration.c b/migration/migration.c
index 2d1da917c7..bad7b39293 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1406,8 +1406,8 @@ static void migrate_fd_cleanup(MigrationState *s)
 
     g_free(s->hostname);
     s->hostname = NULL;
-    json_writer_free(s->vmdesc);
-    s->vmdesc = NULL;
+
+    g_clear_pointer(&s->vmdesc, json_writer_free);
 
     qemu_savevm_state_cleanup();
 
@@ -1681,7 +1681,10 @@ int migrate_init(MigrationState *s, Error **errp)
     s->migration_thread_running = false;
     error_free(s->error);
     s->error = NULL;
-    s->vmdesc = NULL;
+
+    if (should_send_vmdesc()) {
+        s->vmdesc = json_writer_new(false);
+    }
 
     migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
 
diff --git a/migration/savevm.c b/migration/savevm.c
index 0c4df27177..fa03a0a264 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1231,8 +1231,7 @@ void qemu_savevm_non_migratable_list(strList **reasons)
 void qemu_savevm_state_header(QEMUFile *f)
 {
     MigrationState *s = migrate_get_current();
-
-    s->vmdesc = json_writer_new(false);
+    JSONWriter *vmdesc = s->vmdesc;
 
     trace_savevm_state_header();
     qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
@@ -1241,16 +1240,21 @@ void qemu_savevm_state_header(QEMUFile *f)
     if (s->send_configuration) {
         qemu_put_byte(f, QEMU_VM_CONFIGURATION);
 
-        /*
-         * This starts the main json object and is paired with the
-         * json_writer_end_object in
-         * qemu_savevm_state_complete_precopy_non_iterable
-         */
-        json_writer_start_object(s->vmdesc, NULL);
+        if (vmdesc) {
+            /*
+             * This starts the main json object and is paired with the
+             * json_writer_end_object in
+             * qemu_savevm_state_complete_precopy_non_iterable
+             */
+            json_writer_start_object(vmdesc, NULL);
+            json_writer_start_object(vmdesc, "configuration");
+        }
+
+        vmstate_save_state(f, &vmstate_configuration, &savevm_state, vmdesc);
 
-        json_writer_start_object(s->vmdesc, "configuration");
-        vmstate_save_state(f, &vmstate_configuration, &savevm_state, s->vmdesc);
-        json_writer_end_object(s->vmdesc);
+        if (vmdesc) {
+            json_writer_end_object(vmdesc);
+        }
     }
 }
 
@@ -1296,16 +1300,19 @@ int qemu_savevm_state_setup(QEMUFile *f, Error **errp)
 {
     ERRP_GUARD();
     MigrationState *ms = migrate_get_current();
+    JSONWriter *vmdesc = ms->vmdesc;
     SaveStateEntry *se;
     int ret = 0;
 
-    json_writer_int64(ms->vmdesc, "page_size", qemu_target_page_size());
-    json_writer_start_array(ms->vmdesc, "devices");
+    if (vmdesc) {
+        json_writer_int64(vmdesc, "page_size", qemu_target_page_size());
+        json_writer_start_array(vmdesc, "devices");
+    }
 
     trace_savevm_state_setup();
     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
         if (se->vmsd && se->vmsd->early_setup) {
-            ret = vmstate_save(f, se, ms->vmdesc, errp);
+            ret = vmstate_save(f, se, vmdesc, errp);
             if (ret) {
                 migrate_set_error(ms, *errp);
                 qemu_file_set_error(f, ret);
@@ -1424,7 +1431,7 @@ int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy)
     return all_finished;
 }
 
-static bool should_send_vmdesc(void)
+bool should_send_vmdesc(void)
 {
     MachineState *machine = MACHINE(qdev_get_machine());
 
@@ -1564,21 +1571,17 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
         /* Postcopy stream will still be going */
         qemu_put_byte(f, QEMU_VM_EOF);
 
-        json_writer_end_array(vmdesc);
-        json_writer_end_object(vmdesc);
-        vmdesc_len = strlen(json_writer_get(vmdesc));
+        if (vmdesc) {
+            json_writer_end_array(vmdesc);
+            json_writer_end_object(vmdesc);
+            vmdesc_len = strlen(json_writer_get(vmdesc));
 
-        if (should_send_vmdesc()) {
             qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
             qemu_put_be32(f, vmdesc_len);
             qemu_put_buffer(f, (uint8_t *)json_writer_get(vmdesc), vmdesc_len);
         }
     }
 
-    /* Free it now to detect any inconsistencies. */
-    json_writer_free(vmdesc);
-    ms->vmdesc = NULL;
-
     trace_vmstate_downtime_checkpoint("src-non-iterable-saved");
 
     return 0;
-- 
2.47.0



  parent reply	other threads:[~2025-01-14 23:10 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-14 23:07 [PATCH 00/16] migration: Switchover phase refactoring Peter Xu
2025-01-14 23:07 ` [PATCH 01/16] migration: Remove postcopy implications in should_send_vmdesc() Peter Xu
2025-01-14 23:07 ` Peter Xu [this message]
2025-01-14 23:07 ` [PATCH 03/16] migration: Optimize postcopy on downtime by avoiding JSON writer Peter Xu
2025-01-14 23:07 ` [PATCH 04/16] migration: Avoid two src-downtime-end tracepoints for postcopy Peter Xu
2025-01-14 23:07 ` [PATCH 05/16] migration: Drop inactivate_disk param in qemu_savevm_state_complete* Peter Xu
2025-01-14 23:07 ` [PATCH 06/16] migration: Synchronize all CPU states only for non-iterable dump Peter Xu
2025-01-14 23:07 ` [PATCH 07/16] migration: Adjust postcopy bandwidth during switchover Peter Xu
2025-01-14 23:07 ` [PATCH 08/16] migration: Adjust locking in migration_maybe_pause() Peter Xu
2025-01-14 23:07 ` [PATCH 09/16] migration: Drop cached migration state " Peter Xu
2025-01-14 23:07 ` [PATCH 10/16] migration: Take BQL slightly longer in postcopy_start() Peter Xu
2025-01-14 23:07 ` [PATCH 11/16] migration: Notify COMPLETE once for postcopy Peter Xu
2025-01-14 23:07 ` [PATCH 12/16] migration: Unwrap qemu_savevm_state_complete_precopy() in postcopy Peter Xu
2025-01-14 23:07 ` [PATCH 13/16] migration: Cleanup qemu_savevm_state_complete_precopy() Peter Xu
2025-01-14 23:07 ` [PATCH 14/16] migration: Always set DEVICE state Peter Xu
2025-01-14 23:07 ` [PATCH 15/16] migration: Merge precopy/postcopy on switchover start Peter Xu
2025-01-14 23:07 ` [PATCH 16/16] migration: Trivial cleanup on JSON writer of vmstate_save() Peter Xu
2025-01-15  9:12 ` [PATCH 00/16] migration: Switchover phase refactoring Jiri Denemark
2025-01-15 12:55   ` Peter Xu
2025-01-15 16:13 ` Juraj Marcin
2025-01-15 16:49 ` Fabiano Rosas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250114230746.3268797-3-peterx@redhat.com \
    --to=peterx@redhat.com \
    --cc=farosas@suse.de \
    --cc=jmarcin@redhat.com \
    --cc=jusual@redhat.com \
    --cc=ppandit@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).