all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Fiona Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu 2/6] async snapshot: allow skipping VM start after successful completion
Date: Wed, 27 May 2026 13:00:46 +0200	[thread overview]
Message-ID: <20260527110106.287916-3-f.ebner@proxmox.com> (raw)
In-Reply-To: <20260527110106.287916-1-f.ebner@proxmox.com>

When creating a snapshot for hibernation, the VM must not be started
again after a successful snapshot operation. The VM should remain
stopped so that the management layer can issue a QMP 'quit' without
further activity from the VM.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 ...async-for-background-state-snapshots.patch | 49 +++++++++++++------
 ...add-optional-buffer-size-to-QEMUFile.patch |  6 +--
 ...ckup-Proxmox-backup-patches-for-QEMU.patch |  2 +-
 ...se-migration-blocker-check-for-snaps.patch |  4 +-
 4 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch b/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
index 21ebd78182..192f3abf46 100644
--- a/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
+++ b/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
@@ -34,6 +34,7 @@ Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
      improve setting state in savevm-end handler
      improve runstate preservation
      use dedicated iothread for state file to avoid deadlock, bug #6262
+     add parameter to skip vm start to be used for hibernation
      rebase for 11.0.0]
 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
 ---
@@ -42,13 +43,13 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
  include/migration/snapshot.h |   2 +
  include/monitor/hmp.h        |   3 +
  migration/meson.build        |   1 +
- migration/savevm-async.c     | 586 +++++++++++++++++++++++++++++++++++
+ migration/savevm-async.c     | 597 +++++++++++++++++++++++++++++++++++
  monitor/hmp-cmds.c           |  38 +++
  qapi/migration.json          |  34 ++
- qapi/misc.json               |  18 ++
+ qapi/misc.json               |  25 ++
  qemu-options.hx              |  12 +
  system/vl.c                  |  10 +
- 11 files changed, 734 insertions(+)
+ 11 files changed, 752 insertions(+)
  create mode 100644 migration/savevm-async.c
 
 diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
@@ -146,10 +147,10 @@ index 0222d5ea6e..90d62d5723 100644
  ), gnutls, zlib)
 diff --git a/migration/savevm-async.c b/migration/savevm-async.c
 new file mode 100644
-index 0000000000..d973d8300c
+index 0000000000..2a860f11a1
 --- /dev/null
 +++ b/migration/savevm-async.c
-@@ -0,0 +1,586 @@
+@@ -0,0 +1,597 @@
 +#include "qemu/osdep.h"
 +#include "migration/channel-savevm-async.h"
 +#include "migration/migration.h"
@@ -204,7 +205,8 @@ index 0000000000..d973d8300c
 +    int state;
 +    Error *error;
 +    Error *blocker;
-+    int vm_needs_start;
++    bool vm_needs_start;
++    bool skip_vm_start;
 +    QEMUFile *file;
 +    int64_t total_time;
 +    QEMUBH *finalize_bh;
@@ -219,6 +221,10 @@ index 0000000000..d973d8300c
 +        snap_state.state == SAVE_STATE_ERROR;
 +}
 +
++static bool should_skip_vm_start(void) {
++    return snap_state.state == SAVE_STATE_COMPLETED && snap_state.skip_vm_start;
++}
++
 +SaveVMInfo *qmp_query_savevm(Error **errp)
 +{
 +    SaveVMInfo *info = g_malloc0(sizeof(*info));
@@ -380,7 +386,9 @@ index 0000000000..d973d8300c
 +                            snap_state.state);
 +    }
 +    if (snap_state.vm_needs_start) {
-+        vm_start();
++        if (!should_skip_vm_start()) {
++            vm_start();
++        }
 +        snap_state.vm_needs_start = false;
 +    }
 +
@@ -490,7 +498,8 @@ index 0000000000..d973d8300c
 +    }
 +}
 +
-+void qmp_savevm_start(const char *statefile, Error **errp)
++void qmp_savevm_start(const char *statefile, bool has_skip_vm_start,
++                      bool skip_vm_start, Error **errp)
 +{
 +    Error *local_err = NULL;
 +    MigrationState *ms = migrate_get_current();
@@ -514,6 +523,7 @@ index 0000000000..d973d8300c
 +    snap_state.total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
 +    snap_state.blocker = NULL;
 +    snap_state.target_close_wait = (QemuCoSleep){ .to_wake = NULL };
++    snap_state.skip_vm_start = has_skip_vm_start && skip_vm_start;
 +
 +    if (snap_state.error) {
 +        error_free(snap_state.error);
@@ -657,7 +667,9 @@ index 0000000000..d973d8300c
 +    }
 +
 +    if (snap_state.vm_needs_start) {
-+        vm_start();
++        if (!should_skip_vm_start()) {
++            vm_start();
++        }
 +        snap_state.vm_needs_start = false;
 +    }
 +
@@ -737,7 +749,7 @@ index 0000000000..d973d8300c
 +    return ret;
 +}
 diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
-index bc26b39d70..cbedf13103 100644
+index bc26b39d70..e7afe15e97 100644
 --- a/monitor/hmp-cmds.c
 +++ b/monitor/hmp-cmds.c
 @@ -27,6 +27,7 @@
@@ -757,7 +769,7 @@ index bc26b39d70..cbedf13103 100644
 +    Error *errp = NULL;
 +    const char *statefile = qdict_get_try_str(qdict, "statefile");
 +
-+    qmp_savevm_start(statefile, &errp);
++    qmp_savevm_start(statefile, false, false, &errp);
 +    hmp_handle_error(mon, errp);
 +}
 +
@@ -838,22 +850,29 @@ index 7134d4ce47..8dc8d52b23 100644
  # @query-migrate:
  #
 diff --git a/qapi/misc.json b/qapi/misc.json
-index 28c641fe2f..5d2f12259a 100644
+index 28c641fe2f..cfa10c849b 100644
 --- a/qapi/misc.json
 +++ b/qapi/misc.json
-@@ -449,6 +449,24 @@
+@@ -449,6 +449,31 @@
  ##
  { 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
  
 +##
 +# @savevm-start:
 +#
-+# Prepare for snapshot and halt VM.  Save VM state to statefile.
++# Prepare for snapshot and halt VM.  Save VM state to statefile.  When
++# a @statefile is used, then the VM is only halted before completion.
++# Use @query-savevm to check the state of the operation.
 +#
 +# @statefile: target file that state should be written to.
 +#
++# @skip-vm-start: Do not resume the VM after the snapshot is done
++#                 successfully, even if the VM was running before
++#                 snapshot completion.  Useful for hibernation.
++#
 +##
-+{ 'command': 'savevm-start', 'data': { '*statefile': 'str' } }
++{ 'command': 'savevm-start', 'data': { '*statefile': 'str',
++                                       '*skip-vm-start': 'bool' } }
 +
 +##
 +# @savevm-end:
diff --git a/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch b/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
index 4c8bb44560..ab8aac16a5 100644
--- a/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
+++ b/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
@@ -184,10 +184,10 @@ index a390554208..eda093b16a 100644
  
  G_DEFINE_AUTOPTR_CLEANUP_FUNC(QEMUFile, qemu_fclose)
 diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index d973d8300c..edc4c5b6ac 100644
+index 2a860f11a1..f5a4819e27 100644
 --- a/migration/savevm-async.c
 +++ b/migration/savevm-async.c
-@@ -409,7 +409,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -418,7 +418,7 @@ void qmp_savevm_start(const char *statefile, bool has_skip_vm_start,
  
      QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target,
                                                                 &snap_state.bs_pos));
@@ -196,7 +196,7 @@ index d973d8300c..edc4c5b6ac 100644
  
      if (!snap_state.file) {
          error_setg(errp, "failed to open '%s'", statefile);
-@@ -544,7 +544,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
+@@ -555,7 +555,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
      bdrv_op_block_all(bs, blocker);
  
      /* restore the VM state */
diff --git a/debian/patches/pve/0029-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch b/debian/patches/pve/0029-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
index 73117a6f3a..a4ac880fa7 100644
--- a/debian/patches/pve/0029-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
+++ b/debian/patches/pve/0029-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
@@ -275,7 +275,7 @@ index f747bc3cb2..7aa0ed1b5a 100644
  # libselinux
  selinux = dependency('libselinux',
 diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
-index cbedf13103..33c1c81b3c 100644
+index e7afe15e97..ce374de2ec 100644
 --- a/monitor/hmp-cmds.c
 +++ b/monitor/hmp-cmds.c
 @@ -25,6 +25,7 @@
diff --git a/debian/patches/pve/0046-savevm-async-reuse-migration-blocker-check-for-snaps.patch b/debian/patches/pve/0046-savevm-async-reuse-migration-blocker-check-for-snaps.patch
index 6bd48361f1..df9f3df96b 100644
--- a/debian/patches/pve/0046-savevm-async-reuse-migration-blocker-check-for-snaps.patch
+++ b/debian/patches/pve/0046-savevm-async-reuse-migration-blocker-check-for-snaps.patch
@@ -136,10 +136,10 @@ index b6888daced..80eb0dcd1f 100644
  bool migration_in_postcopy(void);
  bool migration_postcopy_is_alive(MigrationStatus state);
 diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index edc4c5b6ac..acd1a4de6e 100644
+index f5a4819e27..41376406eb 100644
 --- a/migration/savevm-async.c
 +++ b/migration/savevm-async.c
-@@ -375,7 +375,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -384,7 +384,7 @@ void qmp_savevm_start(const char *statefile, bool has_skip_vm_start,
          return;
      }
  
-- 
2.47.3





  parent reply	other threads:[~2026-05-27 11:01 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-27 11:00 [PATCH-SERIES qemu/qemu-server 0/6] fix #6424: avoid timeout issue for QMP 'quit' for bulk suspend Fiona Ebner
2026-05-27 11:00 ` [PATCH qemu 1/6] regenerate patches to restore incremental numbering Fiona Ebner
2026-05-27 11:00 ` Fiona Ebner [this message]
2026-05-27 11:00 ` [PATCH qemu 3/6] update submodule and patches to QEMU 11.0.1 Fiona Ebner
2026-05-27 11:00 ` [PATCH qemu-server 4/6] fix #6424: increase timeout for QMP 'quit' to 60s to avoid issue with bulk suspend Fiona Ebner
2026-05-27 11:00 ` [PATCH qemu-server 5/6] run state: use v5.36 and signatures in module Fiona Ebner
2026-05-27 11:00 ` [PATCH qemu-server 6/6] suspend: skip VM start after successfully saving state Fiona Ebner

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=20260527110106.287916-3-f.ebner@proxmox.com \
    --to=f.ebner@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal