Skip to content

Commit 9af031e

Browse files
committed
storpool: enable direct I/O for qemu-img volume copy to secondary storage
Fix qemu-img convert failures when copying StorPool volumes to secondary storage (NFS) during offline volume migration. Symptom: Offline migration of a StorPool volume to another primary storage (e.g. Linstor) fails with: qemu-img: error while writing sector 4202495: Invalid argument This happens in StorPoolCopyVolumeToSecondaryCommand which creates a temporary StorPool snapshot, attaches it as a block device, and copies it via qemu-img convert to a file on NFS secondary storage. Root cause: The basic QemuImg(timeout) constructor creates qemu-img convert commands without any I/O mode flags. On certain NFS configurations, buffered I/O can cause EINVAL errors at specific sector boundaries when writing large volumes from a raw block device source. Fix: Use the 3-parameter constructor QemuImg(timeout, skipZero=false, noCache=true): - skipZero=false: Do NOT enable --target-is-zero. This flag is only safe when the target device is guaranteed pre-zeroed (e.g. thin-provisioned block devices like LVM_THIN or ZFS_THIN). NFS files are NOT pre-zeroed, so enabling this flag would cause silent data corruption by skipping zero-filled sectors that the target still contains stale data for. The Linstor storage adaptor handles this correctly by checking LinstorUtil.resourceSupportZeroBlocks() before enabling skipZero. - noCache=true: Enable direct I/O (-t none) which bypasses the kernel page cache. This ensures writes are flushed directly to the NFS server, avoiding cache-related EINVAL errors at sector boundaries and improving reliability for large volume copies. Impact: Only affects the StorPoolCopyVolumeToSecondaryCommandWrapper code path, which is used during offline volume migration when StorPool is the source and the copy goes through secondary (NFS) storage. StorPool-to-StorPool copies use native StorPool cloning and are not affected. Files: - MOD: plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/ kvm/resource/wrapper/StorPoolCopyVolumeToSecondaryCommandWrapper.java
1 parent 27ad767 commit 9af031e

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/StorPoolCopyVolumeToSecondaryCommandWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public CopyCmdAnswer execute(final StorPoolCopyVolumeToSecondaryCommand cmd, fin
9393
PhysicalDiskFormat destFormat = newDisk.getFormat();
9494
SP_LOG("StorpoolCopyVolumeToSecondaryCommandWrapper.execute: KVMPhysicalDisk name=%s, format=%s, path=%s, destinationPath=%s " , newDisk.getName(), newDisk.getFormat(), newDisk.getPath(), destPath);
9595
QemuImgFile destFile = new QemuImgFile(destPath, destFormat);
96-
QemuImg qemu = new QemuImg(cmd.getWaitInMillSeconds());
96+
QemuImg qemu = new QemuImg(cmd.getWaitInMillSeconds(), false, true);
9797
qemu.convert(srcFile, destFile);
9898

9999
final File file = new File(destPath);

0 commit comments

Comments
 (0)