From: Erik Fastermann <e.fastermann@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Erik Fastermann <e.fastermann@proxmox.com>
Subject: [PATCH pve-manager 3/3] fix #1989: qemu: disk: add cache size config
Date: Fri, 29 May 2026 14:58:08 +0200 [thread overview]
Message-ID: <20260529125808.204983-4-e.fastermann@proxmox.com> (raw)
In-Reply-To: <20260529125808.204983-1-e.fastermann@proxmox.com>
Add the option to control the size of the qcow2 L2/refcount cache in
the vm disk create and edit dialogs. This enables huge 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 <e.fastermann@proxmox.com>
---
www/manager6/Parser.js | 2 +-
www/manager6/qemu/HDEdit.js | 70 +++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/www/manager6/Parser.js b/www/manager6/Parser.js
index 36df8e9d..90467316 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+)$/);
if (!match) {
if (!p.match(/[=]/)) {
res.file = p;
diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js
index 1bb2bfda..401b8032 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,
+ cacheSizeBasedOnDisk: false,
},
},
@@ -54,6 +56,22 @@ Ext.define('PVE.qemu.HDInputPanel', {
vm.set('isSCSISingle', value === 'virtio-scsi-single');
},
},
+ 'field[name=diskformat]': {
+ change: function (f, value) {
+ this.getViewModel().set('isQcow2', value === 'qcow2');
+ },
+ afterrender: function (f) {
+ this.getViewModel().set('isQcow2', f.getValue() === 'qcow2');
+ },
+ },
+ 'field[name=cacheSizeBasedOnDisk]': {
+ change: function (f, value) {
+ this.getViewModel().set('cacheSizeBasedOnDisk', value);
+ },
+ afterrender: function (f) {
+ this.getViewModel().set('cacheSizeBasedOnDisk', f.getValue());
+ },
+ },
},
init: function (view) {
@@ -88,6 +106,16 @@ Ext.define('PVE.qemu.HDInputPanel', {
me.drive.format = values.diskformat;
}
+ if (me.drive?.format === 'qcow2' || me.drive?.file?.endsWith('.qcow2')) {
+ if (values.cacheSizeBasedOnDisk) {
+ me.drive.cache_size = 'based-on-disk';
+ } else if (values.cacheSize) {
+ me.drive.cache_size = values.cacheSize;
+ } else {
+ delete me.drive.cache_size;
+ }
+ }
+
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');
@@ -157,6 +185,14 @@ Ext.define('PVE.qemu.HDInputPanel', {
values.readOnly = PVE.Parser.parseBoolean(drive.ro);
values.aio = drive.aio || '__default__';
+ if (drive.cache_size === 'based-on-disk') {
+ values.cacheSizeBasedOnDisk = true;
+ values.cacheSize = undefined;
+ } else {
+ values.cacheSizeBasedOnDisk = false;
+ values.cacheSize = drive.cache_size;
+ }
+
values.mbps_rd = drive.mbps_rd;
values.mbps_wr = drive.mbps_wr;
values.iops_rd = drive.iops_rd;
@@ -167,6 +203,12 @@ 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'),
+ );
+ this.getViewModel().set('cacheSizeBasedOnDisk', values.cacheSizeBasedOnDisk);
},
setNodename: function (nodename) {
@@ -355,6 +397,34 @@ Ext.define('PVE.qemu.HDInputPanel', {
disabled: '{!isVirtIO && !isSCSI}',
},
},
+ {
+ xtype: 'numberfield',
+ name: 'cacheSize',
+ minValue: 1,
+ step: 1024 * 1024,
+ fieldLabel: gettext('Cache size'),
+ emptyText: gettext('Default cache size'),
+ bind: {
+ disabled: '{!isQcow2 || cacheSizeBasedOnDisk}',
+ },
+ listeners: {
+ disable: function (field) {
+ console.log(field);
+ field.setValue(null);
+ },
+ },
+ },
+ {
+ xtype: 'proxmoxcheckbox',
+ name: 'cacheSizeBasedOnDisk',
+ reference: 'cacheSizeBasedOnDisk',
+ defaultValue: 0,
+ fieldLabel: gettext('Cache size based on disk'),
+ clearOnDisable: true,
+ bind: {
+ disabled: '{!isQcow2}',
+ },
+ },
);
advancedColumn2.push(
--
2.47.3
next prev parent reply other threads:[~2026-05-29 12:58 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-29 12:58 [RFC common/manager/qemu-server 0/3] fix #1989: qemu: add qcow2 cache options Erik Fastermann
2026-05-29 12:58 ` [PATCH pve-common 1/3] json schema: display nested oneOf error messages Erik Fastermann
2026-05-29 15:25 ` Fiona Ebner
2026-05-29 12:58 ` [PATCH qemu-server 2/3] fix #1989: disk: add qcow2 cache options Erik Fastermann
2026-05-29 15:26 ` Fiona Ebner
2026-05-29 12:58 ` Erik Fastermann [this message]
2026-05-29 15:26 ` [RFC common/manager/qemu-server 0/3] fix #1989: qemu: " Fiona Ebner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260529125808.204983-4-e.fastermann@proxmox.com \
--to=e.fastermann@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox