[libvirt] [PATCH v3 0/7] qemu: Introduce support for new the block_set_io_throttle parameters add in the version 1.7 of qemu.

This series of patches add support for bps_max, bps_rd_max, bps_wr_max, bps_max, bps_rd_max, bps_wr_max, and iops_size in the functions qemuDomainSetBlockIoTune and qemuDomainGetBlockIoTune. The last patch add support for these parameters to the virsh blkdeviotune command. v2: spellfix v3: Merge patch 1/9,2/9,5/9 together. Change the capability detection.(patch 2/7 and 3/7). Try to make the usage of QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX more explicit(patch 3/7). Matthias Gatto (7): qemu: Add defines for the news throttle options and modify the structure _virDomainBlockIoTuneInfo. qemu: Add the capability to detect if the qemu binary have the capability to use bps_max and friends qemu: Add bps_max and friends qemu driver qemu: Add bps_max and friends QMP suport qemu: Add bps_max and friends "text" support qemu: add bps_max and friends to qemu command generation virsh: Add bps_max and friends to virsh include/libvirt/libvirt.h.in | 54 +++++++++++++++ src/conf/domain_conf.c | 89 +++++++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 +++++++++++++ src/qemu/qemu_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 6 +- src/qemu/qemu_monitor_json.c | 70 +++++++++++++++---- src/qemu/qemu_monitor_json.h | 6 +- src/qemu/qemu_monitor_text.c | 89 +++++++++++++++++++++--- src/qemu/qemu_monitor_text.h | 6 +- tests/qemumonitorjsontest.c | 6 +- tools/virsh-domain.c | 119 +++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++- 16 files changed, 643 insertions(+), 50 deletions(-) -- 1.8.3.1

Add defines for the news options total_bytes_sec_max, write_bytes_sec_max, read_bytes_sec_max total_iops_sec_max, write_iops_sec_max, read_iops_sec_max, size_iops_sec. Modify the structure _virDomainBlockIoTuneInfo to support these options. Change the initialization of the variable expectedInfo in qemumonitorjsontest.c to avoid compiling problem. Allow libvirt to save the configuration. Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- include/libvirt/libvirt.h.in | 54 +++++++++++++++++++++++++++ src/conf/domain_conf.c | 89 +++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 7 ++++ tests/qemumonitorjsontest.c | 2 +- 4 files changed, 150 insertions(+), 2 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index ad6785f..4094103 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2668,6 +2668,60 @@ int virDomainBlockCommit(virDomainPtr dom, const char *disk, const char *base, */ #define VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC "write_iops_sec" +/** + * VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX: + * + * Macro for the BlockIoTune tunable weight: it represents the maximum total + * bytes per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX "total_bytes_sec_max" + +/** + * VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX: + * + * Macro for the BlockIoTune tunable weight: it represents the maximum read + * bytes per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX "read_bytes_sec_max" + +/** + * VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX: + * + * Macro for the BlockIoTune tunable weight: it represents the maximum write + * bytes per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX "write_bytes_sec_max" + +/** + * VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX: + * + * Macro for the BlockIoTune tunable weight: it represents the maximum + * I/O operations per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX "total_iops_sec_max" + +/** + * VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX: + * + * Macro for the BlockIoTune tunable weight: it represents the maximum read + * I/O operations per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX "read_iops_sec_max" + +/** + * VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX: + * Macro for the BlockIoTune tunable weight: it represents the maximum write + * I/O operations per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX "write_iops_sec_max" + +/** + * VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC: + * Macro for the BlockIoTune tunable weight: it represents the size + * I/O operations per second permitted through a block device, as a ullong. + */ +#define VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC "size_iops_sec" + int virDomainSetBlockIoTune(virDomainPtr dom, const char *disk, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c7016f3..57b9e7f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5680,6 +5680,49 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, def->blkdeviotune.write_iops_sec = 0; } + if (virXPathULongLong("string(./iotune/total_bytes_sec_max)", + ctxt, + &def->blkdeviotune.total_bytes_sec_max) < 0) { + def->blkdeviotune.total_bytes_sec_max = 0; + } + + if (virXPathULongLong("string(./iotune/read_bytes_sec_max)", + ctxt, + &def->blkdeviotune.read_bytes_sec_max) < 0) { + def->blkdeviotune.read_bytes_sec_max = 0; + } + + if (virXPathULongLong("string(./iotune/write_bytes_sec_max)", + ctxt, + &def->blkdeviotune.write_bytes_sec_max) < 0) { + def->blkdeviotune.write_bytes_sec_max = 0; + } + + if (virXPathULongLong("string(./iotune/total_iops_sec_max)", + ctxt, + &def->blkdeviotune.total_iops_sec_max) < 0) { + def->blkdeviotune.total_iops_sec_max = 0; + } + + if (virXPathULongLong("string(./iotune/read_iops_sec_max)", + ctxt, + &def->blkdeviotune.read_iops_sec_max) < 0) { + def->blkdeviotune.read_iops_sec_max = 0; + } + + if (virXPathULongLong("string(./iotune/write_iops_sec_max)", + ctxt, + &def->blkdeviotune.write_iops_sec_max) < 0) { + def->blkdeviotune.write_iops_sec_max = 0; + } + + if (virXPathULongLong("string(./iotune/size_iops_sec)", + ctxt, + &def->blkdeviotune.size_iops_sec) < 0) { + def->blkdeviotune.size_iops_sec = 0; + } + + if ((def->blkdeviotune.total_bytes_sec && def->blkdeviotune.read_bytes_sec) || (def->blkdeviotune.total_bytes_sec && @@ -15578,7 +15621,14 @@ virDomainDiskDefFormat(virBufferPtr buf, def->blkdeviotune.write_bytes_sec || def->blkdeviotune.total_iops_sec || def->blkdeviotune.read_iops_sec || - def->blkdeviotune.write_iops_sec) { + def->blkdeviotune.write_iops_sec || + def->blkdeviotune.total_bytes_sec_max || + def->blkdeviotune.read_bytes_sec_max || + def->blkdeviotune.write_bytes_sec_max || + def->blkdeviotune.total_iops_sec_max || + def->blkdeviotune.read_iops_sec_max || + def->blkdeviotune.write_iops_sec_max || + def->blkdeviotune.size_iops_sec) { virBufferAddLit(buf, "<iotune>\n"); virBufferAdjustIndent(buf, 2); if (def->blkdeviotune.total_bytes_sec) { @@ -15611,6 +15661,43 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "<write_iops_sec>%llu</write_iops_sec>\n", def->blkdeviotune.write_iops_sec); } + + if (def->blkdeviotune.total_bytes_sec_max) { + virBufferAsprintf(buf, "<total_bytes_sec_max>%llu</total_bytes_sec_max>\n", + def->blkdeviotune.total_bytes_sec_max); + } + + if (def->blkdeviotune.read_bytes_sec_max) { + virBufferAsprintf(buf, "<read_bytes_sec_max>%llu</read_bytes_sec_max>\n", + def->blkdeviotune.read_bytes_sec_max); + + } + + if (def->blkdeviotune.write_bytes_sec_max) { + virBufferAsprintf(buf, "<write_bytes_sec_max>%llu</write_bytes_sec_max>\n", + def->blkdeviotune.write_bytes_sec_max); + } + + if (def->blkdeviotune.total_iops_sec_max) { + virBufferAsprintf(buf, "<total_iops_sec_max>%llu</total_iops_sec_max>\n", + def->blkdeviotune.total_iops_sec_max); + } + + if (def->blkdeviotune.read_iops_sec_max) { + virBufferAsprintf(buf, "<read_iops_sec_max>%llu</read_iops_sec_max>\n", + def->blkdeviotune.read_iops_sec_max); + } + + if (def->blkdeviotune.write_iops_sec_max) { + virBufferAsprintf(buf, "<write_iops_sec_max>%llu</write_iops_sec_max>\n", + def->blkdeviotune.write_iops_sec_max); + } + + if (def->blkdeviotune.size_iops_sec) { + virBufferAsprintf(buf, "<size_iops_sec>%llu</size_iops_sec>\n", + def->blkdeviotune.size_iops_sec); + } + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</iotune>\n"); } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ff7d640..4978679 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -606,6 +606,13 @@ struct _virDomainBlockIoTuneInfo { unsigned long long total_iops_sec; unsigned long long read_iops_sec; unsigned long long write_iops_sec; + unsigned long long total_bytes_sec_max; + unsigned long long read_bytes_sec_max; + unsigned long long write_bytes_sec_max; + unsigned long long total_iops_sec_max; + unsigned long long read_iops_sec_max; + unsigned long long write_iops_sec_max; + unsigned long long size_iops_sec; }; typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr; diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index baee80a..319f999 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1835,7 +1835,7 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data) if (!test) return -1; - expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6}; + expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0 || qemuMonitorTestAddItemParams(test, "block_set_io_throttle", -- 1.8.3.1

Add a value in the enum virQEMUCapsFlags for the qemu capability. Set it with virQEMUCapsSet if the binary suport bps_max and they friends. Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 360cc67..17a168d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -265,6 +265,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "numa", "memory-backend-file", "usb-audio", + "drive-iotune-max", ); @@ -1063,6 +1064,8 @@ virQEMUCapsComputeCmdFlags(const char *help, virQEMUCapsSet(qemuCaps, QEMU_CAPS_DRIVE_COPY_ON_READ); if (strstr(help, "bps=")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DRIVE_IOTUNE); + if (strstr(help, "bps_max=")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX); } if ((p = strstr(help, "-vga")) && !strstr(help, "-std-vga")) { const char *nl = strstr(p, "\n"); @@ -2432,6 +2435,7 @@ static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { { "spice", "disable-agent-file-xfer", QEMU_CAPS_SPICE_FILE_XFER_DISABLE }, { "msg", "timestamp", QEMU_CAPS_MSG_TIMESTAMP }, { "numa", NULL, QEMU_CAPS_NUMA }, + { "drive", "throttling.bps-total-max", QEMU_CAPS_DRIVE_IOTUNE_MAX}, }; static int diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 2911759..394a836 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -213,6 +213,7 @@ typedef enum { QEMU_CAPS_NUMA = 171, /* newer -numa handling with disjoint cpu ranges */ QEMU_CAPS_OBJECT_MEMORY_FILE = 172, /* -object memory-backend-file */ QEMU_CAPS_OBJECT_USB_AUDIO = 173, /* usb-audio device support */ + QEMU_CAPS_DRIVE_IOTUNE_MAX = 174, /* -drive bps_max= and friends */ QEMU_CAPS_LAST, /* this must always be the last item */ } virQEMUCapsFlags; -- 1.8.3.1

Add support for bps_max and friends in the driver part. In the part checking if a qemu is running, check if the running binary support bps_max, if not print an error message, if yes add it to "info" variable Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- src/qemu/qemu_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 6 +- src/qemu/qemu_monitor_json.c | 13 ++-- src/qemu/qemu_monitor_json.h | 6 +- src/qemu/qemu_monitor_text.c | 15 ++-- src/qemu/qemu_monitor_text.h | 6 +- tests/qemumonitorjsontest.c | 4 +- 8 files changed, 195 insertions(+), 31 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2c3f179..cc4fc69 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -104,6 +104,7 @@ 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_NUMA_PARAM 2 @@ -15818,6 +15819,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, int idx = -1; bool set_bytes = false; bool set_iops = false; + bool set_bytes_max = false; + bool set_iops_max = false; + bool set_size_iops = false; virQEMUDriverConfigPtr cfg = NULL; virCapsPtr caps = NULL; @@ -15836,6 +15840,20 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, VIR_TYPED_PARAM_ULLONG, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC, VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC, + VIR_TYPED_PARAM_ULLONG, NULL) < 0) return -1; @@ -15902,6 +15920,34 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) { info.write_iops_sec = param->value.ul; set_iops = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX)) { + info.total_bytes_sec_max = param->value.ul; + set_bytes_max = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX)) { + info.read_bytes_sec_max = param->value.ul; + set_bytes_max = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX)) { + info.write_bytes_sec_max = param->value.ul; + set_bytes_max = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX)) { + info.total_iops_sec_max = param->value.ul; + set_iops_max = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX)) { + info.read_iops_sec_max = param->value.ul; + set_iops_max = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX)) { + info.write_iops_sec_max = param->value.ul; + set_iops_max = true; + } else if (STREQ(param->field, + VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC)) { + info.size_iops_sec = param->value.ul; + set_size_iops = true; } } @@ -15919,11 +15965,32 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, goto endjob; } + if ((info.total_bytes_sec_max && info.read_bytes_sec_max) || + (info.total_bytes_sec_max && info.write_bytes_sec_max)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("total and read/write of bytes_sec_max cannot be set at the same time")); + goto endjob; + } + + if ((info.total_iops_sec_max && info.read_iops_sec_max) || + (info.total_iops_sec_max && info.write_iops_sec_max)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("total and read/write of iops_sec_max cannot be set at the same time")); + goto endjob; + } + if (flags & VIR_DOMAIN_AFFECT_LIVE) { if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("block I/O throttling not supported with this " - "QEMU binary")); + _("block I/O throttling not supported with this " + "QEMU binary")); + goto endjob; + } + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX) && (set_iops_max || set_bytes_max)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("a block I/O throttling parameter is not supported with this " + "QEMU binary")); goto endjob; } @@ -15936,13 +16003,25 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, info.read_bytes_sec = oldinfo->read_bytes_sec; info.write_bytes_sec = oldinfo->write_bytes_sec; } + if (!set_bytes_max) { + info.total_bytes_sec_max = oldinfo->total_bytes_sec_max; + info.read_bytes_sec_max = oldinfo->read_bytes_sec_max; + info.write_bytes_sec_max = oldinfo->write_bytes_sec_max; + } if (!set_iops) { info.total_iops_sec = oldinfo->total_iops_sec; info.read_iops_sec = oldinfo->read_iops_sec; info.write_iops_sec = oldinfo->write_iops_sec; } + if (!set_iops_max) { + info.total_iops_sec_max = oldinfo->total_iops_sec_max; + info.read_iops_sec_max = oldinfo->read_iops_sec_max; + info.write_iops_sec_max = oldinfo->write_iops_sec_max; + } + if (!set_size_iops) + info.size_iops_sec = oldinfo->size_iops_sec; qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorSetBlockIoThrottle(priv->mon, device, &info); + ret = qemuMonitorSetBlockIoThrottle(priv->mon, device, &info, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX)); qemuDomainObjExitMonitor(driver, vm); if (ret < 0) goto endjob; @@ -15957,11 +16036,23 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, info.read_bytes_sec = oldinfo->read_bytes_sec; info.write_bytes_sec = oldinfo->write_bytes_sec; } + if (!set_bytes_max) { + info.total_bytes_sec_max = oldinfo->total_bytes_sec_max; + info.read_bytes_sec_max = oldinfo->read_bytes_sec_max; + info.write_bytes_sec_max = oldinfo->write_bytes_sec_max; + } if (!set_iops) { info.total_iops_sec = oldinfo->total_iops_sec; info.read_iops_sec = oldinfo->read_iops_sec; info.write_iops_sec = oldinfo->write_iops_sec; } + if (!set_iops_max) { + info.total_iops_sec_max = oldinfo->total_iops_sec_max; + info.read_iops_sec_max = oldinfo->read_iops_sec_max; + info.write_iops_sec_max = oldinfo->write_iops_sec_max; + } + if (!set_size_iops) + info.size_iops_sec = oldinfo->size_iops_sec; persistentDef->disks[idx]->blkdeviotune = info; ret = virDomainSaveConfig(cfg->configDir, persistentDef); if (ret < 0) { @@ -15972,6 +16063,7 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, } endjob: + if (!qemuDomainObjEndJob(driver, vm)) vm = NULL; @@ -16001,6 +16093,7 @@ qemuDomainGetBlockIoTune(virDomainPtr dom, size_t i; virCapsPtr caps = NULL; virQEMUDriverConfigPtr cfg = NULL; + bool supportMaxOptions = true; virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG | @@ -16026,8 +16119,8 @@ qemuDomainGetBlockIoTune(virDomainPtr dom, goto cleanup; if ((*nparams) == 0) { - /* Current number of parameters supported by QEMU Block I/O Throttling */ - *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM; + /* Current number of parameters supported by QEMU Block I/O Throttling including the optionals parameters */ + *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX; ret = 0; goto cleanup; } @@ -16046,8 +16139,11 @@ qemuDomainGetBlockIoTune(virDomainPtr dom, if (flags & VIR_DOMAIN_AFFECT_LIVE) { priv = vm->privateData; + supportMaxOptions = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX); + if (!supportMaxOptions) + *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM; qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply); + ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply, supportMaxOptions); qemuDomainObjExitMonitor(driver, vm); if (ret < 0) goto endjob; @@ -16060,7 +16156,7 @@ qemuDomainGetBlockIoTune(virDomainPtr dom, reply = persistentDef->disks[idx]->blkdeviotune; } - for (i = 0; i < QEMU_NB_BLOCK_IO_TUNE_PARAM && i < *nparams; i++) { + for (i = 0; i < QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX && i < *nparams; i++) { virTypedParameterPtr param = ¶ms[i]; switch (i) { @@ -16106,13 +16202,63 @@ qemuDomainGetBlockIoTune(virDomainPtr dom, reply.write_iops_sec) < 0) goto endjob; break; + case 6: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + reply.total_bytes_sec_max) < 0) + goto endjob; + break; + case 7: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + reply.read_bytes_sec_max) < 0) + goto endjob; + break; + case 8: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + reply.write_bytes_sec_max) < 0) + goto endjob; + break; + case 9: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + reply.total_iops_sec_max) < 0) + goto endjob; + break; + case 10: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + reply.read_iops_sec_max) < 0) + goto endjob; + break; + case 11: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + reply.write_iops_sec_max) < 0) + goto endjob; + break; + case 12: + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC, + VIR_TYPED_PARAM_ULLONG, + reply.size_iops_sec) < 0) + goto endjob; default: break; } } - if (*nparams > QEMU_NB_BLOCK_IO_TUNE_PARAM) + if (!supportMaxOptions && *nparams > QEMU_NB_BLOCK_IO_TUNE_PARAM) *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM; + else if (*nparams > QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX) + *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX; ret = 0; endjob: diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 3d9f87b..17ff641 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3398,32 +3398,34 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon, int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr info) + virDomainBlockIoTuneInfoPtr info, + bool supportMaxOptions) { int ret; VIR_DEBUG("mon=%p, device=%p, info=%p", mon, device, info); if (mon->json) { - ret = qemuMonitorJSONSetBlockIoThrottle(mon, device, info); + ret = qemuMonitorJSONSetBlockIoThrottle(mon, device, info, supportMaxOptions); } else { - ret = qemuMonitorTextSetBlockIoThrottle(mon, device, info); + ret = qemuMonitorTextSetBlockIoThrottle(mon, device, info, supportMaxOptions); } return ret; } int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr reply) + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions) { int ret; VIR_DEBUG("mon=%p, device=%p, reply=%p", mon, device, reply); if (mon->json) { - ret = qemuMonitorJSONGetBlockIoThrottle(mon, device, reply); + ret = qemuMonitorJSONGetBlockIoThrottle(mon, device, reply, supportMaxOptions); } else { - ret = qemuMonitorTextGetBlockIoThrottle(mon, device, reply); + ret = qemuMonitorTextGetBlockIoThrottle(mon, device, reply, supportMaxOptions); } return ret; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c3695f2..c9add8f 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -708,11 +708,13 @@ int qemuMonitorOpenGraphics(qemuMonitorPtr mon, int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr info); + virDomainBlockIoTuneInfoPtr info, + bool supportMaxOptions); int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr reply); + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions); int qemuMonitorSystemWakeup(qemuMonitorPtr mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a62c02f..c2e6c5c 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3937,13 +3937,15 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon, static int qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result, const char *device, - virDomainBlockIoTuneInfoPtr reply) + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions) { virJSONValuePtr io_throttle; int ret = -1; size_t i; bool found = false; + (void)supportMaxOptions; io_throttle = virJSONValueObjectGet(result, "return"); if (!io_throttle || io_throttle->type != VIR_JSON_TYPE_ARRAY) { @@ -4008,12 +4010,14 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result, int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr info) + virDomainBlockIoTuneInfoPtr info, + bool supportMaxOptions) { int ret = -1; virJSONValuePtr cmd = NULL; virJSONValuePtr result = NULL; + (void)supportMaxOptions; cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle", "s:device", device, "U:bps", info->total_bytes_sec, @@ -4048,7 +4052,8 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon, int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr reply) + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions) { int ret = -1; virJSONValuePtr cmd = NULL; @@ -4075,7 +4080,7 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon, } if (ret == 0) - ret = qemuMonitorJSONBlockIoThrottleInfo(result, device, reply); + ret = qemuMonitorJSONBlockIoThrottleInfo(result, device, reply, supportMaxOptions); virJSONValueFree(cmd); virJSONValueFree(result); diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 5f6c846..8c01049 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -301,11 +301,13 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon, int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr info); + virDomainBlockIoTuneInfoPtr info, + bool supportMaxOptions); int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr reply); + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions); int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index fc54a11..2858247 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2985,7 +2985,8 @@ int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon, int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr info) + virDomainBlockIoTuneInfoPtr info, + bool supportMaxOptions) { char *cmd = NULL; char *result = NULL; @@ -2993,6 +2994,7 @@ int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon, const char *cmd_name = NULL; /* For the not specified fields, 0 by default */ + (void)supportMaxOptions; cmd_name = "block_set_io_throttle"; if (virAsprintf(&cmd, "%s %s %llu %llu %llu %llu %llu %llu", cmd_name, device, info->total_bytes_sec, info->read_bytes_sec, @@ -3019,15 +3021,17 @@ int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon, static int qemuMonitorTextParseBlockIoThrottle(const char *result, const char *device, - virDomainBlockIoTuneInfoPtr reply) + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions) { char *dummy = NULL; int ret = -1; const char *p, *eol; int devnamelen = strlen(device); + (void)supportMaxOptions; p = result; - + while (*p) { if (STREQLEN(p, device, devnamelen) && p[devnamelen] == ':' && p[devnamelen+1] == ' ') { @@ -3093,7 +3097,8 @@ qemuMonitorTextParseBlockIoThrottle(const char *result, int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr reply) + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions) { char *result = NULL; int ret = -1; @@ -3108,7 +3113,7 @@ int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon, goto cleanup; } - ret = qemuMonitorTextParseBlockIoThrottle(result, device, reply); + ret = qemuMonitorTextParseBlockIoThrottle(result, device, reply, supportMaxOptions); cleanup: VIR_FREE(result); diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 49d4b88..a3fb194 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -237,10 +237,12 @@ int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon, int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr info); + virDomainBlockIoTuneInfoPtr info, + bool supportMaxOptions); int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, - virDomainBlockIoTuneInfoPtr reply); + virDomainBlockIoTuneInfoPtr reply, + bool supportMaxOptions); #endif /* QEMU_MONITOR_TEXT_H */ diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 319f999..caa4512 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1847,7 +1847,7 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data) goto cleanup; if (qemuMonitorJSONGetBlockIoThrottle(qemuMonitorTestGetMonitor(test), - "drive-virtio-disk0", &info) < 0) + "drive-virtio-disk0", &info, false) < 0) goto cleanup; if (memcmp(&info, &expectedInfo, sizeof(info) != 0)) { @@ -1857,7 +1857,7 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data) } if (qemuMonitorJSONSetBlockIoThrottle(qemuMonitorTestGetMonitor(test), - "drive-virtio-disk1", &info) < 0) + "drive-virtio-disk1", &info, false) < 0) goto cleanup; ret = 0; -- 1.8.3.1

Detect if the the qemu binary currently in use suport the bps_max option, If yes add it to the command, if not, just ignore the options. Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- src/qemu/qemu_monitor_json.c | 59 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c2e6c5c..8bd506f 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3924,6 +3924,12 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon, } +#define GET_THROTTLE_STATS_OPTIONAL(FIELD, STORE) \ + if (virJSONValueObjectGetNumberUlong(inserted, \ + FIELD, \ + &reply->STORE) < 0) { \ + reply->STORE = 0; \ + } #define GET_THROTTLE_STATS(FIELD, STORE) \ if (virJSONValueObjectGetNumberUlong(inserted, \ FIELD, \ @@ -3991,7 +3997,16 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result, GET_THROTTLE_STATS("iops", total_iops_sec); GET_THROTTLE_STATS("iops_rd", read_iops_sec); GET_THROTTLE_STATS("iops_wr", write_iops_sec); - + if (supportMaxOptions) + { + GET_THROTTLE_STATS_OPTIONAL("bps_max", total_bytes_sec_max); + GET_THROTTLE_STATS_OPTIONAL("bps_rd_max", read_bytes_sec_max); + GET_THROTTLE_STATS_OPTIONAL("bps_wr_max", write_bytes_sec_max); + GET_THROTTLE_STATS_OPTIONAL("iops_max", total_iops_sec_max); + 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); + } break; } @@ -4007,6 +4022,7 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result, return ret; } #undef GET_THROTTLE_STATS +#undef GET_THROTTLE_STATS_OPTIONAL int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon, const char *device, @@ -4017,16 +4033,37 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon, virJSONValuePtr cmd = NULL; virJSONValuePtr result = NULL; - (void)supportMaxOptions; - cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle", - "s:device", device, - "U:bps", info->total_bytes_sec, - "U:bps_rd", info->read_bytes_sec, - "U:bps_wr", info->write_bytes_sec, - "U:iops", info->total_iops_sec, - "U:iops_rd", info->read_iops_sec, - "U:iops_wr", info->write_iops_sec, - NULL); + if (supportMaxOptions) + { + cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle", + "s:device", device, + "U:bps", info->total_bytes_sec, + "U:bps_rd", info->read_bytes_sec, + "U:bps_wr", info->write_bytes_sec, + "U:iops", info->total_iops_sec, + "U:iops_rd", info->read_iops_sec, + "U:iops_wr", info->write_iops_sec, + "U:bps_max", info->total_bytes_sec_max, + "U:bps_rd_max", info->read_bytes_sec_max, + "U:bps_wr_max", info->write_bytes_sec_max, + "U:iops_max", info->total_iops_sec_max, + "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, + NULL); + } + else + { + cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle", + "s:device", device, + "U:bps", info->total_bytes_sec, + "U:bps_rd", info->read_bytes_sec, + "U:bps_wr", info->write_bytes_sec, + "U:iops", info->total_iops_sec, + "U:iops_rd", info->read_iops_sec, + "U:iops_wr", info->write_iops_sec, + NULL); + } if (!cmd) return -1; -- 1.8.3.1

Detect if the the qemu binary currently in use suport the bps_max option and thy firends, If yes add it to the command, if not, just ignore the options. Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- src/qemu/qemu_monitor_text.c | 76 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 2858247..ffc67d7 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2994,13 +2994,27 @@ int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon, const char *cmd_name = NULL; /* For the not specified fields, 0 by default */ - (void)supportMaxOptions; cmd_name = "block_set_io_throttle"; - if (virAsprintf(&cmd, "%s %s %llu %llu %llu %llu %llu %llu", cmd_name, - device, info->total_bytes_sec, info->read_bytes_sec, - info->write_bytes_sec, info->total_iops_sec, - info->read_iops_sec, info->write_iops_sec) < 0) - goto cleanup; + if (supportMaxOptions) + { + if (virAsprintf(&cmd, "%s %s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", cmd_name, + device, info->total_bytes_sec, info->read_bytes_sec, + info->write_bytes_sec, info->total_iops_sec, + info->read_iops_sec, info->write_iops_sec, + info->total_bytes_sec_max, info->read_bytes_sec_max, + info->write_bytes_sec_max, info->total_iops_sec_max, + info->read_iops_sec_max, info->write_iops_sec_max, + info->size_iops_sec) < 0) + goto cleanup; + } + else + { + if (virAsprintf(&cmd, "%s %s %llu %llu %llu %llu %llu %llu", cmd_name, + device, info->total_bytes_sec, info->read_bytes_sec, + info->write_bytes_sec, info->total_iops_sec, + info->read_iops_sec, info->write_iops_sec) < 0) + goto cleanup; + } if (qemuMonitorHMPCommand(mon, cmd, &result) < 0) goto cleanup; @@ -3028,6 +3042,7 @@ qemuMonitorTextParseBlockIoThrottle(const char *result, int ret = -1; const char *p, *eol; int devnamelen = strlen(device); + bool checkBlockInfo; (void)supportMaxOptions; p = result; @@ -3043,31 +3058,78 @@ qemuMonitorTextParseBlockIoThrottle(const char *result, p += devnamelen + 2; /* Skip to first label. */ while (*p) { + checkBlockInfo = false; if (STRPREFIX(p, "bps=")) { p += strlen("bps="); + checkBlockInfo = true; if (virStrToLong_ull(p, &dummy, 10, &reply->total_bytes_sec) == -1) VIR_DEBUG("error reading total_bytes_sec: %s", p); } else if (STRPREFIX(p, "bps_rd=")) { + checkBlockInfo = true; p += strlen("bps_rd="); if (virStrToLong_ull(p, &dummy, 10, &reply->read_bytes_sec) == -1) VIR_DEBUG("error reading read_bytes_sec: %s", p); } else if (STRPREFIX(p, "bps_wr=")) { + checkBlockInfo = true; p += strlen("bps_wr="); if (virStrToLong_ull(p, &dummy, 10, &reply->write_bytes_sec) == -1) VIR_DEBUG("error reading write_bytes_sec: %s", p); } else if (STRPREFIX(p, "iops=")) { + checkBlockInfo = true; p += strlen("iops="); if (virStrToLong_ull(p, &dummy, 10, &reply->total_iops_sec) == -1) VIR_DEBUG("error reading total_iops_sec: %s", p); } else if (STRPREFIX(p, "iops_rd=")) { + checkBlockInfo = true; p += strlen("iops_rd="); if (virStrToLong_ull(p, &dummy, 10, &reply->read_iops_sec) == -1) VIR_DEBUG("error reading read_iops_sec: %s", p); } else if (STRPREFIX(p, "iops_wr=")) { + checkBlockInfo = true; p += strlen("iops_wr="); if (virStrToLong_ull(p, &dummy, 10, &reply->write_iops_sec) == -1) VIR_DEBUG("error reading write_iops_sec: %s", p); - } else { + } + if (supportMaxOptions) + { + if (STRPREFIX(p, "bps_max=")) { + checkBlockInfo = true; + p += strlen("bps_max="); + if (virStrToLong_ull(p, &dummy, 10, &reply->total_bytes_sec_max) == -1) + VIR_DEBUG("error reading total_bytes_sec_max: %s", p); + } else if (STRPREFIX(p, "bps_wr_max=")) { + checkBlockInfo = true; + p += strlen("bps_wr_max="); + if (virStrToLong_ull(p, &dummy, 10, &reply->write_bytes_sec_max) == -1) + VIR_DEBUG("error reading write_bytes_sec_max: %s", p); + } else if (STRPREFIX(p, "bps_rd_max=")) { + checkBlockInfo = true; + p += strlen("bps_rd_max="); + if (virStrToLong_ull(p, &dummy, 10, &reply->read_bytes_sec_max) == -1) + VIR_DEBUG("error reading read_bytes_sec_max: %s", p); + } else if (STRPREFIX(p, "iops_max=")) { + checkBlockInfo = true; + p += strlen("iops_max="); + if (virStrToLong_ull(p, &dummy, 10, &reply->total_iops_sec_max) == -1) + VIR_DEBUG("error reading total_iops_sec_max: %s", p); + } else if (STRPREFIX(p, "iops_rd_max=")) { + checkBlockInfo = true; + p += strlen("iops_rd_max="); + if (virStrToLong_ull(p, &dummy, 10, &reply->read_iops_sec_max) == -1) + VIR_DEBUG("error reading read_iops_sec_max: %s", p); + } else if (STRPREFIX(p, "iops_wr_max=")) { + checkBlockInfo = true; + p += strlen("iops_wr_max="); + if (virStrToLong_ull(p, &dummy, 10, &reply->write_iops_sec_max) == -1) + VIR_DEBUG("error reading write_iops_sec_max: %s", p); + } else if (STRPREFIX(p, "size_iops=")) { + checkBlockInfo = true; + p += strlen("size_iops="); + if (virStrToLong_ull(p, &dummy, 10, &reply->size_iops_sec) == -1) + VIR_DEBUG("error reading size_iops_sec: %s", p); + } + } + if (!checkBlockInfo) { VIR_DEBUG(" unknown block info %s", p); } -- 1.8.3.1

Check the arability of the options with the current qemu binary, add them in the varable opt if yes, print a message if not. Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- src/qemu/qemu_command.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8a69976..9e84e98 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3598,6 +3598,55 @@ qemuBuildDriveStr(virConnectPtr conn, disk->blkdeviotune.write_iops_sec); } + /* block I/O throttling 1.7 */ + if ((disk->blkdeviotune.total_bytes_sec_max || + disk->blkdeviotune.read_bytes_sec_max || + disk->blkdeviotune.write_bytes_sec_max || + disk->blkdeviotune.total_iops_sec_max || + disk->blkdeviotune.read_iops_sec_max || + disk->blkdeviotune.write_iops_sec_max) && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("there is some block I/O throttling paramater that are not supported with this " + "QEMU binary(need QEMU 1.7 or superior)")); + goto error; + } + + if (disk->blkdeviotune.total_bytes_sec_max) { + virBufferAsprintf(&opt, ",bps_max=%llu", + disk->blkdeviotune.total_bytes_sec_max); + } + + if (disk->blkdeviotune.read_bytes_sec_max) { + virBufferAsprintf(&opt, ",bps_rd_max=%llu", + disk->blkdeviotune.read_bytes_sec_max); + } + + if (disk->blkdeviotune.write_bytes_sec_max) { + virBufferAsprintf(&opt, ",bps_wr_max=%llu", + disk->blkdeviotune.write_bytes_sec_max); + } + + if (disk->blkdeviotune.total_iops_sec_max) { + virBufferAsprintf(&opt, ",iops_max=%llu", + disk->blkdeviotune.total_iops_sec_max); + } + + if (disk->blkdeviotune.read_iops_sec_max) { + virBufferAsprintf(&opt, ",iops_rd_max=%llu", + disk->blkdeviotune.read_iops_sec_max); + } + + if (disk->blkdeviotune.write_iops_sec_max) { + virBufferAsprintf(&opt, ",iops_wr_max=%llu", + disk->blkdeviotune.write_iops_sec_max); + } + + if (disk->blkdeviotune.write_iops_sec_max) { + virBufferAsprintf(&opt, ",iops_size=%llu", + disk->blkdeviotune.size_iops_sec); + } + if (virBufferCheckError(&opt) < 0) goto error; -- 1.8.3.1

Add the new throttle options to virsh, and send them to libvirt. Signed-off-by: Matthias Gatto <matthias.gatto@outscale.com> --- tools/virsh-domain.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++++- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index f7193cb..cf7884f 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -1082,6 +1082,62 @@ static const vshCmdOptDef opts_blkdeviotune[] = { .type = VSH_OT_INT, .help = N_("write I/O operations limit per second") }, + {.name = "total_bytes_sec_max", + .type = VSH_OT_ALIAS, + .help = "total-bytes-sec-max" + }, + {.name = "total-bytes-sec-max", + .type = VSH_OT_INT, + .help = N_("total max in bytes") + }, + {.name = "read_bytes_sec_max", + .type = VSH_OT_ALIAS, + .help = "read-bytes-sec-max" + }, + {.name = "read-bytes-sec-max", + .type = VSH_OT_INT, + .help = N_("read max in bytes") + }, + {.name = "write_bytes_sec_max", + .type = VSH_OT_ALIAS, + .help = "write-bytes-sec-max" + }, + {.name = "write-bytes-sec-max", + .type = VSH_OT_INT, + .help = N_("write max in bytes") + }, + {.name = "total_iops_sec_max", + .type = VSH_OT_ALIAS, + .help = "total-iops-sec-max" + }, + {.name = "total-iops-sec-max", + .type = VSH_OT_INT, + .help = N_("total I/O operations max") + }, + {.name = "read_iops_sec_max", + .type = VSH_OT_ALIAS, + .help = "read-iops-sec-max" + }, + {.name = "read-iops-sec-max", + .type = VSH_OT_INT, + .help = N_("read I/O operations max") + }, + {.name = "write_iops_sec_max", + .type = VSH_OT_ALIAS, + .help = "write-iops-sec-max" + }, + {.name = "write-iops-sec-max", + .type = VSH_OT_INT, + .help = N_("write I/O operations max") + }, + {.name = "size_iops_sec", + .type = VSH_OT_ALIAS, + .help = "size-iops-sec" + }, + {.name = "size-iops-sec", + .type = VSH_OT_INT, + .help = N_("I/O size in bytes") + }, {.name = "config", .type = VSH_OT_BOOL, .help = N_("affect next boot") @@ -1155,6 +1211,33 @@ cmdBlkdeviotune(vshControl *ctl, const vshCmd *cmd) goto save_error; } + if ((rv = vshCommandOptULongLong(cmd, "total-bytes-sec-max", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX, + value) < 0) + goto save_error; + } + + if ((rv = vshCommandOptULongLong(cmd, "read-bytes-sec-max", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX, + value) < 0) + goto save_error; + } + + if ((rv = vshCommandOptULongLong(cmd, "write-bytes-sec-max", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX, + value) < 0) + goto save_error; + } + if ((rv = vshCommandOptULongLong(cmd, "total-iops-sec", &value)) < 0) { goto interror; } else if (rv > 0) { @@ -1182,6 +1265,42 @@ cmdBlkdeviotune(vshControl *ctl, const vshCmd *cmd) goto save_error; } + if ((rv = vshCommandOptULongLong(cmd, "write-iops-sec-max", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX, + value) < 0) + goto save_error; + } + + if ((rv = vshCommandOptULongLong(cmd, "read-iops-sec-max", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX, + value) < 0) + goto save_error; + } + + if ((rv = vshCommandOptULongLong(cmd, "total-iops-sec-max", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX, + value) < 0) + goto save_error; + } + + if ((rv = vshCommandOptULongLong(cmd, "size-iops-sec", &value)) < 0) { + goto interror; + } else if (rv > 0) { + if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC, + value) < 0) + goto save_error; + } + if (nparams == 0) { if (virDomainGetBlockIoTune(dom, NULL, NULL, &nparams, flags) != 0) { vshError(ctl, "%s", diff --git a/tools/virsh.pod b/tools/virsh.pod index 26b1d79..787f9a0 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -954,7 +954,9 @@ convert it to the maximum value allowed. [[I<--config>] [I<--live>] | [I<--current>]] [[I<total-bytes-sec>] | [I<read-bytes-sec>] [I<write-bytes-sec>]] [[I<total-iops-sec>] | [I<read-iops-sec>] [I<write-iops-sec>]] - +[[I<total-bytes-sec-max>] | [I<read-bytes-sec-max>] [I<write-bytes-sec-max>]] +[[I<total-iops-sec-max>] | [I<read-iops-sec-max>] [I<write-iops-sec-max>]] +[I<size-iops-sec>] Set or query the block disk io parameters for a block device of I<domain>. I<device> specifies a unique target name (<target dev='name'/>) or source file (<source file='name'/>) for one of the disk devices attached to @@ -968,6 +970,13 @@ I<--write-bytes-sec> specifies write throughput limit in bytes per second. I<--total-iops-sec> specifies total I/O operations limit per second. I<--read-iops-sec> specifies read I/O operations limit per second. I<--write-iops-sec> specifies write I/O operations limit per second. +I<--total-bytes-sec-max> specifies maximum total throughput limit in bytes per second. +I<--read-bytes-sec-max> specifies maximum read throughput limit in bytes per second. +I<--write-bytes-sec-max> specifies maximum write throughput limit in bytes per second. +I<--total-iops-sec-max> specifies maximum total I/O operations limit per second. +I<--read-iops-sec-max> specifies maximum read I/O operations limit per second. +I<--write-iops-sec-max> specifies maximum write I/O operations limit per second. +I<--size-iops-sec> specifies size I/O operations limit per second. Older versions of virsh only accepted these options with underscore instead of dash, as in I<--total_bytes_sec>. -- 1.8.3.1

On 23.09.2014 16:13, Matthias Gatto wrote:
This series of patches add support for bps_max, bps_rd_max, bps_wr_max, bps_max, bps_rd_max, bps_wr_max, and iops_size in the functions qemuDomainSetBlockIoTune and qemuDomainGetBlockIoTune. The last patch add support for these parameters to the virsh blkdeviotune command.
v2: spellfix
v3: Merge patch 1/9,2/9,5/9 together. Change the capability detection.(patch 2/7 and 3/7). Try to make the usage of QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX more explicit(patch 3/7).
Matthias Gatto (7): qemu: Add defines for the news throttle options and modify the structure _virDomainBlockIoTuneInfo. qemu: Add the capability to detect if the qemu binary have the capability to use bps_max and friends qemu: Add bps_max and friends qemu driver qemu: Add bps_max and friends QMP suport qemu: Add bps_max and friends "text" support qemu: add bps_max and friends to qemu command generation virsh: Add bps_max and friends to virsh
include/libvirt/libvirt.h.in | 54 +++++++++++++++ src/conf/domain_conf.c | 89 +++++++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 +++++++++++++ src/qemu/qemu_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 6 +- src/qemu/qemu_monitor_json.c | 70 +++++++++++++++---- src/qemu/qemu_monitor_json.h | 6 +- src/qemu/qemu_monitor_text.c | 89 +++++++++++++++++++++--- src/qemu/qemu_monitor_text.h | 6 +- tests/qemumonitorjsontest.c | 6 +- tools/virsh-domain.c | 119 +++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++- 16 files changed, 643 insertions(+), 50 deletions(-)
Interesting, you've sent the patches only two days ago, but I'm unable to apply it cleanly. And what even more weird is that I had to go all the way down to 1.2.7 release to apply your patches. Can you please rebase to the current HEAD and resend? Be aware of Pavel's patches, esp. 18fc3199. Michal

On Thu, Sep 25, 2014 at 4:08 PM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 23.09.2014 16:13, Matthias Gatto wrote:
This series of patches add support for bps_max, bps_rd_max, bps_wr_max, bps_max, bps_rd_max, bps_wr_max, and iops_size in the functions qemuDomainSetBlockIoTune and qemuDomainGetBlockIoTune. The last patch add support for these parameters to the virsh blkdeviotune command.
v2: spellfix
v3: Merge patch 1/9,2/9,5/9 together. Change the capability detection.(patch 2/7 and 3/7). Try to make the usage of QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX more explicit(patch 3/7).
Matthias Gatto (7): qemu: Add defines for the news throttle options and modify the structure _virDomainBlockIoTuneInfo. qemu: Add the capability to detect if the qemu binary have the capability to use bps_max and friends qemu: Add bps_max and friends qemu driver qemu: Add bps_max and friends QMP suport qemu: Add bps_max and friends "text" support qemu: add bps_max and friends to qemu command generation virsh: Add bps_max and friends to virsh
include/libvirt/libvirt.h.in | 54 +++++++++++++++ src/conf/domain_conf.c | 89 +++++++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 +++++++++++++ src/qemu/qemu_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 6 +- src/qemu/qemu_monitor_json.c | 70 +++++++++++++++---- src/qemu/qemu_monitor_json.h | 6 +- src/qemu/qemu_monitor_text.c | 89 +++++++++++++++++++++--- src/qemu/qemu_monitor_text.h | 6 +- tests/qemumonitorjsontest.c | 6 +- tools/virsh-domain.c | 119 +++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++- 16 files changed, 643 insertions(+), 50 deletions(-)
Interesting, you've sent the patches only two days ago, but I'm unable to apply it cleanly. And what even more weird is that I had to go all the way down to 1.2.7 release to apply your patches. Can you please rebase to the current HEAD and resend? Be aware of Pavel's patches, esp. 18fc3199.
Michal
Ok i do it now. Sorry for the inconvenience.

On Mon, Sep 29, 2014 at 10:32 AM, Matthias Gatto <matthias.gatto@outscale.com> wrote:
On Thu, Sep 25, 2014 at 4:08 PM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 23.09.2014 16:13, Matthias Gatto wrote:
This series of patches add support for bps_max, bps_rd_max, bps_wr_max, bps_max, bps_rd_max, bps_wr_max, and iops_size in the functions qemuDomainSetBlockIoTune and qemuDomainGetBlockIoTune. The last patch add support for these parameters to the virsh blkdeviotune command.
v2: spellfix
v3: Merge patch 1/9,2/9,5/9 together. Change the capability detection.(patch 2/7 and 3/7). Try to make the usage of QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX more explicit(patch 3/7).
Matthias Gatto (7): qemu: Add defines for the news throttle options and modify the structure _virDomainBlockIoTuneInfo. qemu: Add the capability to detect if the qemu binary have the capability to use bps_max and friends qemu: Add bps_max and friends qemu driver qemu: Add bps_max and friends QMP suport qemu: Add bps_max and friends "text" support qemu: add bps_max and friends to qemu command generation virsh: Add bps_max and friends to virsh
include/libvirt/libvirt.h.in | 54 +++++++++++++++ src/conf/domain_conf.c | 89 +++++++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 +++++++++++++ src/qemu/qemu_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 6 +- src/qemu/qemu_monitor_json.c | 70 +++++++++++++++---- src/qemu/qemu_monitor_json.h | 6 +- src/qemu/qemu_monitor_text.c | 89 +++++++++++++++++++++--- src/qemu/qemu_monitor_text.h | 6 +- tests/qemumonitorjsontest.c | 6 +- tools/virsh-domain.c | 119 +++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++- 16 files changed, 643 insertions(+), 50 deletions(-)
Interesting, you've sent the patches only two days ago, but I'm unable to apply it cleanly. And what even more weird is that I had to go all the way down to 1.2.7 release to apply your patches. Can you please rebase to the current HEAD and resend? Be aware of Pavel's patches, esp. 18fc3199.
Michal
Ok i do it now. Sorry for the inconvenience. I have a question BTW: I've saw you don't use qemu_monitor_text for the new qemu binary, do I have to remove the code I've made for this file ?

On 29.09.2014 10:36, Matthias Gatto wrote:
On Mon, Sep 29, 2014 at 10:32 AM, Matthias Gatto <matthias.gatto@outscale.com> wrote:
On Thu, Sep 25, 2014 at 4:08 PM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 23.09.2014 16:13, Matthias Gatto wrote:
This series of patches add support for bps_max, bps_rd_max, bps_wr_max, bps_max, bps_rd_max, bps_wr_max, and iops_size in the functions qemuDomainSetBlockIoTune and qemuDomainGetBlockIoTune. The last patch add support for these parameters to the virsh blkdeviotune command.
v2: spellfix
v3: Merge patch 1/9,2/9,5/9 together. Change the capability detection.(patch 2/7 and 3/7). Try to make the usage of QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX more explicit(patch 3/7).
Matthias Gatto (7): qemu: Add defines for the news throttle options and modify the structure _virDomainBlockIoTuneInfo. qemu: Add the capability to detect if the qemu binary have the capability to use bps_max and friends qemu: Add bps_max and friends qemu driver qemu: Add bps_max and friends QMP suport qemu: Add bps_max and friends "text" support qemu: add bps_max and friends to qemu command generation virsh: Add bps_max and friends to virsh
include/libvirt/libvirt.h.in | 54 +++++++++++++++ src/conf/domain_conf.c | 89 +++++++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 +++++++++++++ src/qemu/qemu_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor.c | 14 ++-- src/qemu/qemu_monitor.h | 6 +- src/qemu/qemu_monitor_json.c | 70 +++++++++++++++---- src/qemu/qemu_monitor_json.h | 6 +- src/qemu/qemu_monitor_text.c | 89 +++++++++++++++++++++--- src/qemu/qemu_monitor_text.h | 6 +- tests/qemumonitorjsontest.c | 6 +- tools/virsh-domain.c | 119 +++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++- 16 files changed, 643 insertions(+), 50 deletions(-)
Interesting, you've sent the patches only two days ago, but I'm unable to apply it cleanly. And what even more weird is that I had to go all the way down to 1.2.7 release to apply your patches. Can you please rebase to the current HEAD and resend? Be aware of Pavel's patches, esp. 18fc3199.
Michal
Ok i do it now. Sorry for the inconvenience. I have a question BTW: I've saw you don't use qemu_monitor_text for the new qemu binary, do I have to remove the code I've made for this file ?
Well, the code can be kept around although libvirt will use QMP whenever possible. And you could say QMP is around for a while so the _text won't be used at all. I wonder if there's a qemu that would have this feature enabled but don't use QMP. So yes, you can just drop the _text implementation. Michal
participants (2)
-
Matthias Gatto
-
Michal Privoznik