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-server 6/9] partially fix #7836: allow mirror for drive with read-only flag when using blockdev
Date: Fri, 24 Jul 2026 16:32:27 +0200	[thread overview]
Message-ID: <20260724143240.211130-7-f.ebner@proxmox.com> (raw)
In-Reply-To: <20260724143240.211130-1-f.ebner@proxmox.com>

The switch to -blockdev in Proxmox VE 9 introduced a regression,
making clone of a VM with a read-only drive fail. The reason is that
the target node is also attached as read-only and thus cannot serve as
the mirror target. To fix the issue, open the mirror target as
writeable initially and in case the VM switched to the new drive,
re-open as read-only later. Note that the drive device is always
read-only for the guest, because the top throttle node is.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 src/PVE/QemuServer/BlockJob.pm | 38 ++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/src/PVE/QemuServer/BlockJob.pm b/src/PVE/QemuServer/BlockJob.pm
index 7be5a1e4..bce350da 100644
--- a/src/PVE/QemuServer/BlockJob.pm
+++ b/src/PVE/QemuServer/BlockJob.pm
@@ -80,6 +80,25 @@ sub qemu_blockjobs_cancel {
     }
 }
 
+sub check_reopen_after_complete {
+    my ($job_info) = @_;
+
+    my $reopen_info = $job_info->{'target-reopen-upon-complete'} or return;
+
+    my ($storecfg, $vmid, $drive, $options) = $reopen_info->@{qw(storecfg vmid drive options)};
+
+    # Re-opening is currently only done to restore read-only below the throttle node. For the guest,
+    # the drive will be seen as read-only if the throttle node already is, so a failure here is not
+    # too bad.
+    eval { PVE::QemuServer::Blockdev::reopen($storecfg, $vmid, $drive, $options); };
+    if (my $err = $@) {
+        my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+        print "$drive_id: failed to re-apply read-only flag below throttle - $err\n";
+    }
+
+    return;
+}
+
 # $completion can be either
 # 'complete': wait until all jobs are ready, job-complete them (default)
 # 'cancel': wait until all jobs are ready, block-job-cancel them
@@ -210,6 +229,7 @@ sub monitor {
                             if ($completion eq 'complete') {
                                 $detach_node_name = $jobs->{$job_id}->{'source-node-name'};
                                 qmp_cmd($qmp_peer, 'job-complete', id => $job_id);
+                                check_reopen_after_complete($jobs->{$job_id});
                             } elsif ($completion eq 'cancel') {
                                 $detach_node_name = $jobs->{$job_id}->{'target-node-name'};
                                 qmp_cmd($qmp_peer, 'block-job-cancel', device => $job_id);
@@ -519,6 +539,14 @@ sub blockdev_mirror {
         }
     }
 
+    # If the drive is configured as read-only, attach the mirror target as writeable initially and
+    # re-open it as read-only later. For the guest, the drive will be seen as read-only if the
+    # throttle node is, even in case mirror switches to the new target.
+    my $dest_is_read_only = $dest_drive->{ro};
+    if ($dest_is_read_only) {
+        $attach_dest_opts->{'read-only'} = 0;
+    }
+
     # Note that if 'aio' is not explicitly set, i.e. default, it can change if source and target
     # don't both allow or both not allow 'io_uring' as the default.
     my ($target_node_name) =
@@ -531,6 +559,16 @@ sub blockdev_mirror {
         'target-node-name' => $target_node_name,
     };
 
+    if ($dest_is_read_only) {
+        delete($attach_dest_opts->{'read-only'}); # remove the override for re-opening later
+        $jobs->{$jobid}->{'target-reopen-upon-complete'} = {
+            storecfg => $storecfg,
+            vmid => $vmid,
+            drive => $dest_drive,
+            options => $attach_dest_opts,
+        };
+    }
+
     my $qmp_opts = common_mirror_qmp_options(
         $vmid, $device_id, $target_node_name, $source->{bitmap}, $options->{bwlimit},
     );
-- 
2.47.3





  parent reply	other threads:[~2026-07-24 14:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-24 14:32 [PATCH-SERIES qemu/qemu-server 0/9] mirror: fix regressions with blockdev and allow migration with 'ro' flag Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu 1/9] add patch to allow mirror job to use non-root block node Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu-server 2/9] partially fix #7299: fix regression with guest IO limits applying to mirror job Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu-server 3/9] partially fix #7299: migrate: fix regression with guest IO limits applying to NBD export Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu-server 4/9] blockdev: attach: support explicitly attaching as writeable Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu-server 5/9] blockdev: implement reopen function Fiona Ebner
2026-07-24 14:32 ` Fiona Ebner [this message]
2026-07-24 14:32 ` [PATCH qemu-server 7/9] qm: schema: declare 'nbdstop' command as being for internal use only Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu-server 8/9] migrate: log messages from remote nbdstop command Fiona Ebner
2026-07-24 14:32 ` [PATCH qemu-server 9/9] partially fix #7836: allow migration for drive with read-only flag when using blockdev 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=20260724143240.211130-7-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