[pve-devel] [PATCH qemu-server 4/4] fix #4525: clone disk: disallow mirror if it might cause problems with io_uring

Fiona Ebner f.ebner at proxmox.com
Fri Feb 10 15:19:12 CET 2023

The target of the drive-mirror operation is opened with (essentially)
the same flags as the source in QEMU, in particular whether io_uring
should be used is inherited.

But io_uring currently causes problems in combination with certain
storage types, sometimes even leading to crashes (LVM with Linux 6.1).
Just disallow live cloning of drives when the source uses io_uring and
the target storage is not ready for it. There is one exception, namely
when source and target storage are the same. In that case, just assume
it will keep working for the target.

Migration does not seem to be affected, because there, the target VM
opens the images with the checked aio setting and then NBD exports of
those are used as the targets for mirroring.

It can be that the default determined for the source is not what's
actually used, because after a drive-mirror to a storage with a
different default, it will still use the default from the old storage.
Unfortunately, aio doesn't seem to be part of the 'query-block' QMP
command's result, so just tolerate this edge case.

The check can be removed if either
1. drive-mirror learns to open the target with a different aio setting
or more ideally
2. there are no more bad storages for io_uring.

Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
 PVE/QemuServer.pm | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index d4b1a984..6121bcdd 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -7957,6 +7957,33 @@ sub qemu_blockjobs_cancel {
+# Check for bug #4525: drive-mirror will open the target drive with the same aio setting as the
+# source, but some storages have problems with io_uring, sometimes even leading to crashes.
+my sub clone_disk_check_io_uring {
+    my ($src_drive, $storecfg, $src_storeid, $dst_storeid, $use_drive_mirror) = @_;
+    return if !$use_drive_mirror;
+    # Don't complain when not changing storage.
+    # Assume if it works for the source, it'll work for the target too.
+    return if $src_storeid eq $dst_storeid;
+    my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
+    my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
+    my $cache_direct = drive_uses_cache_direct($src_drive);
+    my $src_uses_io_uring;
+    if ($src_drive->{aio}) {
+	$src_uses_io_uring = $src_drive->{aio} eq 'io_uring';
+    } else {
+	$src_uses_io_uring = storage_allows_io_uring_default($src_scfg, $cache_direct);
+    }
+    die "target storage is known to cause issues with aio=io_uring (used by current drive)\n"
+	if $src_uses_io_uring && !storage_allows_io_uring_default($dst_scfg, $cache_direct);
 sub clone_disk {
     my ($storecfg, $source, $dest, $full, $newvollist, $jobs, $completion, $qga, $bwlimit) = @_;
@@ -7992,9 +8019,8 @@ sub clone_disk {
 	$newvolid = PVE::Storage::vdisk_clone($storecfg,  $drive->{file}, $newvmid, $snapname);
 	push @$newvollist, $newvolid;
     } else {
-	my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
-	$storeid = $storage if $storage;
+	my ($src_storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
+	my $storeid = $storage || $src_storeid;
 	my $dst_format = resolve_dst_disk_format($storecfg, $storeid, $volname, $format);
@@ -8014,6 +8040,8 @@ sub clone_disk {
 	    $dst_format = 'raw';
 	    $size = PVE::QemuServer::Drive::TPMSTATE_DISK_SIZE;
 	} else {
+	    clone_disk_check_io_uring($drive, $storecfg, $src_storeid, $storeid, $use_drive_mirror);
 	    ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 10);
 	$newvolid = PVE::Storage::vdisk_alloc(

More information about the pve-devel mailing list