Re: [libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
On Wed, Nov 23, 2011 at 10:41:32AM -0700, Eric Blake wrote: Hmm - passing nparams==1 to set just read_bytes_sec has the side effect of wiping out any existing total_iops_sec, even though those two parameters seem somewhat orthogonal, all because we zero-initialized the struct that we pass on to the monitor command. Is that intended? I can live with it (but it probably ought to be documented), but we may want to consider being more flexible, by using '0' to clear a previous limit, but initializing to '-1' to imply the limit does not change. Then the qemu_monitor_json code should only emit the arguments that are actually being changed, rather than blindly always outputting 6 parameters even when the user only passed in one parameter. But I'm okay delaying that to a separate patch based on whether others think it would be a good improvement. +1. I believe I had pointed this out previously as well (albeit not as concisely as this). -- Adam Litke a...@us.ibm.com IBM Linux Technology Center -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
On 11/28/2011 11:24 PM, Adam Litke wrote: On Wed, Nov 23, 2011 at 10:41:32AM -0700, Eric Blake wrote: Hmm - passing nparams==1 to set just read_bytes_sec has the side effect of wiping out any existing total_iops_sec, even though those two parameters seem somewhat orthogonal, all because we zero-initialized the struct that we pass on to the monitor command. Is that intended? I can live with it (but it probably ought to be documented), but we may want to consider being more flexible, by using '0' to clear a previous limit, but initializing to '-1' to imply the limit does not change. Then the qemu_monitor_json code should only emit the arguments that are actually being changed, rather than blindly always outputting 6 parameters even when the user only passed in one parameter. But I'm okay delaying that to a separate patch based on whether others think it would be a good improvement. +1. I believe I had pointed this out previously as well (albeit not as concisely as this). Well, here is the description of block I/O throttling command 'block_io_set_throttle' in qmp-commands.hx. EQMP { .name = block_set_io_throttle, .args_type = device:B,bps:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?, .params = device [bps] [bps_rd] [bps_wr] [iops] [iops_rd] [iops_wr], .help = change I/O throttle limits for a block drive, .user_print = monitor_user_noop, .mhandler.cmd_new = do_block_set_io_throttle, }, SQMP block_set_io_throttle Change I/O throttle limits for a block drive. Arguments: - device: device name (json-string) - bps: total throughput limit in bytes per second(json-int, optional) - bps_rd: read throughput limit in bytes per second(json-int, optional) - bps_wr: read throughput limit in bytes per second(json-int, optional) - iops: total I/O operations per second(json-int, optional) - iops_rd: read I/O operations per second(json-int, optional) - iops_wr: write I/O operations per second(json-int, optional) Example: - { execute: block_set_io_throttle, arguments: { device: virtio0, bps: 100, bps_rd: 0, bps_wr: 0, iops: 0, iops_rd: 0, iops_wr: 0 } } - { return: {} } This qmp command need all these 6 parameters at one time in qemu, so zero-initialized the struct to meet If there is no setting value for some of the fields. -- Lei -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
On 11/15/2011 02:02 AM, Lei Li wrote: Implement the block I/O throttle setting and getting support to qemu driver. Signed-off-by: Lei Li li...@linux.vnet.ibm.com Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 342 ++ src/qemu/qemu_monitor.c | 37 + src/qemu/qemu_monitor.h | 22 +++ src/qemu/qemu_monitor_json.c | 186 +++ src/qemu/qemu_monitor_json.h | 10 ++ src/qemu/qemu_monitor_text.c | 165 src/qemu/qemu_monitor_text.h | 10 ++ 7 files changed, 772 insertions(+), 0 deletions(-) Now that I've finished reviewing 4/8 and 6/8, I'm back to this one. In addition to the syntax check fixes I previously mentioned... +static int +qemuDomainSetBlockIoTune(virDomainPtr dom, + const char *disk, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + +device = qemuDiskPathToAlias(vm, disk); Huh, I just noticed that qemuDiskPathToAlias returns a malloc'd string as const char*, which is not const-correct. I'll fix that separately. +if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) 0) +goto cleanup; + +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_AFFECT_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_AFFECT_LIVE; +else +flags = VIR_DOMAIN_AFFECT_CONFIG; +} + +if (!isActive (flags VIR_DOMAIN_AFFECT_LIVE)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(domain is not running)); +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto endjob; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto endjob; +} Hmm, we repeat this chunk of code in several functions; maybe it's time to factor it into a helper method. But that's a patch for another day. + +for (i = 0; i nparams; i++) { +virTypedParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC)) { + +info.total_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) { +info.read_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) { +info.write_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) { +info.total_iops_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) { +info.read_iops_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) { +info.write_iops_sec = params[i].value.ul; This is not type-safe. You have to also validate that the user passed a ullong value before you blindly dereference the value.ul union memory. Hmm - passing nparams==1 to set just read_bytes_sec has the side effect of wiping out any existing total_iops_sec, even though those two parameters seem somewhat orthogonal, all because we zero-initialized the struct that we pass on to the monitor command. Is that intended? I can live with it (but it probably ought to be documented), but we may want to consider being more flexible, by using '0' to clear a previous limit, but initializing to '-1' to imply the limit does not change. Then the qemu_monitor_json code should only emit the arguments that are actually being changed, rather than blindly always outputting 6 parameters even when the user only passed in one parameter. But I'm okay delaying that to a separate patch based on whether others think it would be a good improvement. +} else { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(Unrecognized parameter)); Why not tell the user which parameter name was not recognized? Also, this is not an OPERATION_INVALID, but an INVALID_ARG (it is bad input, not input that might be valid if the domain were in a different state). +goto endjob; +} +} + +if ((info.total_bytes_sec info.read_bytes_sec) || +(info.total_bytes_sec info.write_bytes_sec)) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(total and read/write of bytes_sec cannot be set at the same time)); +goto endjob; +} + +if ((info.total_iops_sec info.read_iops_sec) || +(info.total_iops_sec info.write_iops_sec)) { +
Re: [libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
On 11/15/2011 02:02 AM, Lei Li wrote: Implement the block I/O throttle setting and getting support to qemu driver. Signed-off-by: Lei Li li...@linux.vnet.ibm.com Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 342 ++ src/qemu/qemu_monitor.c | 37 + src/qemu/qemu_monitor.h | 22 +++ src/qemu/qemu_monitor_json.c | 186 +++ src/qemu/qemu_monitor_json.h | 10 ++ src/qemu/qemu_monitor_text.c | 165 src/qemu/qemu_monitor_text.h | 10 ++ 7 files changed, 772 insertions(+), 0 deletions(-) 'make syntax-check' didn't like this one: libvirt_unmarked_diagnostics src/qemu/qemu_monitor_json.c-3332-), total_bytes_sec); src/qemu/qemu_monitor_json.c-3338-), read_bytes_sec); src/qemu/qemu_monitor_json.c-3344-), write_bytes_sec); src/qemu/qemu_monitor_json.c-3350-), total_iops_sec); src/qemu/qemu_monitor_json.c-3356-), read_iops_sec); src/qemu/qemu_monitor_json.c-3362-), write_iops_sec); maint.mk: found unmarked diagnostic(s) I ended up shuffling those lines around. Also, prohibit_empty_lines_at_EOF src/qemu/qemu_monitor_json.c src/qemu/qemu_monitor_text.c maint.mk: empty line(s) or no newline at EOF I stripped the spurious whitespace. diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5f4a18d..0a4eaa9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -94,6 +94,8 @@ #define QEMU_NB_MEM_PARAM 3 +#define QEMU_NB_BLKIOTHROTTLE_PARAM 6 Naming should match the public API. After fixing the syntax errors, I then got: qemu/qemu_driver.c: In function 'qemuDomainSetBlockIoTune': qemu/qemu_driver.c:10881:34: error: 'virDomainDiskDef' has no member named 'blkdeviotune' Ouch - your patches are submitted out of order. Looks like I'll have to defer further review of this one until domain_conf.h is updated. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
Implement the block I/O throttle setting and getting support to qemu driver. Signed-off-by: Lei Li li...@linux.vnet.ibm.com Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 342 ++ src/qemu/qemu_monitor.c | 37 + src/qemu/qemu_monitor.h | 22 +++ src/qemu/qemu_monitor_json.c | 186 +++ src/qemu/qemu_monitor_json.h | 10 ++ src/qemu/qemu_monitor_text.c | 165 src/qemu/qemu_monitor_text.h | 10 ++ 7 files changed, 772 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5f4a18d..0a4eaa9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -94,6 +94,8 @@ #define QEMU_NB_MEM_PARAM 3 +#define QEMU_NB_BLKIOTHROTTLE_PARAM 6 + #if HAVE_LINUX_KVM_H # include linux/kvm.h #endif @@ -10775,6 +10777,344 @@ cleanup: return ret; } +static int +qemuDomainSetBlockIoTune(virDomainPtr dom, + const char *disk, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ +struct qemud_driver *driver = dom-conn-privateData; +virDomainObjPtr vm = NULL; +qemuDomainObjPrivatePtr priv; +virDomainDefPtr persistentDef = NULL; +virDomainBlockIoTuneInfo info; +char uuidstr[VIR_UUID_STRING_BUFLEN]; +const char *device = NULL; +int ret = -1; +int i; +bool isActive; + +virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + +memset(info, 0, sizeof(info)); + +qemuDriverLock(driver); +virUUIDFormat(dom-uuid, uuidstr); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +if (!vm) { +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +device = qemuDiskPathToAlias(vm, disk); +if (!device) { +goto cleanup; +} + +if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) 0) +goto cleanup; + +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_AFFECT_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_AFFECT_LIVE; +else +flags = VIR_DOMAIN_AFFECT_CONFIG; +} + +if (!isActive (flags VIR_DOMAIN_AFFECT_LIVE)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(domain is not running)); +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto endjob; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto endjob; +} + +for (i = 0; i nparams; i++) { +virTypedParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC)) { + +info.total_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) { +info.read_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) { +info.write_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) { +info.total_iops_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) { +info.read_iops_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) { +info.write_iops_sec = params[i].value.ul; +} else { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(Unrecognized parameter)); +goto endjob; +} +} + +if ((info.total_bytes_sec info.read_bytes_sec) || +(info.total_bytes_sec info.write_bytes_sec)) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(total and read/write of bytes_sec cannot be set at the same time)); +goto endjob; +} + +if ((info.total_iops_sec info.read_iops_sec) || +(info.total_iops_sec info.write_iops_sec)) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(total and read/write of iops_sec cannot be set at the same time)); +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_LIVE) { +priv = vm-privateData; +qemuDomainObjEnterMonitorWithDriver(driver, vm); +ret = qemuMonitorSetBlockIoThrottle(priv-mon, device, info, 1); +qemuDomainObjExitMonitorWithDriver(driver, vm); +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +sa_assert(persistentDef); +int idx =
[libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
This patch implement the block I/O throttle setting and getting support to qemu driver. Signed-off-by: Lei Li li...@linux.vnet.ibm.com Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 340 ++ src/qemu/qemu_monitor.c | 37 + src/qemu/qemu_monitor.h | 22 +++ src/qemu/qemu_monitor_json.c | 185 +++ src/qemu/qemu_monitor_json.h | 10 ++ src/qemu/qemu_monitor_text.c | 164 src/qemu/qemu_monitor_text.h | 10 ++ 7 files changed, 768 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5f4a18d..740d2a2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10775,6 +10775,344 @@ cleanup: return ret; } +static int +qemuDomainSetBlockIoTune(virDomainPtr dom, + const char *disk, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ +struct qemud_driver *driver = dom-conn-privateData; +virDomainObjPtr vm = NULL; +qemuDomainObjPrivatePtr priv; +virDomainDefPtr persistentDef = NULL; +virDomainBlockIoTuneInfo info; +char uuidstr[VIR_UUID_STRING_BUFLEN]; +const char *device = NULL; +int ret = -1; +int i; +bool isActive; + +virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + +memset(info, 0, sizeof(info)); + +qemuDriverLock(driver); +virUUIDFormat(dom-uuid, uuidstr); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +if (!vm) { +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +device = qemuDiskPathToAlias(vm, disk); +if (!device) { +goto cleanup; +} + +if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) 0) +goto cleanup; + +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_AFFECT_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_AFFECT_LIVE; +else +flags = VIR_DOMAIN_AFFECT_CONFIG; +} + +if (!isActive (flags VIR_DOMAIN_AFFECT_LIVE)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(domain is not running)); +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto endjob; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto endjob; +} + +for (i = 0; i nparams; i++) { +virTypedParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC)) { + +info.total_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) { +info.read_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) { +info.write_bytes_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) { +info.total_iops_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) { +info.read_iops_sec = params[i].value.ul; +} else if (STREQ(param-field, VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) { +info.write_iops_sec = params[i].value.ul; +} else { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(Unrecognized parameter)); +goto endjob; +} +} + +if ((info.total_bytes_sec info.read_bytes_sec) || +(info.total_bytes_sec info.write_bytes_sec)) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(total and read/write of bytes_sec cannot be set at the same time)); +goto endjob; +} + +if ((info.total_iops_sec info.read_iops_sec) || +(info.total_iops_sec info.write_iops_sec)) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(total and read/write of iops_sec cannot be set at the same time)); +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_LIVE) { +priv = vm-privateData; +qemuDomainObjEnterMonitorWithDriver(driver, vm); +ret = qemuMonitorSetBlockIoThrottle(priv-mon, device, info, 1); +qemuDomainObjExitMonitorWithDriver(driver, vm); +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +sa_assert(persistentDef); +int idx = virDomainDiskIndexByName(vm-def, disk, true); +if (i 0) +goto endjob; +persistentDef-disks[idx]-blkdeviotune.total_bytes_sec =
Re: [libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
On Thu, Nov 10, 2011 at 04:32:53AM +0800, Lei HH Li wrote: This patch implement the blk io throttle setting and getting support to qemu driver. Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 216 ++ src/qemu/qemu_monitor.c | 36 +++ src/qemu/qemu_monitor.h | 10 ++ src/qemu/qemu_monitor_json.c | 191 + src/qemu/qemu_monitor_json.h | 10 ++ src/qemu/qemu_monitor_text.c | 152 + src/qemu/qemu_monitor_text.h | 10 ++ 7 files changed, 625 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index db2ac0d..7ca6719 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10759,6 +10759,220 @@ cleanup: return ret; } +static int +qemuDomainSetBlockIoTune(virDomainPtr dom, + const char *disk, + virDomainBlockIoTuneInfoPtr info, + unsigned int flags) +{ +struct qemud_driver *driver = dom-conn-privateData; +virDomainObjPtr vm = NULL; +qemuDomainObjPrivatePtr priv; +virDomainDefPtr persistentDef = NULL; +char uuidstr[VIR_UUID_STRING_BUFLEN]; +const char *device = NULL; +int ret = -1; +bool isActive; + +virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + +qemuDriverLock(driver); +virUUIDFormat(dom-uuid, uuidstr); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +if (!vm) { +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +device = qemuDiskPathToAlias(vm, disk); +if (!device) { +goto cleanup; +} + +if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) 0) +goto cleanup; + +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_AFFECT_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_AFFECT_LIVE; +else +flags = VIR_DOMAIN_AFFECT_CONFIG; +} + +if ((info-total_bytes_sec info-read_bytes_sec) || +(info-total_bytes_sec info-write_bytes_sec)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(bps and bps_rd/bps_wr cannot be used at the same time)); These messages should use the user visible names for the fields (ie. read_bytes_sec). +goto endjob; +} + +if ((info-total_iops_sec info-read_iops_sec) || +(info-total_iops_sec info-write_iops_sec)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(iops and iops_rd/iops_wr cannot be used at the same time)); Same here. +goto endjob; +} + +if (!isActive (flags VIR_DOMAIN_AFFECT_LIVE)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(domain is not running)); +goto endjob; +} + + if (flags VIR_DOMAIN_AFFECT_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto endjob; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_LIVE) { +priv = vm-privateData; +qemuDomainObjEnterMonitorWithDriver(driver, vm); +ret = qemuMonitorSetBlockIoThrottle(priv-mon, device, info, 1); +qemuDomainObjExitMonitorWithDriver(driver, vm); +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +sa_assert(persistentDef); +int i = virDomainDiskIndexByName(vm-def, disk, true); +if (i 0) +goto endjob; +persistentDef-disks[i]-blkdeviotune.total_bytes_sec = info-total_bytes_sec; +persistentDef-disks[i]-blkdeviotune.read_bytes_sec = info-read_bytes_sec; +persistentDef-disks[i]-blkdeviotune.write_bytes_sec = info-write_bytes_sec; +persistentDef-disks[i]-blkdeviotune.total_iops_sec = info-total_iops_sec; +persistentDef-disks[i]-blkdeviotune.read_iops_sec = info-read_iops_sec; +persistentDef-disks[i]-blkdeviotune.write_iops_sec = info-write_iops_sec; +persistentDef-disks[i]-blkdeviotune.mark = 1; +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +ret = virDomainSaveConfig(driver-configDir, persistentDef); +if (ret 0) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, + _(Write to config file failed)); +goto endjob; +} +} + +endjob: +if (qemuDomainObjEndJob(driver, vm) == 0) +vm = NULL; +
[libvirt] [PATCH 3/8] Implement virDomain{Set, Get}BlockIoTune for the qemu driver
This patch implement the blk io throttle setting and getting support to qemu driver. Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 216 ++ src/qemu/qemu_monitor.c | 36 +++ src/qemu/qemu_monitor.h | 10 ++ src/qemu/qemu_monitor_json.c | 191 + src/qemu/qemu_monitor_json.h | 10 ++ src/qemu/qemu_monitor_text.c | 152 + src/qemu/qemu_monitor_text.h | 10 ++ 7 files changed, 625 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index db2ac0d..7ca6719 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10759,6 +10759,220 @@ cleanup: return ret; } +static int +qemuDomainSetBlockIoTune(virDomainPtr dom, + const char *disk, + virDomainBlockIoTuneInfoPtr info, + unsigned int flags) +{ +struct qemud_driver *driver = dom-conn-privateData; +virDomainObjPtr vm = NULL; +qemuDomainObjPrivatePtr priv; +virDomainDefPtr persistentDef = NULL; +char uuidstr[VIR_UUID_STRING_BUFLEN]; +const char *device = NULL; +int ret = -1; +bool isActive; + +virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + +qemuDriverLock(driver); +virUUIDFormat(dom-uuid, uuidstr); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +if (!vm) { +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +device = qemuDiskPathToAlias(vm, disk); +if (!device) { +goto cleanup; +} + +if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) 0) +goto cleanup; + +isActive = virDomainObjIsActive(vm); + +if (flags == VIR_DOMAIN_AFFECT_CURRENT) { +if (isActive) +flags = VIR_DOMAIN_AFFECT_LIVE; +else +flags = VIR_DOMAIN_AFFECT_CONFIG; +} + +if ((info-total_bytes_sec info-read_bytes_sec) || +(info-total_bytes_sec info-write_bytes_sec)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(bps and bps_rd/bps_wr cannot be used at the same time)); +goto endjob; +} + +if ((info-total_iops_sec info-read_iops_sec) || +(info-total_iops_sec info-write_iops_sec)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(iops and iops_rd/iops_wr cannot be used at the same time)); +goto endjob; +} + +if (!isActive (flags VIR_DOMAIN_AFFECT_LIVE)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(domain is not running)); +goto endjob; +} + + if (flags VIR_DOMAIN_AFFECT_CONFIG) { +if (!vm-persistent) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot change persistent config of a transient domain)); +goto endjob; +} +if (!(persistentDef = virDomainObjGetPersistentDef(driver-caps, vm))) +goto endjob; +} + +if (flags VIR_DOMAIN_AFFECT_LIVE) { +priv = vm-privateData; +qemuDomainObjEnterMonitorWithDriver(driver, vm); +ret = qemuMonitorSetBlockIoThrottle(priv-mon, device, info, 1); +qemuDomainObjExitMonitorWithDriver(driver, vm); +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +sa_assert(persistentDef); +int i = virDomainDiskIndexByName(vm-def, disk, true); +if (i 0) +goto endjob; +persistentDef-disks[i]-blkdeviotune.total_bytes_sec = info-total_bytes_sec; +persistentDef-disks[i]-blkdeviotune.read_bytes_sec = info-read_bytes_sec; +persistentDef-disks[i]-blkdeviotune.write_bytes_sec = info-write_bytes_sec; +persistentDef-disks[i]-blkdeviotune.total_iops_sec = info-total_iops_sec; +persistentDef-disks[i]-blkdeviotune.read_iops_sec = info-read_iops_sec; +persistentDef-disks[i]-blkdeviotune.write_iops_sec = info-write_iops_sec; +persistentDef-disks[i]-blkdeviotune.mark = 1; +} + +if (flags VIR_DOMAIN_AFFECT_CONFIG) { +ret = virDomainSaveConfig(driver-configDir, persistentDef); +if (ret 0) { +qemuReportError(VIR_ERR_OPERATION_INVALID, %s, + _(Write to config file failed)); +goto endjob; +} +} + +endjob: +if (qemuDomainObjEndJob(driver, vm) == 0) +vm = NULL; + +cleanup: +VIR_FREE(device); +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + +static int +qemuDomainGetBlockIoTune(virDomainPtr dom, + const char *disk, + virDomainBlockIoTuneInfoPtr reply, +