With this patch, user can setup the throttle blkio cgorup for domain through the virsh cmd, such as: virsh blkiotune domain1 --device-read-bps /dev/sda1,10000,/dev/sda2,20000 --device-write-bps /dev/sda1,10000 --device-read-iops /dev/sda1,10000 --device-write-iops /dev/sda1,10000,/dev/sda2,0 Signed-off-by: Guan Qiang <hzguanqiang@xxxxxxxxxxxxxxxx> Signed-off-by: Gao feng <gaofeng@xxxxxxxxxxxxxx> --- include/libvirt/libvirt.h.in | 45 +++++ src/qemu/qemu_driver.c | 418 +++++++++++++++++++++++++++++++++++++++---- tools/virsh-domain.c | 64 +++++++ 3 files changed, 488 insertions(+), 39 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5aad75c..d054900 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1806,6 +1806,51 @@ char * virDomainGetSchedulerType(virDomainPtr domain, #define VIR_DOMAIN_BLKIO_DEVICE_WEIGHT "device_weight" + +/** + * VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS: + * + * Macro for the blkio tunable throttle.read_iops_device: it represents + * the number of reading the block device per second, as a string. The + * string is parsed as a series of /path/to/device, read_iops elements, + * separated by ','. + */ + +#define VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS "device_read_iops" + + +/** + * VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS: + * + * Macro for the blkio tunable throttle.write_iops_device: it represents + * the number of writing the block device per second, as a string. The + * string is parsed as a series of /path/to/device, write_iops elements, + * separated by ','. + */ +#define VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS "device_write_iops" + + +/** + * VIR_DOMAIN_BLKIO_DEVICE_READ_BPS: + * + * Macro for the blkio tunable throttle.read_iops_device: it represents + * the bytes of reading the block device per second, as a string. The + * string is parsed as a series of /path/to/device, read_bps elements, + * separated by ','. + */ +#define VIR_DOMAIN_BLKIO_DEVICE_READ_BPS "device_read_bps" + + +/** + * VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS: + * + * Macro for the blkio tunable throttle.read_iops_device: it represents + * the number of reading the block device per second, as a string. The + * string is parsed as a series of /path/to/device, read_iops elements, + * separated by ','. + */ +#define VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS "device_write_bps" + /* Set Blkio tunables for the domain*/ int virDomainSetBlkioParameters(virDomainPtr domain, virTypedParameterPtr params, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 61dbe7f..1ad5b94 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -131,7 +131,7 @@ # define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */ #endif -#define QEMU_NB_BLKIO_PARAM 2 +#define QEMU_NB_BLKIO_PARAM 6 #define QEMU_NB_BANDWIDTH_PARAM 6 @@ -7419,12 +7419,12 @@ cleanup: return ret; } -/* deviceWeightStr in the form of /device/path,weight,/device/path,weight +/* blkioDeviceStr in the form of /device/path,weight,/device/path,weight * for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800 */ static int -qemuDomainParseDeviceWeightStr(char *deviceWeightStr, - virBlkioDevicePtr *dev, size_t *size) +qemuDomainParseBlkioDeviceStr(char *blkioDeviceStr, const char *type, + virBlkioDevicePtr *dev, size_t *size) { char *temp; int ndevices = 0; @@ -7435,10 +7435,10 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr, *dev = NULL; *size = 0; - if (STREQ(deviceWeightStr, "")) + if (STREQ(blkioDeviceStr, "")) return 0; - temp = deviceWeightStr; + temp = blkioDeviceStr; while (temp) { temp = strchr(temp, ','); if (temp) { @@ -7458,7 +7458,7 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr, return -1; i = 0; - temp = deviceWeightStr; + temp = blkioDeviceStr; while (temp) { char *p = temp; @@ -7470,11 +7470,25 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr, if (VIR_STRNDUP(result[i].path, temp, p - temp) < 0) goto cleanup; - /* weight */ + /* value */ temp = p + 1; - if (virStrToLong_ui(temp, &p, 10, &result[i].weight) < 0) - goto error; + if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) { + if (virStrToLong_ui(temp, &p, 10, &result[i].weight) < 0) + goto error; + } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) { + if (virStrToLong_ui(temp, &p, 10, &result[i].riops) < 0) + goto error; + } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) { + if (virStrToLong_ui(temp, &p, 10, &result[i].wiops) < 0) + goto error; + } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) { + if (virStrToLong_ull(temp, &p, 10, &result[i].rbps) < 0) + goto error; + } else { + if (virStrToLong_ull(temp, &p, 10, &result[i].wbps) < 0) + goto error; + } i++; @@ -7495,20 +7509,21 @@ qemuDomainParseDeviceWeightStr(char *deviceWeightStr, error: virReportError(VIR_ERR_INVALID_ARG, - _("unable to parse device weight '%s'"), deviceWeightStr); + _("unable to parse blkio device '%s'"), blkioDeviceStr); cleanup: virBlkioDeviceArrayClear(result, ndevices); VIR_FREE(result); return -1; } -/* Modify dest_array to reflect all device weight changes described in +/* Modify dest_array to reflect all blkio device changes described in * src_array. */ static int -qemuDomainMergeDeviceWeights(virBlkioDevicePtr *dest_array, - size_t *dest_size, - virBlkioDevicePtr src_array, - size_t src_size) +qemuDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array, + size_t *dest_size, + virBlkioDevicePtr src_array, + size_t src_size, + const char *type) { size_t i, j; virBlkioDevicePtr dest, src; @@ -7521,18 +7536,40 @@ qemuDomainMergeDeviceWeights(virBlkioDevicePtr *dest_array, dest = &(*dest_array)[j]; if (STREQ(src->path, dest->path)) { found = true; - dest->weight = src->weight; + + if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) + dest->weight = src->weight; + else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) + dest->riops = src->riops; + else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) + dest->wiops = src->wiops; + else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) + dest->rbps = src->rbps; + else + dest->wbps = src->wbps; + break; } } if (!found) { - if (!src->weight) + if (!src->weight && !src->riops && src->wiops && src->rbps && src->wbps) continue; if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0) return -1; dest = &(*dest_array)[*dest_size - 1]; dest->path = src->path; - dest->weight = src->weight; + + if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) + dest->weight = src->weight; + else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) + dest->riops = src->riops; + else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) + dest->wiops = src->wiops; + else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) + dest->rbps = src->rbps; + else + dest->wbps = src->wbps; + src->path = NULL; } } @@ -7562,6 +7599,14 @@ qemuDomainSetBlkioParameters(virDomainPtr dom, VIR_TYPED_PARAM_UINT, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT, VIR_TYPED_PARAM_STRING, + VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS, + VIR_TYPED_PARAM_STRING, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS, + VIR_TYPED_PARAM_STRING, + VIR_DOMAIN_BLKIO_DEVICE_READ_BPS, + VIR_TYPED_PARAM_STRING, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS, + VIR_TYPED_PARAM_STRING, NULL) < 0) return -1; @@ -7604,33 +7649,72 @@ qemuDomainSetBlkioParameters(virDomainPtr dom, if (virCgroupSetBlkioWeight(priv->cgroup, params[i].value.ui) < 0) ret = -1; - } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) { + } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) { size_t ndevices; virBlkioDevicePtr devices = NULL; size_t j; - if (qemuDomainParseDeviceWeightStr(params[i].value.s, + if (qemuDomainParseBlkioDeviceStr(params[i].value.s, + param->field, &devices, &ndevices) < 0) { ret = -1; continue; } - for (j = 0; j < ndevices; j++) { - if (virCgroupSetBlkioDevice(priv->cgroup, - devices[j].path, - devices[j].weight, - devices[j].riops, - devices[j].wiops, - devices[j].rbps, - devices[j].wbps) < 0) { - ret = -1; - break; + if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) { + for (j = 0; j < ndevices; j++) { + if (virCgroupSetBlkioDeviceWeight(priv->cgroup, + devices[j].path, + devices[j].weight) < 0) { + ret = -1; + break; + } + } + } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) { + for (j = 0; j < ndevices; j++) { + if (virCgroupSetBlkioDeviceIops(priv->cgroup, + devices[j].path, + 1, devices[j].riops) < 0) { + ret = -1; + break; + } + } + } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) { + for (j = 0; j < ndevices; j++) { + if (virCgroupSetBlkioDeviceIops(priv->cgroup, + devices[j].path, + 0, devices[j].wiops) < 0) { + ret = -1; + break; + } + } + } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) { + for (j = 0; j < ndevices; j++) { + if (virCgroupSetBlkioDeviceBps(priv->cgroup, + devices[j].path, + 1, devices[j].rbps) < 0) { + ret = -1; + break; + } + } + } else { + for (j = 0; j < ndevices; j++) { + if (virCgroupSetBlkioDeviceBps(priv->cgroup, + devices[j].path, + 0, devices[j].wbps) < 0) { + ret = -1; + break; + } } } if (j != ndevices || - qemuDomainMergeDeviceWeights(&vm->def->blkio.devices, - &vm->def->blkio.ndevices, - devices, ndevices) < 0) + qemuDomainMergeBlkioDevice(&vm->def->blkio.devices, + &vm->def->blkio.ndevices, + devices, ndevices, param->field) < 0) ret = -1; virBlkioDeviceArrayClear(devices, ndevices); VIR_FREE(devices); @@ -7655,19 +7739,24 @@ qemuDomainSetBlkioParameters(virDomainPtr dom, } persistentDef->blkio.weight = params[i].value.ui; - } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) { + } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) || + STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) { virBlkioDevicePtr devices = NULL; size_t ndevices; - if (qemuDomainParseDeviceWeightStr(params[i].value.s, + if (qemuDomainParseBlkioDeviceStr(params[i].value.s, + params[i].field, &devices, &ndevices) < 0) { ret = -1; continue; } - if (qemuDomainMergeDeviceWeights(&persistentDef->blkio.devices, - &persistentDef->blkio.ndevices, - devices, ndevices) < 0) + if (qemuDomainMergeBlkioDevice(&persistentDef->blkio.devices, + &persistentDef->blkio.ndevices, + devices, ndevices, param->field) < 0) ret = -1; virBlkioDeviceArrayClear(devices, ndevices); VIR_FREE(devices); @@ -7753,6 +7842,7 @@ qemuDomainGetBlkioParameters(virDomainPtr dom, VIR_TYPED_PARAM_UINT, val) < 0) goto cleanup; break; + case 1: /* blkiotune.device_weight */ if (vm->def->blkio.ndevices > 0) { virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -7782,6 +7872,122 @@ qemuDomainGetBlkioParameters(virDomainPtr dom, goto cleanup; break; + case 2: /* blkiotune.device_read_iops */ + if (vm->def->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < vm->def->blkio.ndevices; j++) { + if (!vm->def->blkio.devices[j].riops) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%u", + vm->def->blkio.devices[j].path, + vm->def->blkio.devices[j].riops); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS, + VIR_TYPED_PARAM_STRING, + param->value.s) < 0) + goto cleanup; + break; + + case 3: /* blkiotune.device_write_iops */ + if (vm->def->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < vm->def->blkio.ndevices; j++) { + if (!vm->def->blkio.devices[j].wiops) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%u", + vm->def->blkio.devices[j].path, + vm->def->blkio.devices[j].wiops); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS, + VIR_TYPED_PARAM_STRING, + param->value.s) < 0) + goto cleanup; + break; + + case 4: /* blkiotune.device_read_bps */ + if (vm->def->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < vm->def->blkio.ndevices; j++) { + if (!vm->def->blkio.devices[j].rbps) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%llu", + vm->def->blkio.devices[j].path, + vm->def->blkio.devices[j].rbps); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLKIO_DEVICE_READ_BPS, + VIR_TYPED_PARAM_STRING, + param->value.s) < 0) + goto cleanup; + break; + + case 5: /* blkiotune.device_write_bps */ + if (vm->def->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < vm->def->blkio.ndevices; j++) { + if (!vm->def->blkio.devices[j].wbps) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%llu", + vm->def->blkio.devices[j].path, + vm->def->blkio.devices[j].wbps); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (virTypedParameterAssign(param, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS, + VIR_TYPED_PARAM_STRING, + param->value.s) < 0) + goto cleanup; + break; + default: break; /* should not hit here */ @@ -7839,6 +8045,140 @@ qemuDomainGetBlkioParameters(virDomainPtr dom, } break; + case 2: /* blkiotune.device_read_iops */ + if (persistentDef->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < persistentDef->blkio.ndevices; j++) { + if (!persistentDef->blkio.devices[j].riops) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%u", + persistentDef->blkio.devices[j].path, + persistentDef->blkio.devices[j].riops); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0) + goto cleanup; + param->type = VIR_TYPED_PARAM_STRING; + if (virStrcpyStatic(param->field, + VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Field name '%s' too long"), + VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS); + goto cleanup; + } + break; + case 3: /* blkiotune.device_write_iops */ + if (persistentDef->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < persistentDef->blkio.ndevices; j++) { + if (!persistentDef->blkio.devices[j].wiops) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%u", + persistentDef->blkio.devices[j].path, + persistentDef->blkio.devices[j].wiops); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0) + goto cleanup; + param->type = VIR_TYPED_PARAM_STRING; + if (virStrcpyStatic(param->field, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Field name '%s' too long"), + VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS); + goto cleanup; + } + break; + case 4: /* blkiotune.device_read_bps */ + if (persistentDef->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < persistentDef->blkio.ndevices; j++) { + if (!persistentDef->blkio.devices[j].rbps) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%llu", + persistentDef->blkio.devices[j].path, + persistentDef->blkio.devices[j].rbps); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0) + goto cleanup; + param->type = VIR_TYPED_PARAM_STRING; + if (virStrcpyStatic(param->field, + VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Field name '%s' too long"), + VIR_DOMAIN_BLKIO_DEVICE_READ_BPS); + goto cleanup; + } + break; + + case 5: /* blkiotune.device_write_bps */ + if (persistentDef->blkio.ndevices > 0) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool comma = false; + + for (j = 0; j < persistentDef->blkio.ndevices; j++) { + if (!persistentDef->blkio.devices[j].wbps) + continue; + if (comma) + virBufferAddChar(&buf, ','); + else + comma = true; + virBufferAsprintf(&buf, "%s,%llu", + persistentDef->blkio.devices[j].path, + persistentDef->blkio.devices[j].wbps); + } + if (virBufferError(&buf)) { + virReportOOMError(); + goto cleanup; + } + param->value.s = virBufferContentAndReset(&buf); + } + if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0) + goto cleanup; + param->type = VIR_TYPED_PARAM_STRING; + if (virStrcpyStatic(param->field, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Field name '%s' too long"), + VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS); + goto cleanup; + } + break; + default: break; /* should not hit here */ diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1fe138c..f01691d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -1250,6 +1250,22 @@ static const vshCmdOptDef opts_blkiotune[] = { .type = VSH_OT_STRING, .help = N_("per-device IO Weights, in the form of /path/to/device,weight,...") }, + {.name = "device-read-iops", + .type = VSH_OT_STRING, + .help = N_("per-device read I/O limit per second, in the form of /path/to/device,read_iops,...") + }, + {.name = "device-write-iops", + .type = VSH_OT_STRING, + .help = N_("per-device write I/O limit per second, in the form of /path/to/device,write_iops,...") + }, + {.name = "device-read-bps", + .type = VSH_OT_STRING, + .help = N_("per-device bytes read per second, in the form of /path/to/device,read-bps,...") + }, + {.name = "device-write-bps", + .type = VSH_OT_STRING, + .help = N_("per-device bytes wrote per second, in the form of /path/to/device,write-bps,...") + }, {.name = "config", .type = VSH_OT_BOOL, .help = N_("affect next boot") @@ -1270,6 +1286,10 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) { virDomainPtr dom; const char *device_weight = NULL; + const char *device_riops = NULL; + const char *device_wiops = NULL; + const char *device_rbps = NULL; + const char *device_wbps = NULL; int weight = 0; int nparams = 0; int maxparams = 0; @@ -1317,6 +1337,50 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) goto save_error; } + rv = vshCommandOptString(cmd, "device-read-iops", &device_riops); + if (rv < 0) { + vshError(ctl, "%s", _("Unable to parse string parameter")); + goto cleanup; + } else if (rv > 0) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS, + device_riops) < 0) + goto save_error; + } + + rv = vshCommandOptString(cmd, "device-write-iops", &device_wiops); + if (rv < 0) { + vshError(ctl, "%s", _("Unable to parse string parameter")); + goto cleanup; + } else if (rv > 0) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS, + device_wiops) < 0) + goto save_error; + } + + rv = vshCommandOptString(cmd, "device-read-bps", &device_rbps); + if (rv < 0) { + vshError(ctl, "%s", _("Unable to parse string parameter")); + goto cleanup; + } else if (rv > 0) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLKIO_DEVICE_READ_BPS, + device_rbps) < 0) + goto save_error; + } + + rv = vshCommandOptString(cmd, "device-write-bps", &device_wbps); + if (rv < 0) { + vshError(ctl, "%s", _("Unable to parse string parameter")); + goto cleanup; + } else if (rv > 0) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS, + device_wbps) < 0) + goto save_error; + } + if (nparams == 0) { /* get the number of blkio parameters */ if (virDomainGetBlkioParameters(dom, NULL, &nparams, flags) != 0) { -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list