From 24fe1bf621944fd78abd183da4bfd4974c0b1d7d Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Wed, 9 Jul 2025 18:21:49 +0200 Subject: [PATCH] plugin: add qemu_img_create_qcow2_backed and use it for plugin linked clone This also enable extended_l2=on, as it's mandatory for backing file preallocation. Preallocation was missing previously, so it should increase performance for linked clone now (around x5 in randwrite 4k) cluster_size is set to 128k, as it reduce qcow2 overhead (reduce disk, but also memory needed to cache metadatas) l2_extended is not enabled yet on base image, but it could help too to reduce overhead without impacting performance bench on 100G qcow2 file: fio --filename=/dev/sdb --direct=1 --rw=randwrite --bs=4k --iodepth=32 --ioengine=libaio --name=test fio --filename=/dev/sdb --direct=1 --rw=randread --bs=4k --iodepth=32 --ioengine=libaio --name=test base image: randwrite 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 20215 randread 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 22219 randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 20217 randread 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 21742 randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 21599 randread 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 22037 clone image with backing file: randwrite 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 3912 randread 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 21476 randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 20563 randread 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 22265 randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 18016 randread 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 21611 Signed-off-by: Alexandre Derumier --- src/PVE/Storage/Plugin.pm | 52 ++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm index 65a34b1..c4b4cd3 100644 --- a/src/PVE/Storage/Plugin.pm +++ b/src/PVE/Storage/Plugin.pm @@ -51,6 +51,10 @@ our $RAW_PREALLOCATION = { full => 1, }; +my $QCOW2_CLUSTERS = { + backed => ['extended_l2=on', 'cluster_size=128k'], +}; + our $MAX_VOLUMES_PER_GUEST = 1024; cfs_register_file( @@ -654,6 +658,39 @@ sub qemu_img_create { run_command($cmd, errmsg => "unable to create image"); } +=pod + +=head3 qemu_img_create_qcow2_backed + + qemu_img_create_qcow2_backed($scfg, $path, $backing_path, $backing_format) + +Create a new qemu qcow2 image C<$path> using an existing backing image C<$backing_path> with backing_format C<$backing_format>. + +=cut + +sub qemu_img_create_qcow2_backed { + my ($scfg, $path, $backing_path, $backing_format) = @_; + + my $cmd = [ + '/usr/bin/qemu-img', + 'create', + '-F', + $backing_format, + '-b', + $backing_path, + '-f', + 'qcow2', + $path, + ]; + + my $options = $QCOW2_CLUSTERS->{backed}; + + push @$options, preallocation_cmd_option($scfg, 'qcow2'); + push @$cmd, '-o', join(',', @$options) if @$options > 0; + + run_command($cmd, errmsg => "unable to create image"); +} + # Storage implementation # called during addition of storage (before the new storage config got written) @@ -941,20 +978,7 @@ sub clone_image { # Note: we use relative paths, so we need to call chdir before qemu-img eval { local $CWD = $imagedir; - - my $cmd = [ - '/usr/bin/qemu-img', - 'create', - '-b', - "../$basevmid/$basename", - '-F', - $format, - '-f', - 'qcow2', - $path, - ]; - - run_command($cmd); + qemu_img_create_qcow2_backed($scfg, $path, "../$basevmid/$basename", $format); }; my $err = $@;