diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index 45daa06c..de1c39a5 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -5729,6 +5729,28 @@ sub vm_start_nolock { warn $@ if $@; } + # set write threshold for LVM thin provisioning disks + PVE::QemuConfig->foreach_volume( + $conf, + sub { + my ($ds, $drive) = @_; + return if PVE::QemuServer::drive_is_cdrom($drive, 1); + my $volid = $drive->{file}; + if ( $volid ne 'none') { + my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive); + my $snapshots = PVE::Storage::volume_snapshot_info($storecfg, $volid); + my $parentid = $snapshots->{'current'}->{parent}; + # for now only set write_threshold for volumes that have snapshots + # FIX: Change to only thin drives + if ($parentid) { + PVE::QemuServer::Blockdev::set_write_threshold( + $storecfg, $vmid, $drive_id, $volid + ); + } + } + }, + ); + #start nbd server for storage migration if (my $nbd = $migrate_opts->{nbd}) { diff --git a/src/PVE/QemuServer/Blockdev.pm b/src/PVE/QemuServer/Blockdev.pm index 8fa5eb51..5da1abd9 100644 --- a/src/PVE/QemuServer/Blockdev.pm +++ b/src/PVE/QemuServer/Blockdev.pm @@ -113,6 +113,21 @@ sub get_block_info { return $block_info; } +sub get_block_stats { + my ($vmid) = @_; + + my $block_stats = {}; + + my $qmp_block_stats = mon_cmd($vmid, "query-blockstats"); + for my $info ($qmp_block_stats->@*) { + my $qdev_id = $info->{qdev} or next; + my $drive_id = qdev_id_to_drive_id($qdev_id); + $block_stats->{$drive_id} = $info; + } + + return $block_stats; +} + my sub get_node_name { my ($type, $drive_id, $volid, $options) = @_; @@ -710,6 +725,24 @@ sub resize { ); } +sub underlay_resize { + my ($storecfg, $vmid, $drive_id, $volid) = @_; + + my $running = PVE::QemuServer::Helpers::vm_running_locally($vmid); + + # get backing_snap + my $snapshots = PVE::Storage::volume_snapshot_info($storecfg, $volid); + my $backing_snap = $snapshots->{current}->{parent}; + my $size = PVE::Storage::volume_underlay_resize($storecfg, $volid, $backing_snap); + + return if !$running; + my $block_info = get_block_info($vmid); + my $inserted = $block_info->{$drive_id}->{inserted} + or die "no block node inserted for drive '$drive_id'\n"; + + set_write_threshold($storecfg, $vmid, $drive_id, $volid); +} + my sub blockdev_change_medium { my ($storecfg, $vmid, $qdev_id, $drive) = @_; @@ -830,6 +863,49 @@ sub set_io_throttle { } } +sub block_set_write_threshold { + my ($vmid, $nodename, $threshold) = @_; + + print "set threshold $nodename $threshold\n"; + + PVE::QemuServer::mon_cmd( + $vmid, + "block-set-write-threshold", + 'node-name' => $nodename, + 'write-threshold' => int($threshold), + ); +} + +sub compute_write_threshold { + my ($storecfg, $scfg, $volid) = @_; + + my $lv_size = PVE::Storage::volume_underlay_size_info($storecfg, $volid, 5); + + my $write_threshold = $lv_size - $scfg->{chunksize} * $scfg->{'chunk-percentage'}; + + return $write_threshold; +} + +sub set_write_threshold { + my ($storecfg, $vmid, $drive_id, $volid, $options) = @_; + + my ($storeid) = PVE::Storage::parse_volume_id($volid); + my $scfg = PVE::Storage::storage_config($storecfg, $storeid); + my $support_qemu_snapshots = PVE::Storage::volume_qemu_snapshot_method($storecfg, $volid); + + # set write threshold is only supported for lvm storage using + # qcow2+external snapshots + return if $scfg->{type} ne 'lvm' || $support_qemu_snapshots ne 'mixed'; + # return if drive is not set as thin + # return if !$drive->{thin}; + + my $nodename = get_node_name('file', $drive_id, $volid, $options); + my $write_threshold = compute_write_threshold($storecfg, $scfg, $volid); + + print "setting threshold for $volid from $storeid\n"; + block_set_write_threshold($vmid, $nodename, $write_threshold); +} + sub blockdev_external_snapshot { my ($storecfg, $vmid, $machine_version, $deviceid, $drive, $snap, $parent_snap) = @_; @@ -878,6 +954,10 @@ sub blockdev_external_snapshot { node => $snap_fmt_blockdev->{'node-name'}, overlay => $new_fmt_blockdev->{'node-name'}, ); + + # FIX: only if thin + my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive); + set_write_threshold($storecfg, $vmid, $drive_id, $volid); } sub blockdev_delete { diff --git a/src/PVE/QemuServer/Drive.pm b/src/PVE/QemuServer/Drive.pm index 79dd22e6..44f477a9 100644 --- a/src/PVE/QemuServer/Drive.pm +++ b/src/PVE/QemuServer/Drive.pm @@ -253,6 +253,13 @@ my %drivedesc_base = ( optional => 1, default => 0, }, + thin => { + type => 'boolean', + description => + 'Controls whether a drive should be thin provisioned', + optional => 1, + default => 0, + }, ); my %iothread_fmt = (