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-server] clone disk: refactor code to avoid goto
Date: Wed, 15 Jul 2026 16:26:00 +0200	[thread overview]
Message-ID: <20260715142608.152953-1-f.ebner@proxmox.com> (raw)

No functional change intended.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---

The new proxmox-perltidy=1.3 version wants to indent the label:

* do not outdent labels: in the Proxmox codebases labels are used for
labeled blocks and loops (next <label>), not as global goto targets,
so outdenting them is unhelpful; where it is wanted, guard the label
with '#<<<'/'#>>>' markers.

Instead of adding markers to prevent this, just get rid of the goto.
This is the only goto in the codebase except one for AUTOLOAD in
RESTHandler.pm.

 src/PVE/QemuServer.pm | 121 ++++++++++++++++++++++++------------------
 1 file changed, 68 insertions(+), 53 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 191ae549..774adcc7 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -7923,6 +7923,67 @@ my sub clone_disk_check_io_uring {
         if $src_uses_io_uring && !storage_allows_io_uring_default($dst_scfg, $cache_direct);
 }
 
+my sub clone_disk_copy_data {
+    my ($storecfg, $source, $dest, $use_drive_mirror, $jobs, $completion, $qga, $bwlimit) = @_;
+
+    my ($vmid, $drive, $size, $snapname) = $source->@{qw(vmid drive size snapname)};
+    my ($newvmid, $newvolid, $dst_drivename, $dst_format) =
+        $dest->@{qw(vmid volid drivename format)};
+
+    my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
+    if ($use_drive_mirror) {
+        my $source_info = { vmid => $vmid, drive => $drive };
+        my $dest_info = { volid => $newvolid };
+        $dest_info->{'zero-initialized'} = 1 if $sparseinit;
+        $dest_info->{vmid} = $newvmid if defined($newvmid);
+        my $mirror_opts = {};
+        $mirror_opts->{'guest-agent'} = $qga;
+        $mirror_opts->{bwlimit} = $bwlimit if defined($bwlimit);
+        PVE::QemuServer::BlockJob::mirror(
+            $source_info,
+            $dest_info,
+            $jobs,
+            $completion,
+            $mirror_opts,
+        );
+    } else {
+        if ($dst_drivename eq 'efidisk0') {
+            # the relevant data on the efidisk may be smaller than the source
+            # e.g. on RBD/ZFS, so we use dd to copy only the amount
+            # that is given by the OVMF_VARS.fd
+            my $src_path = PVE::Storage::path($storecfg, $drive->{file}, $snapname);
+            my $dst_path = PVE::Storage::path($storecfg, $newvolid);
+
+            my $src_format = (PVE::Storage::parse_volname($storecfg, $drive->{file}))[6];
+
+            # better for Ceph if block size is not too small, see bug #3324
+            my $bs = 1024 * 1024;
+
+            my $cmd = ['qemu-img', 'dd', '-n', '-f', $src_format, '-O', $dst_format];
+
+            if ($src_format eq 'qcow2' && $snapname) {
+                die "cannot clone qcow2 EFI disk snapshot - requires QEMU >= 6.2\n"
+                    if !min_version(kvm_user_version(), 6, 2);
+
+                my $method = PVE::Storage::volume_qemu_snapshot_method($storecfg, $drive->{file});
+                # in case of snapshot-as-volume-chain, $src_path points to the snapshot volume
+                push $cmd->@*, '-l', $snapname if $method eq 'qemu';
+            }
+            push $cmd->@*, "bs=$bs", "osize=$size", "if=$src_path", "of=$dst_path";
+            run_command($cmd);
+        } else {
+            my $opts = {
+                bwlimit => $bwlimit,
+                'is-zero-initialized' => $sparseinit,
+                snapname => $snapname,
+            };
+            PVE::QemuServer::QemuImage::convert($drive->{file}, $newvolid, $size, $opts);
+        }
+    }
+
+    return;
+}
+
 sub clone_disk {
     my ($storecfg, $source, $dest, $full, $newvollist, $jobs, $completion, $qga, $bwlimit) = @_;
 
@@ -7967,6 +8028,7 @@ sub clone_disk {
             warn "format '$format' is not supported by the target storage '$storeid' - using"
                 . " '$dst_format' instead\n";
         }
+        $dest->{format} = $dst_format;
 
         my $name = undef;
         my $size = undef;
@@ -7989,6 +8051,7 @@ sub clone_disk {
 
             $size = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 10);
         }
+        $source->{size} = $size;
         $newvolid = PVE::Storage::vdisk_alloc(
             $storecfg,
             $storeid,
@@ -7998,6 +8061,7 @@ sub clone_disk {
             ($size / 1024),
         );
         push @$newvollist, $newvolid;
+        $dest->{volid} = $newvolid;
 
         print("allocated target volume '$newvolid'\n");
 
@@ -8012,63 +8076,14 @@ sub clone_disk {
                     vm_qmp_peer($vmid), $newvmid, $jobs, $completion, $qga,
                 );
             }
-            goto no_data_clone;
-        }
-
-        my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
-        if ($use_drive_mirror) {
-            my $source_info = { vmid => $vmid, drive => $drive };
-            my $dest_info = { volid => $newvolid };
-            $dest_info->{'zero-initialized'} = 1 if $sparseinit;
-            $dest_info->{vmid} = $newvmid if defined($newvmid);
-            my $mirror_opts = {};
-            $mirror_opts->{'guest-agent'} = $qga;
-            $mirror_opts->{bwlimit} = $bwlimit if defined($bwlimit);
-            PVE::QemuServer::BlockJob::mirror(
-                $source_info,
-                $dest_info,
-                $jobs,
-                $completion,
-                $mirror_opts,
-            );
+            # No data needs to be copied for the cloudinit drive.
         } else {
-            if ($dst_drivename eq 'efidisk0') {
-                # the relevant data on the efidisk may be smaller than the source
-                # e.g. on RBD/ZFS, so we use dd to copy only the amount
-                # that is given by the OVMF_VARS.fd
-                my $src_path = PVE::Storage::path($storecfg, $drive->{file}, $snapname);
-                my $dst_path = PVE::Storage::path($storecfg, $newvolid);
-
-                my $src_format = (PVE::Storage::parse_volname($storecfg, $drive->{file}))[6];
-
-                # better for Ceph if block size is not too small, see bug #3324
-                my $bs = 1024 * 1024;
-
-                my $cmd = ['qemu-img', 'dd', '-n', '-f', $src_format, '-O', $dst_format];
-
-                if ($src_format eq 'qcow2' && $snapname) {
-                    die "cannot clone qcow2 EFI disk snapshot - requires QEMU >= 6.2\n"
-                        if !min_version(kvm_user_version(), 6, 2);
-
-                    my $method =
-                        PVE::Storage::volume_qemu_snapshot_method($storecfg, $drive->{file});
-                    # in case of snapshot-as-volume-chain, $src_path points to the snapshot volume
-                    push $cmd->@*, '-l', $snapname if $method eq 'qemu';
-                }
-                push $cmd->@*, "bs=$bs", "osize=$size", "if=$src_path", "of=$dst_path";
-                run_command($cmd);
-            } else {
-                my $opts = {
-                    bwlimit => $bwlimit,
-                    'is-zero-initialized' => $sparseinit,
-                    snapname => $snapname,
-                };
-                PVE::QemuServer::QemuImage::convert($drive->{file}, $newvolid, $size, $opts);
-            }
+            clone_disk_copy_data(
+                $storecfg, $source, $dest, $use_drive_mirror, $jobs, $completion, $qga, $bwlimit,
+            );
         }
     }
 
-no_data_clone:
     my $size = eval { PVE::Storage::volume_size_info($storecfg, $newvolid, 10) };
 
     my $disk = dclone($drive);
-- 
2.47.3





                 reply	other threads:[~2026-07-15 14:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260715142608.152953-1-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