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: [pve-devel] [PATCH qemu-server 16/31] introduce RunState module
Date: Wed, 25 Jun 2025 17:56:39 +0200	[thread overview]
Message-ID: <20250625155751.268047-17-f.ebner@proxmox.com> (raw)
In-Reply-To: <20250625155751.268047-1-f.ebner@proxmox.com>

For now, move only the vm_resume() and vm_suspend() functions. Others
like vm_stop() and friends, vm_reboot() and vm_start() would require
more preparation.

Apart from slightly improving modularity, this is in preparation to
add a BlockJob module, where vm_resume() and vm_suspend() need to be
called after drive-mirror, to avoid a cyclic dependency with the main
QemuServer module.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 src/PVE/API2/Qemu.pm           |   7 +-
 src/PVE/CLI/qm.pm              |   3 +-
 src/PVE/QemuServer.pm          | 175 +------------------------------
 src/PVE/QemuServer/Makefile    |   1 +
 src/PVE/QemuServer/RunState.pm | 185 +++++++++++++++++++++++++++++++++
 5 files changed, 196 insertions(+), 175 deletions(-)
 create mode 100644 src/PVE/QemuServer/RunState.pm

diff --git a/src/PVE/API2/Qemu.pm b/src/PVE/API2/Qemu.pm
index 27426eab..de762cca 100644
--- a/src/PVE/API2/Qemu.pm
+++ b/src/PVE/API2/Qemu.pm
@@ -42,6 +42,7 @@ use PVE::QemuServer::OVMF;
 use PVE::QemuServer::PCI;
 use PVE::QemuServer::QMPHelpers;
 use PVE::QemuServer::RNG;
+use PVE::QemuServer::RunState;
 use PVE::QemuServer::USB;
 use PVE::QemuServer::Virtiofs qw(max_virtiofs);
 use PVE::QemuMigrate;
@@ -3934,7 +3935,7 @@ __PACKAGE__->register_method({
 
             syslog('info', "suspend VM $vmid: $upid\n");
 
-            PVE::QemuServer::vm_suspend($vmid, $skiplock, $todisk, $statestorage);
+            PVE::QemuServer::RunState::vm_suspend($vmid, $skiplock, $todisk, $statestorage);
 
             return;
         };
@@ -4011,7 +4012,7 @@ __PACKAGE__->register_method({
             syslog('info', "resume VM $vmid: $upid\n");
 
             if (!$to_disk_suspended) {
-                PVE::QemuServer::vm_resume($vmid, $skiplock, $nocheck);
+                PVE::QemuServer::RunState::vm_resume($vmid, $skiplock, $nocheck);
             } else {
                 my $storecfg = PVE::Storage::config();
                 PVE::QemuServer::vm_start($storecfg, $vmid, { skiplock => $skiplock });
@@ -6642,7 +6643,7 @@ __PACKAGE__->register_method({
                 },
                 'resume' => sub {
                     if (PVE::QemuServer::Helpers::vm_running_locally($state->{vmid})) {
-                        PVE::QemuServer::vm_resume($state->{vmid}, 1, 1);
+                        PVE::QemuServer::RunState::vm_resume($state->{vmid}, 1, 1);
                     } else {
                         die "VM $state->{vmid} not running\n";
                     }
diff --git a/src/PVE/CLI/qm.pm b/src/PVE/CLI/qm.pm
index 23f71ab0..f3e9a702 100755
--- a/src/PVE/CLI/qm.pm
+++ b/src/PVE/CLI/qm.pm
@@ -36,6 +36,7 @@ use PVE::QemuServer::Agent;
 use PVE::QemuServer::ImportDisk;
 use PVE::QemuServer::Monitor qw(mon_cmd);
 use PVE::QemuServer::QMPHelpers;
+use PVE::QemuServer::RunState;
 use PVE::QemuServer;
 
 use PVE::CLIHandler;
@@ -465,7 +466,7 @@ __PACKAGE__->register_method({
                 # check_running and vm_resume with nocheck, since local node
                 # might not have processed config move/rename yet
                 if (PVE::QemuServer::check_running($vmid, 1)) {
-                    eval { PVE::QemuServer::vm_resume($vmid, 1, 1); };
+                    eval { PVE::QemuServer::RunState::vm_resume($vmid, 1, 1); };
                     if ($@) {
                         $tunnel_write->("ERR: resume failed - $@");
                     } else {
diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 3c612b44..942a1363 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -81,6 +81,7 @@ use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port
 use PVE::QemuServer::QemuImage;
 use PVE::QemuServer::QMPHelpers qw(qemu_deviceadd qemu_devicedel qemu_objectadd qemu_objectdel);
 use PVE::QemuServer::RNG qw(parse_rng print_rng_device_commandline print_rng_object_commandline);
+use PVE::QemuServer::RunState;
 use PVE::QemuServer::StateFile;
 use PVE::QemuServer::USB;
 use PVE::QemuServer::Virtiofs qw(max_virtiofs start_all_virtiofsd);
@@ -5359,7 +5360,7 @@ sub vm_start {
             if ($has_backup_lock && $running) {
                 # a backup is currently running, attempt to start the guest in the
                 # existing QEMU instance
-                return vm_resume($vmid);
+                return PVE::QemuServer::RunState::vm_resume($vmid);
             }
 
             PVE::QemuConfig->check_lock($conf)
@@ -6165,174 +6166,6 @@ sub vm_reboot {
     );
 }
 
-# note: if using the statestorage parameter, the caller has to check privileges
-sub vm_suspend {
-    my ($vmid, $skiplock, $includestate, $statestorage) = @_;
-
-    my $conf;
-    my $path;
-    my $storecfg;
-    my $vmstate;
-
-    PVE::QemuConfig->lock_config(
-        $vmid,
-        sub {
-
-            $conf = PVE::QemuConfig->load_config($vmid);
-
-            my $is_backing_up = PVE::QemuConfig->has_lock($conf, 'backup');
-            PVE::QemuConfig->check_lock($conf)
-                if !($skiplock || $is_backing_up);
-
-            die "cannot suspend to disk during backup\n"
-                if $is_backing_up && $includestate;
-
-            PVE::QemuMigrate::Helpers::check_non_migratable_resources($conf, $includestate, 0);
-
-            if ($includestate) {
-                $conf->{lock} = 'suspending';
-                my $date = strftime("%Y-%m-%d", localtime(time()));
-                $storecfg = PVE::Storage::config();
-                if (!$statestorage) {
-                    $statestorage = PVE::QemuConfig::find_vmstate_storage($conf, $storecfg);
-                    # check permissions for the storage
-                    my $rpcenv = PVE::RPCEnvironment::get();
-                    if ($rpcenv->{type} ne 'cli') {
-                        my $authuser = $rpcenv->get_user();
-                        $rpcenv->check(
-                            $authuser,
-                            "/storage/$statestorage",
-                            ['Datastore.AllocateSpace'],
-                        );
-                    }
-                }
-
-                $vmstate = PVE::QemuConfig->__snapshot_save_vmstate(
-                    $vmid, $conf, "suspend-$date", $storecfg, $statestorage, 1,
-                );
-                $path = PVE::Storage::path($storecfg, $vmstate);
-                PVE::QemuConfig->write_config($vmid, $conf);
-            } else {
-                mon_cmd($vmid, "stop");
-            }
-        },
-    );
-
-    if ($includestate) {
-        # save vm state
-        PVE::Storage::activate_volumes($storecfg, [$vmstate]);
-
-        eval {
-            PVE::QemuMigrate::Helpers::set_migration_caps($vmid, 1);
-            mon_cmd($vmid, "savevm-start", statefile => $path);
-            for (;;) {
-                my $state = mon_cmd($vmid, "query-savevm");
-                if (!$state->{status}) {
-                    die "savevm not active\n";
-                } elsif ($state->{status} eq 'active') {
-                    sleep(1);
-                    next;
-                } elsif ($state->{status} eq 'completed') {
-                    print "State saved, quitting\n";
-                    last;
-                } elsif ($state->{status} eq 'failed' && $state->{error}) {
-                    die "query-savevm failed with error '$state->{error}'\n";
-                } else {
-                    die "query-savevm returned status '$state->{status}'\n";
-                }
-            }
-        };
-        my $err = $@;
-
-        PVE::QemuConfig->lock_config(
-            $vmid,
-            sub {
-                $conf = PVE::QemuConfig->load_config($vmid);
-                if ($err) {
-                    # cleanup, but leave suspending lock, to indicate something went wrong
-                    eval {
-                        eval { mon_cmd($vmid, "savevm-end"); };
-                        warn $@ if $@;
-                        PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
-                        PVE::Storage::vdisk_free($storecfg, $vmstate);
-                        delete $conf->@{qw(vmstate runningmachine runningcpu)};
-                        PVE::QemuConfig->write_config($vmid, $conf);
-                    };
-                    warn $@ if $@;
-                    die $err;
-                }
-
-                die "lock changed unexpectedly\n"
-                    if !PVE::QemuConfig->has_lock($conf, 'suspending');
-
-                mon_cmd($vmid, "quit");
-                $conf->{lock} = 'suspended';
-                PVE::QemuConfig->write_config($vmid, $conf);
-            },
-        );
-    }
-}
-
-# $nocheck is set when called as part of a migration - in this context the
-# location of the config file (source or target node) is not deterministic,
-# since migration cannot wait for pmxcfs to process the rename
-sub vm_resume {
-    my ($vmid, $skiplock, $nocheck) = @_;
-
-    PVE::QemuConfig->lock_config(
-        $vmid,
-        sub {
-            # After migration, the VM might not immediately be able to respond to QMP commands, because
-            # activating the block devices might take a bit of time.
-            my $res = mon_cmd($vmid, 'query-status', timeout => 60);
-            my $resume_cmd = 'cont';
-            my $reset = 0;
-            my $conf;
-            if ($nocheck) {
-                $conf = eval { PVE::QemuConfig->load_config($vmid) }; # try on target node
-                if ($@) {
-                    my $vmlist = PVE::Cluster::get_vmlist();
-                    if (exists($vmlist->{ids}->{$vmid})) {
-                        my $node = $vmlist->{ids}->{$vmid}->{node};
-                        $conf = eval { PVE::QemuConfig->load_config($vmid, $node) }; # try on source node
-                    }
-                    if (!$conf) {
-                        PVE::Cluster::cfs_update(); # vmlist was wrong, invalidate cache
-                        $conf = PVE::QemuConfig->load_config($vmid); # last try on target node again
-                    }
-                }
-            } else {
-                $conf = PVE::QemuConfig->load_config($vmid);
-            }
-
-            die "VM $vmid is a template and cannot be resumed!\n"
-                if PVE::QemuConfig->is_template($conf);
-
-            if ($res->{status}) {
-                return if $res->{status} eq 'running'; # job done, go home
-                $resume_cmd = 'system_wakeup' if $res->{status} eq 'suspended';
-                $reset = 1 if $res->{status} eq 'shutdown';
-            }
-
-            if (!$nocheck) {
-                PVE::QemuConfig->check_lock($conf)
-                    if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
-            }
-
-            if ($reset) {
-                # required if a VM shuts down during a backup and we get a resume
-                # request before the backup finishes for example
-                mon_cmd($vmid, "system_reset");
-            }
-
-            PVE::QemuServer::Network::add_nets_bridge_fdb($conf, $vmid)
-                if $resume_cmd eq 'cont';
-
-            mon_cmd($vmid, $resume_cmd);
-        },
-    );
-}
-
 sub vm_sendkey {
     my ($vmid, $skiplock, $key) = @_;
 
@@ -7967,7 +7800,7 @@ sub qemu_drive_mirror_monitor {
                         warn $@ if $@;
                     } else {
                         print "suspend vm\n";
-                        eval { PVE::QemuServer::vm_suspend($vmid, 1); };
+                        eval { PVE::QemuServer::RunState::vm_suspend($vmid, 1); };
                         warn $@ if $@;
                     }
 
@@ -7980,7 +7813,7 @@ sub qemu_drive_mirror_monitor {
                         warn $@ if $@;
                     } else {
                         print "resume vm\n";
-                        eval { PVE::QemuServer::vm_resume($vmid, 1, 1); };
+                        eval { PVE::QemuServer::RunState::vm_resume($vmid, 1, 1); };
                         warn $@ if $@;
                     }
 
diff --git a/src/PVE/QemuServer/Makefile b/src/PVE/QemuServer/Makefile
index e30c571c..5f475c73 100644
--- a/src/PVE/QemuServer/Makefile
+++ b/src/PVE/QemuServer/Makefile
@@ -20,6 +20,7 @@ SOURCES=Agent.pm	\
 	QemuImage.pm	\
 	QMPHelpers.pm	\
 	RNG.pm		\
+	RunState.pm	\
 	StateFile.pm	\
 	USB.pm		\
 	Virtiofs.pm
diff --git a/src/PVE/QemuServer/RunState.pm b/src/PVE/QemuServer/RunState.pm
new file mode 100644
index 00000000..05e7fb47
--- /dev/null
+++ b/src/PVE/QemuServer/RunState.pm
@@ -0,0 +1,185 @@
+package PVE::QemuServer::RunState;
+
+use strict;
+use warnings;
+
+use POSIX qw(strftime);
+
+use PVE::Cluster;
+use PVE::RPCEnvironment;
+use PVE::Storage;
+
+use PVE::QemuConfig;
+use PVE::QemuMigrate::Helpers;
+use PVE::QemuServer::Monitor qw(mon_cmd);
+use PVE::QemuServer::Network;
+
+# note: if using the statestorage parameter, the caller has to check privileges
+sub vm_suspend {
+    my ($vmid, $skiplock, $includestate, $statestorage) = @_;
+
+    my $conf;
+    my $path;
+    my $storecfg;
+    my $vmstate;
+
+    PVE::QemuConfig->lock_config(
+        $vmid,
+        sub {
+
+            $conf = PVE::QemuConfig->load_config($vmid);
+
+            my $is_backing_up = PVE::QemuConfig->has_lock($conf, 'backup');
+            PVE::QemuConfig->check_lock($conf)
+                if !($skiplock || $is_backing_up);
+
+            die "cannot suspend to disk during backup\n"
+                if $is_backing_up && $includestate;
+
+            PVE::QemuMigrate::Helpers::check_non_migratable_resources($conf, $includestate, 0);
+
+            if ($includestate) {
+                $conf->{lock} = 'suspending';
+                my $date = strftime("%Y-%m-%d", localtime(time()));
+                $storecfg = PVE::Storage::config();
+                if (!$statestorage) {
+                    $statestorage = PVE::QemuConfig::find_vmstate_storage($conf, $storecfg);
+                    # check permissions for the storage
+                    my $rpcenv = PVE::RPCEnvironment::get();
+                    if ($rpcenv->{type} ne 'cli') {
+                        my $authuser = $rpcenv->get_user();
+                        $rpcenv->check(
+                            $authuser,
+                            "/storage/$statestorage",
+                            ['Datastore.AllocateSpace'],
+                        );
+                    }
+                }
+
+                $vmstate = PVE::QemuConfig->__snapshot_save_vmstate(
+                    $vmid, $conf, "suspend-$date", $storecfg, $statestorage, 1,
+                );
+                $path = PVE::Storage::path($storecfg, $vmstate);
+                PVE::QemuConfig->write_config($vmid, $conf);
+            } else {
+                mon_cmd($vmid, "stop");
+            }
+        },
+    );
+
+    if ($includestate) {
+        # save vm state
+        PVE::Storage::activate_volumes($storecfg, [$vmstate]);
+
+        eval {
+            PVE::QemuMigrate::Helpers::set_migration_caps($vmid, 1);
+            mon_cmd($vmid, "savevm-start", statefile => $path);
+            for (;;) {
+                my $state = mon_cmd($vmid, "query-savevm");
+                if (!$state->{status}) {
+                    die "savevm not active\n";
+                } elsif ($state->{status} eq 'active') {
+                    sleep(1);
+                    next;
+                } elsif ($state->{status} eq 'completed') {
+                    print "State saved, quitting\n";
+                    last;
+                } elsif ($state->{status} eq 'failed' && $state->{error}) {
+                    die "query-savevm failed with error '$state->{error}'\n";
+                } else {
+                    die "query-savevm returned status '$state->{status}'\n";
+                }
+            }
+        };
+        my $err = $@;
+
+        PVE::QemuConfig->lock_config(
+            $vmid,
+            sub {
+                $conf = PVE::QemuConfig->load_config($vmid);
+                if ($err) {
+                    # cleanup, but leave suspending lock, to indicate something went wrong
+                    eval {
+                        eval { mon_cmd($vmid, "savevm-end"); };
+                        warn $@ if $@;
+                        PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
+                        PVE::Storage::vdisk_free($storecfg, $vmstate);
+                        delete $conf->@{qw(vmstate runningmachine runningcpu)};
+                        PVE::QemuConfig->write_config($vmid, $conf);
+                    };
+                    warn $@ if $@;
+                    die $err;
+                }
+
+                die "lock changed unexpectedly\n"
+                    if !PVE::QemuConfig->has_lock($conf, 'suspending');
+
+                mon_cmd($vmid, "quit");
+                $conf->{lock} = 'suspended';
+                PVE::QemuConfig->write_config($vmid, $conf);
+            },
+        );
+    }
+}
+
+# $nocheck is set when called as part of a migration - in this context the
+# location of the config file (source or target node) is not deterministic,
+# since migration cannot wait for pmxcfs to process the rename
+sub vm_resume {
+    my ($vmid, $skiplock, $nocheck) = @_;
+
+    PVE::QemuConfig->lock_config(
+        $vmid,
+        sub {
+            # After migration, the VM might not immediately be able to respond to QMP commands, because
+            # activating the block devices might take a bit of time.
+            my $res = mon_cmd($vmid, 'query-status', timeout => 60);
+            my $resume_cmd = 'cont';
+            my $reset = 0;
+            my $conf;
+            if ($nocheck) {
+                $conf = eval { PVE::QemuConfig->load_config($vmid) }; # try on target node
+                if ($@) {
+                    my $vmlist = PVE::Cluster::get_vmlist();
+                    if (exists($vmlist->{ids}->{$vmid})) {
+                        my $node = $vmlist->{ids}->{$vmid}->{node};
+                        $conf = eval { PVE::QemuConfig->load_config($vmid, $node) }; # try on source node
+                    }
+                    if (!$conf) {
+                        PVE::Cluster::cfs_update(); # vmlist was wrong, invalidate cache
+                        $conf = PVE::QemuConfig->load_config($vmid); # last try on target node again
+                    }
+                }
+            } else {
+                $conf = PVE::QemuConfig->load_config($vmid);
+            }
+
+            die "VM $vmid is a template and cannot be resumed!\n"
+                if PVE::QemuConfig->is_template($conf);
+
+            if ($res->{status}) {
+                return if $res->{status} eq 'running'; # job done, go home
+                $resume_cmd = 'system_wakeup' if $res->{status} eq 'suspended';
+                $reset = 1 if $res->{status} eq 'shutdown';
+            }
+
+            if (!$nocheck) {
+                PVE::QemuConfig->check_lock($conf)
+                    if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
+            }
+
+            if ($reset) {
+                # required if a VM shuts down during a backup and we get a resume
+                # request before the backup finishes for example
+                mon_cmd($vmid, "system_reset");
+            }
+
+            PVE::QemuServer::Network::add_nets_bridge_fdb($conf, $vmid)
+                if $resume_cmd eq 'cont';
+
+            mon_cmd($vmid, $resume_cmd);
+        },
+    );
+}
+
+1;
-- 
2.47.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2025-06-25 16:02 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-25 15:56 [pve-devel] [PATCH-SERIES qemu-server 00/31] preparation for blockdev, part three Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 01/31] print ovmf commandline: collect hardware parameters into hash argument Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 02/31] introduce OVMF module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 03/31] ovmf: add support for using blockdev Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 04/31] cfg2cmd: ovmf: support print_ovmf_commandline() returning machine flags Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 05/31] assume that SDN is available Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 06/31] schema: remove unused pve-qm-ipconfig standard option Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 07/31] remove unused $nic_model_list_txt variable Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 08/31] introduce Network module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 09/31] agent: drop unused $noerr argument from helpers Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 10/31] agent: code style: order module imports according to style guide Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 11/31] agent: avoid dependency on QemuConfig module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 12/31] agent: avoid use of deprecated check_running() function Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 13/31] agent: move qga_check_running() to agent module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 14/31] move find_vmstate_storage() helper to QemuConfig module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 15/31] introduce QemuMigrate::Helpers module Fiona Ebner
2025-06-25 15:56 ` Fiona Ebner [this message]
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 17/31] code cleanup: drive mirror: do not prefix calls to function in the same module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 18/31] introduce BlockJob module Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 19/31] drive: die in get_drive_id() if argument misses relevant members Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 20/31] block job: add and use wrapper for mirror Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 21/31] drive mirror: add variable for device ID and make name for drive ID precise Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 22/31] test: migration: factor out common mocking for mirror Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 23/31] block job: factor out helper for common mirror QMP options Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 24/31] block job: add blockdev mirror Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 25/31] blockdev: support using zeroinit filter Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [PATCH qemu-server 26/31] blockdev: make some functions private Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 27/31] clone disk: skip check for aio=default (io_uring) compatibility starting with machine version 10.0 Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 28/31] print drive device: don't reference any drive for 'none' " Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 29/31] blockdev: add support for NBD paths Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 30/31] command line: switch to blockdev starting with machine version 10.0 Fiona Ebner
2025-06-25 15:56 ` [pve-devel] [RFC qemu-server 31/31] test: migration: update running machine to 10.0 Fiona Ebner
2025-06-26 13:09 ` [pve-devel] partially-applied: [PATCH-SERIES qemu-server 00/31] preparation for blockdev, part three Fabian Grünbichler

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=20250625155751.268047-17-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