The patch add support L2 table cache for qcow2 disk.
L2 table cache can improve IO read and write performance for qcow2 img.
Example: random 4K read requests on a fully populated 100GB image (SSD backend and vm
with directsync cacha mode),
IOPS increased by 7 times.
---
src/conf/domain_conf.c | 25 +++++++++++++++++++++++++
src/conf/domain_conf.h | 4 ++++
src/qemu/qemu_command.c | 7 +++++++
src/qemu/qemu_domain.c | 4 ++++
4 files changed, 40 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b8b5345..cb9fb05 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9502,6 +9502,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
char *vendor = NULL;
char *product = NULL;
char *domain_name = NULL;
+ char *disk_l2_cache_size = NULL;
+ char *disk_cache_clean_interval = NULL;
if (!(def = virDomainDiskDefNew(xmlopt)))
return NULL;
@@ -9701,6 +9703,27 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
}
} else if (virXMLNodeNameEqual(cur, "boot")) {
/* boot is parsed as part of virDomainDeviceInfoParseXML */
+ } else if (virXMLNodeNameEqual(cur, "diskCache")) {
+ disk_l2_cache_size =
+ virXMLPropString(cur, "disk_l2_cache_size");
+ if (disk_l2_cache_size &&
+ virStrToLong_ui(disk_l2_cache_size, NULL, 0,
+ &def->disk_cache.disk_l2_cache_size) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid disk L2 cache size '%s'"),
+ disk_l2_cache_size);
+ goto error;
+ }
+ disk_cache_clean_interval =
+ virXMLPropString(cur, "disk_cache_clean_interval");
+ if (disk_cache_clean_interval &&
+ virStrToLong_ui(disk_cache_clean_interval, NULL, 0,
+ &def->disk_cache.disk_cache_clean_interval) <
0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid disk cache clean interval
'%s'"),
+ disk_cache_clean_interval);
+ goto error;
+ }
}
}
@@ -9903,6 +9926,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(vendor);
VIR_FREE(product);
VIR_FREE(domain_name);
+ VIR_FREE(disk_l2_cache_size);
+ VIR_FREE(disk_cache_clean_interval);
ctxt->node = save_ctxt;
return def;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 71437dc..6396475 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -647,6 +647,10 @@ struct _virDomainDiskDef {
unsigned int physical_block_size;
} blockio;
+ struct {
+ unsigned int disk_l2_cache_size;
+ unsigned int disk_cache_clean_interval;
+ } disk_cache;
virDomainBlockIoTuneInfo blkdeviotune;
char *driverName;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4fc3176..4bc9412 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1637,6 +1637,13 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
if (qemuBuildDriveSourceStr(disk, qemuCaps, &opt) < 0)
goto error;
+
+ if (disk->disk_cache.disk_l2_cache_size > 0)
+ virBufferAsprintf(&opt, "l2-cache-size=%u,",
+ disk->disk_cache.disk_l2_cache_size);
+ if (disk->disk_cache.disk_cache_clean_interval > 0)
+ virBufferAsprintf(&opt, "cache-clean-interval=%u,",
+ disk->disk_cache.disk_cache_clean_interval);
if (qemuDiskBusNeedsDeviceArg(disk->bus)) {
char *drivealias = qemuAliasDiskDriveFromDisk(disk);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index fee4481..4896bf7 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8627,6 +8627,10 @@ qemuDomainDiskChangeSupported(virDomainDiskDefPtr disk,
CHECK_EQ(ioeventfd, "ioeventfd", true);
CHECK_EQ(event_idx, "event_idx", true);
CHECK_EQ(copy_on_read, "copy_on_read", true);
+ CHECK_EQ(disk_cache.disk_l2_cache_size,
+ "diskCache disk_l2_cache_size", true);
+ CHECK_EQ(disk_cache.disk_cache_clean_interval,
+ "diskCache disk_cache_clean_interval", true);
/* "snapshot" is a libvirt internal field and thus can be changed */
/* startupPolicy is allowed to be updated. Therefore not checked here. */
CHECK_EQ(transient, "transient", true);
--
1.8.3.1