Add support for a duration/length for the bps/iops and friends.
Modify the API in order to add the "blkdeviotune." specific definitions
for the iotune throttling duration/length options
total_bytes_sec_max_length
write_bytes_sec_max_length
read_bytes_sec_max_length
total_iops_sec_max_length
write_iops_sec_max_length
read_iops_sec_max_length
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
include/libvirt/libvirt-domain.h | 54 ++++++++++++++++++++
src/conf/domain_conf.h | 6 +++
src/qemu/qemu_driver.c | 106 ++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_monitor.c | 7 ++-
src/qemu/qemu_monitor.h | 3 +-
src/qemu/qemu_monitor_json.c | 25 ++++++++-
src/qemu/qemu_monitor_json.h | 3 +-
tests/qemumonitorjsontest.c | 17 ++++++-
8 files changed, 211 insertions(+), 10 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 5744e25..beeedc6 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3845,6 +3845,60 @@ typedef void
(*virConnectDomainEventJobCompletedCallback)(virConnectPtr conn,
# define VIR_DOMAIN_TUNABLE_BLKDEV_SIZE_IOPS_SEC "blkdeviotune.size_iops_sec"
/**
+ * VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH:
+ *
+ * Macro represents the length in seconds allowed for a burst period
+ * for the blkdeviotune.total_bytes_sec_max,
+ * as VIR_TYPED_PARAM_ULLONG.
+ */
+# define VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH
"blkdeviotune.total_bytes_sec_max_length"
+
+/**
+ * VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH:
+ *
+ * Macro represents the length in seconds allowed for a burst period
+ * for the blkdeviotune.read_bytes_sec_max
+ * as VIR_TYPED_PARAM_ULLONG.
+ */
+# define VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH
"blkdeviotune.read_bytes_sec_max_length"
+
+/**
+ * VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH:
+ *
+ * Macro represents the length in seconds allowed for a burst period
+ * for the blkdeviotune.write_bytes_sec_max
+ * as VIR_TYPED_PARAM_ULLONG.
+ */
+# define VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH
"blkdeviotune.write_bytes_sec_max_length"
+
+/**
+ * VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH:
+ *
+ * Macro represents the length in seconds allowed for a burst period
+ * for the blkdeviotune.total_iops_sec_max
+ * as VIR_TYPED_PARAM_ULLONG.
+ */
+# define VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH
"blkdeviotune.total_iops_sec_max_length"
+
+/**
+ * VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH:
+ *
+ * Macro represents the length in seconds allowed for a burst period
+ * for the blkdeviotune.read_iops_sec_max
+ * as VIR_TYPED_PARAM_ULLONG.
+ */
+# define VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH
"blkdeviotune.read_iops_sec_max_length"
+
+/**
+ * VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH:
+ *
+ * Macro represents the length in seconds allowed for a burst period
+ * for the blkdeviotune.write_iops_sec_max
+ * as VIR_TYPED_PARAM_ULLONG.
+ */
+# define VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH
"blkdeviotune.write_iops_sec_max_length"
+
+/**
* virConnectDomainEventTunableCallback:
* @conn: connection object
* @dom: domain on which the event occurred
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ce90c27..2869951 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -548,6 +548,12 @@ struct _virDomainBlockIoTuneInfo {
unsigned long long read_iops_sec_max;
unsigned long long write_iops_sec_max;
unsigned long long size_iops_sec;
+ unsigned long long total_bytes_sec_max_length;
+ unsigned long long read_bytes_sec_max_length;
+ unsigned long long write_bytes_sec_max_length;
+ unsigned long long total_iops_sec_max_length;
+ unsigned long long read_iops_sec_max_length;
+ unsigned long long write_iops_sec_max_length;
};
typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ee16cb5..3b04754 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -113,7 +113,8 @@ VIR_LOG_INIT("qemu.qemu_driver");
#define QEMU_NB_MEM_PARAM 3
#define QEMU_NB_BLOCK_IO_TUNE_PARAM 6
-#define QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX 13
+#define QEMU_NB_BLOCK_IO_TUNE_PARAM_LENGTH 12
+#define QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX 19
#define QEMU_NB_NUMA_PARAM 2
@@ -17262,7 +17263,10 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
bool set_bytes_max = false;
bool set_iops_max = false;
bool set_size_iops = false;
+ bool set_bytes_max_length = false;
+ bool set_iops_max_length = false;
bool supportMaxOptions = true;
+ bool supportMaxLengthOptions = true;
virQEMUDriverConfigPtr cfg = NULL;
virObjectEventPtr event = NULL;
virTypedParameterPtr eventParams = NULL;
@@ -17298,6 +17302,18 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
+ VIR_TYPED_PARAM_ULLONG,
NULL) < 0)
return -1;
@@ -17449,6 +17465,60 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
VIR_DOMAIN_TUNABLE_BLKDEV_SIZE_IOPS_SEC,
param->value.ul) < 0)
goto endjob;
+ } else if (STREQ(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH)) {
+ info.total_bytes_sec_max_length = param->value.ul;
+ set_bytes_max_length = true;
+ if (virTypedParamsAddULLong(&eventParams, &eventNparams,
+ &eventMaxparams,
+
VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH,
+ param->value.ul) < 0)
+ goto endjob;
+ } else if (STREQ(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH)) {
+ info.read_bytes_sec_max_length = param->value.ul;
+ set_bytes_max_length = true;
+ if (virTypedParamsAddULLong(&eventParams, &eventNparams,
+ &eventMaxparams,
+
VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH,
+ param->value.ul) < 0)
+ goto endjob;
+ } else if (STREQ(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH)) {
+ info.write_bytes_sec_max_length = param->value.ul;
+ set_bytes_max_length = true;
+ if (virTypedParamsAddULLong(&eventParams, &eventNparams,
+ &eventMaxparams,
+
VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH,
+ param->value.ul) < 0)
+ goto endjob;
+ } else if (STREQ(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH)) {
+ info.total_iops_sec_max_length = param->value.ul;
+ set_iops_max_length = true;
+ if (virTypedParamsAddULLong(&eventParams, &eventNparams,
+ &eventMaxparams,
+
VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH,
+ param->value.ul) < 0)
+ goto endjob;
+ } else if (STREQ(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH)) {
+ info.read_iops_sec_max_length = param->value.ul;
+ set_iops_max_length = true;
+ if (virTypedParamsAddULLong(&eventParams, &eventNparams,
+ &eventMaxparams,
+
VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH,
+ param->value.ul) < 0)
+ goto endjob;
+ } else if (STREQ(param->field,
+ VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH)) {
+ info.write_iops_sec_max_length = param->value.ul;
+ set_iops_max_length = true;
+ if (virTypedParamsAddULLong(&eventParams, &eventNparams,
+ &eventMaxparams,
+
VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH,
+ param->value.ul) < 0)
+ goto endjob;
}
}
@@ -17496,6 +17566,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
if (def) {
supportMaxOptions = virQEMUCapsGet(priv->qemuCaps,
QEMU_CAPS_DRIVE_IOTUNE_MAX);
+ supportMaxLengthOptions =
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH);
+
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("block I/O throttling not supported with this "
@@ -17511,6 +17584,14 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
goto endjob;
}
+ if (!supportMaxLengthOptions &&
+ (set_iops_max_length || set_bytes_max_length)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("a block I/O throttling length parameter is not "
+ "supported with this QEMU binary"));
+ goto endjob;
+ }
+
if (!(disk = qemuDomainDiskByName(def, path)))
goto endjob;
@@ -17543,6 +17624,16 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
}
if (!set_size_iops)
info.size_iops_sec = oldinfo->size_iops_sec;
+ if (!set_bytes_max_length) {
+ info.total_bytes_sec_max_length = oldinfo->total_bytes_sec_max_length;
+ info.read_bytes_sec_max_length = oldinfo->read_bytes_sec_max_length;
+ info.write_bytes_sec_max_length = oldinfo->write_bytes_sec_max_length;
+ }
+ if (!set_iops_max_length) {
+ info.total_iops_sec_max_length = oldinfo->total_iops_sec_max_length;
+ info.read_iops_sec_max_length = oldinfo->read_iops_sec_max_length;
+ info.write_iops_sec_max_length = oldinfo->write_iops_sec_max_length;
+ }
#define CHECK_MAX(val) \
do { \
@@ -17566,7 +17657,8 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorSetBlockIoThrottle(priv->mon, device,
- &info, supportMaxOptions);
+ &info, supportMaxOptions,
+ supportMaxLengthOptions);
if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1;
if (ret < 0)
@@ -17667,6 +17759,9 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX))
maxparams = QEMU_NB_BLOCK_IO_TUNE_PARAM;
+
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH))
+ maxparams = QEMU_NB_BLOCK_IO_TUNE_PARAM_LENGTH;
}
if (*nparams == 0) {
@@ -17730,6 +17825,13 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
BLOCK_IOTUNE_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
+ BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_length);
+ BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_length);
+ BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_length);
+
+ BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_length);
+ BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_length);
+ BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_length);
#undef BLOCK_IOTUNE_ASSIGN
ret = 0;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 8083a36..f800efd 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3423,14 +3423,17 @@ int
qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
- bool supportMaxOptions)
+ bool supportMaxOptions,
+ bool supportMaxLengthOptions)
{
VIR_DEBUG("device=%p, info=%p", device, info);
QEMU_CHECK_MONITOR(mon);
if (mon->json)
- return qemuMonitorJSONSetBlockIoThrottle(mon, device, info, supportMaxOptions);
+ return qemuMonitorJSONSetBlockIoThrottle(mon, device, info,
+ supportMaxOptions,
+ supportMaxLengthOptions);
else
return qemuMonitorTextSetBlockIoThrottle(mon, device, info);
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 7d78e5b..700dff9 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -873,7 +873,8 @@ int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
- bool supportMaxOptions);
+ bool supportMaxOptions,
+ bool supportMaxLengthOptions);
int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 43a3fa7..6b26cf9 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4559,6 +4559,12 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
GET_THROTTLE_STATS_OPTIONAL("iops_rd_max", read_iops_sec_max);
GET_THROTTLE_STATS_OPTIONAL("iops_wr_max", write_iops_sec_max);
GET_THROTTLE_STATS_OPTIONAL("iops_size", size_iops_sec);
+ GET_THROTTLE_STATS_OPTIONAL("bps_max_length",
total_bytes_sec_max_length);
+ GET_THROTTLE_STATS_OPTIONAL("bps_rd_max_length",
read_bytes_sec_max_length);
+ GET_THROTTLE_STATS_OPTIONAL("bps_wr_max_length",
write_bytes_sec_max_length);
+ GET_THROTTLE_STATS_OPTIONAL("iops_max_length",
total_iops_sec_max_length);
+ GET_THROTTLE_STATS_OPTIONAL("iops_rd_max_length",
read_iops_sec_max_length);
+ GET_THROTTLE_STATS_OPTIONAL("iops_wr_max_length",
write_iops_sec_max_length);
break;
}
@@ -4580,7 +4586,8 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
- bool supportMaxOptions)
+ bool supportMaxOptions,
+ bool supportMaxLengthOptions)
{
int ret = -1;
virJSONValuePtr cmd = NULL;
@@ -4589,7 +4596,8 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
/* The qemu capability check has already been made in
* qemuDomainSetBlockIoTune. NB, once a NULL is found in
* the sequence, qemuMonitorJSONMakeCommand will stop. So
- * let's make use of that when !supportMaxOptions */
+ * let's make use of that when !supportMaxOptions and
+ * similarly when !supportMaxLengthOptions */
cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle",
"s:device", device,
"U:bps", info->total_bytes_sec,
@@ -4606,6 +4614,19 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
"U:iops_rd_max",
info->read_iops_sec_max,
"U:iops_wr_max",
info->write_iops_sec_max,
"U:iops_size", info->size_iops_sec,
+ !supportMaxLengthOptions ? NULL :
+ "U:bps_max_length",
+ info->total_bytes_sec_max_length,
+ "U:bps_rd_max_length",
+ info->read_bytes_sec_max_length,
+ "U:bps_wr_max_length",
+ info->write_bytes_sec_max_length,
+ "U:iops_max_length",
+ info->total_iops_sec_max_length,
+ "U:iops_rd_max_length",
+ info->read_iops_sec_max_length,
+ "U:iops_wr_max_length",
+ info->write_iops_sec_max_length,
NULL);
if (!cmd)
return -1;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 6a5eb3b..77b2e02 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -327,7 +327,8 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
- bool supportMaxOptions);
+ bool supportMaxOptions,
+ bool supportMaxLengthOptions);
int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index cbc39c6..d4f6250 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -67,6 +67,12 @@ const char *queryBlockReply =
" \"iops_rd_max\": 11,"
" \"iops_wr_max\": 12,"
" \"iops_size\": 13,"
+" \"bps_max_length\": 14,"
+" \"bps_rd_max_length\": 15,"
+" \"bps_wr_max_length\": 16,"
+" \"iops_max_length\": 17,"
+" \"iops_rd_max_length\": 18,"
+" \"iops_wr_max_length\": 19,"
" \"file\":
\"/home/zippy/work/tmp/gentoo.qcow2\","
" \"encryption_key_missing\": false"
" },"
@@ -1885,7 +1891,7 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void
*data)
if (!test)
return -1;
- expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13};
+ expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19};
if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0 ||
qemuMonitorTestAddItemParams(test, "block_set_io_throttle",
@@ -1897,6 +1903,12 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void
*data)
"bps_wr_max", "9",
"iops_max", "10",
"iops_rd_max", "11",
"iops_wr_max", "12",
"iops_size", "13",
+ "bps_max_length", "14",
+ "bps_rd_max_length", "15",
+ "bps_wr_max_length", "16",
+ "iops_max_length", "17",
+ "iops_rd_max_length", "18",
+ "iops_wr_max_length", "19",
NULL, NULL) < 0)
goto cleanup;
@@ -1911,7 +1923,8 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void
*data)
}
if (qemuMonitorJSONSetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
- "drive-virtio-disk1", &info,
true) < 0)
+ "drive-virtio-disk1", &info,
true,
+ true) < 0)
goto cleanup;
ret = 0;
--
2.7.4