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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox