From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 2C1681FF0AF for ; Thu, 10 Sep 2026 15:43:11 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id EAA5C21507; Thu, 10 Sep 2026 15:43:10 +0200 (CEST) Message-ID: Date: Thu, 10 Sep 2026 15:42:59 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Beta Subject: Re: [PATCH pve-manager v2 2/3] partially fix #1989: ui: qemu: disk: add qcow2 cache size config To: Erik Fastermann , pve-devel@lists.proxmox.com, Thomas Lamprecht References: <20260720094638.113056-1-e.fastermann@proxmox.com> <20260720094638.113056-3-e.fastermann@proxmox.com> Content-Language: en-US From: Dominik Csapak In-Reply-To: <20260720094638.113056-3-e.fastermann@proxmox.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1789047770567 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.480 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 2BSQ7YCTADOXUFJOYGMNJLUT5B3ZBDWD X-Message-ID-Hash: 2BSQ7YCTADOXUFJOYGMNJLUT5B3ZBDWD X-MailFrom: d.csapak@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: it seems this (or another version of this) patch was already applied accidentally? @Thomas? since the qemu-server changes are not in yet, should we revert this for now? comments inline On 7/20/26 11:47 AM, Erik Fastermann wrote: > Add the option to control the size of the qcow2 cache in the vm disk > create and edit dialogs. This can provide significant performance gains > in some vm configurations. > > For a detailed explanation see the QEMU docs [0]. Currently only the > cache-size is configurable in the frontend, either directly or based on > the size of the disk. > > [0] https://gitlab.com/qemu-project/qemu/-/blob/master/docs/qcow2-cache.txt > > Signed-off-by: Erik Fastermann > --- > > changes since v1: > * simplified qcow2CacheSizeBasedOnDisk usage by binding the value > (sadly the workaround for isQcow2 is still required) > * added tooltips for the qcow2 cache options > > www/manager6/Parser.js | 2 +- > www/manager6/qemu/HDEdit.js | 73 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 74 insertions(+), 1 deletion(-) > > diff --git a/www/manager6/Parser.js b/www/manager6/Parser.js > index 36df8e9d..f8d2bdad 100644 > --- a/www/manager6/Parser.js > +++ b/www/manager6/Parser.js > @@ -207,7 +207,7 @@ Ext.define('PVE.Parser', { > if (!p || p.match(/^\s*$/)) { > return undefined; // continue > } > - let match = p.match(/^([a-z_]+)=(\S+)$/); > + let match = p.match(/^([0-9a-z-]+)=(\S+)$/); this drops the underscore from the regex > if (!match) { > if (!p.match(/[=]/)) { > res.file = p; > diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js > index 1bb2bfda..fafa0f55 100644 > --- a/www/manager6/qemu/HDEdit.js > +++ b/www/manager6/qemu/HDEdit.js > @@ -18,6 +18,8 @@ Ext.define('PVE.qemu.HDInputPanel', { > isSCSI: false, > isVirtIO: false, > isSCSISingle: false, > + isQcow2: false, > + qcow2CacheSizeBasedOnDisk: false, > }, > }, > > @@ -54,6 +56,15 @@ Ext.define('PVE.qemu.HDInputPanel', { > vm.set('isSCSISingle', value === 'virtio-scsi-single'); > }, > }, > + 'field[name=diskformat]': { > + change: 'onDiskFormatChange', > + // afterrender is needed for setting the initial value > + afterrender: 'onDiskFormatChange', > + }, > + }, > + > + onDiskFormatChange: function (field) { > + this.getViewModel().set('isQcow2', field.getValue() === 'qcow2'); > }, > > init: function (view) { > @@ -88,6 +99,20 @@ Ext.define('PVE.qemu.HDInputPanel', { > me.drive.format = values.diskformat; > } > > + if (me.drive?.format === 'qcow2' || me.drive?.file?.endsWith('.qcow2')) { > + if (values.qcow2CacheSize) { > + me.drive['qcow2-cache-size'] = values.qcow2CacheSize; > + } else { > + delete me.drive['qcow2-cache-size']; > + } > + } > + > + PVE.Utils.propertyStringSet( > + me.drive, > + values.qcow2CacheSizeBasedOnDisk, > + 'qcow2-cache-size-based-on-disk', > + ); > + > PVE.Utils.propertyStringSet(me.drive, !values.backup, 'backup', '0'); > PVE.Utils.propertyStringSet(me.drive, values.noreplicate, 'replicate', 'no'); > PVE.Utils.propertyStringSet(me.drive, values.discard, 'discard', 'on'); > @@ -156,6 +181,8 @@ Ext.define('PVE.qemu.HDInputPanel', { > values.iothread = PVE.Parser.parseBoolean(drive.iothread); > values.readOnly = PVE.Parser.parseBoolean(drive.ro); > values.aio = drive.aio || '__default__'; > + values.qcow2CacheSizeBasedOnDisk = drive['qcow2-cache-size-based-on-disk']; > + values.qcow2CacheSize = drive['qcow2-cache-size']; > > values.mbps_rd = drive.mbps_rd; > values.mbps_wr = drive.mbps_wr; > @@ -167,6 +194,11 @@ Ext.define('PVE.qemu.HDInputPanel', { > values.iops_wr_max = drive.iops_wr_max; > > me.setValues(values); > + > + me.getViewModel().set( > + 'isQcow2', > + values.diskformat === 'qcow2' || values.hdimage?.endsWith('.qcow2'), > + ); > }, > > setNodename: function (nodename) { > @@ -355,6 +387,47 @@ Ext.define('PVE.qemu.HDInputPanel', { > disabled: '{!isVirtIO && !isSCSI}', > }, > }, > + { > + xtype: 'numberfield', > + name: 'qcow2CacheSize', > + minValue: 1, > + fieldLabel: gettext('qcow2 cache') + ' (MiB)', > + emptyText: gettext('Default cache size'), > + autoEl: { > + tag: 'div', > + 'data-qtip': gettext( > + 'Total size of the qcow2 cache in MiB. A larger cache can' + > + ' improve I/O performance on large images. Leave empty to' + > + ' use the QEMU default (32 MiB L2 cache and 256 KiB' + > + ' refcount cache with the default disk settings).', > + ), > + }, > + bind: { > + disabled: '{!isQcow2 || qcow2CacheSizeBasedOnDisk}', > + }, > + listeners: { > + disable: (field) => field.setValue(null), > + }, > + }, > + { > + xtype: 'proxmoxcheckbox', > + name: 'qcow2CacheSizeBasedOnDisk', > + defaultValue: 0, > + fieldLabel: gettext('qcow2 cache based on disk'), > + clearOnDisable: true, > + autoEl: { > + tag: 'div', > + 'data-qtip': gettext( > + 'Automatically size the qcow2 cache to cover the whole disk.' + > + ' Uses roughly 160 KiB of memory per GiB of disk with' + > + ' the default disk settings.', > + ), > + }, > + bind: { > + value: '{qcow2CacheSizeBasedOnDisk}', > + disabled: '{!isQcow2}', > + }, > + }, > ); > > advancedColumn2.push(