public inbox for pve-devel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal