Prior to this patch, for a running dom, the commands:
$ virsh blkiotune dom --device-weights /dev/sda,502,/dev/sdb,498
$ virsh blkiotune dom --device-weights /dev/sda,503
$ virsh blkiotune dom
weight : 500
device_weight : /dev/sda,503
claim that /dev/sdb no longer has a non-default weight, but
directly querying cgroups says otherwise:
$ cat /cgroup/blkio/libvirt/qemu/dom/blkio.weight_device
8:0 503
8:16 498
After this patch, an explicit 0 is required to remove a device path
from the XML, and omitting a device path that was previously
specified leaves that device path untouched in the XML, to match
cgroups behavior.
* src/qemu/qemu_driver.c (parseBlkioWeightDeviceStr): Rename...
(qemuDomainParseDeviceWeightStr): ...and use correct type.
(qemuDomainSetBlkioParameters): After parsing string, modify
rather than replacing existing table.
* tools/virsh.pod (blkiotune): Tweak wording.
---
src/qemu/qemu_driver.c | 80 +++++++++++++++++++++++++++++++++++------------
tools/virsh.pod | 4 ++-
2 files changed, 62 insertions(+), 22 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 105bdde..81d11c2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5887,8 +5887,8 @@ cleanup:
* for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
*/
static int
-parseBlkioWeightDeviceStr(char *deviceWeightStr,
- virBlkioDeviceWeightPtr *dw, int *size)
+qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
+ virBlkioDeviceWeightPtr *dw, size_t *size)
{
char *temp;
int ndevices = 0;
@@ -5965,6 +5965,41 @@ cleanup:
return -1;
}
+/* Modify def to reflect all device weight changes described in tmp. */
+static int
+qemuDomainMergeDeviceWeights(virBlkioDeviceWeightPtr *def, size_t *def_size,
+ virBlkioDeviceWeightPtr tmp, size_t tmp_size)
+{
+ int i, j;
+ virBlkioDeviceWeightPtr dw;
+
+ for (i = 0; i < tmp_size; i++) {
+ bool found = false;
+
+ dw = &tmp[i];
+ for (j = 0; j < *def_size; j++) {
+ if (STREQ(dw->path, (*def)[j].path)) {
+ found = true;
+ (*def)[j].weight = dw->weight;
+ break;
+ }
+ }
+ if (!found) {
+ if (!dw->weight)
+ continue;
+ if (VIR_EXPAND_N(*def, *def_size, 1) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ (*def)[*def_size - 1].path = dw->path;
+ (*def)[*def_size - 1].weight = dw->weight;
+ dw->path = NULL;
+ }
+ }
+
+ return 0;
+}
+
static int qemuDomainSetBlkioParameters(virDomainPtr dom,
virTypedParameterPtr params,
int nparams,
@@ -6056,7 +6091,7 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
ret = -1;
}
} else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
- int ndevices;
+ size_t ndevices;
virBlkioDeviceWeightPtr devices = NULL;
if (param->type != VIR_TYPED_PARAM_STRING) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -6066,9 +6101,9 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
continue;
}
- if (parseBlkioWeightDeviceStr(params[i].value.s,
- &devices,
- &ndevices) < 0) {
+ if (qemuDomainParseDeviceWeightStr(params[i].value.s,
+ &devices,
+ &ndevices) < 0) {
ret = -1;
continue;
}
@@ -6088,14 +6123,16 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
ret = -1;
continue;
}
- virBlkioDeviceWeightArrayClear(vm->def->blkio.devices,
- vm->def->blkio.ndevices);
- VIR_FREE(vm->def->blkio.devices);
- vm->def->blkio.devices = devices;
- vm->def->blkio.ndevices = ndevices;
+ if (qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
+ &vm->def->blkio.ndevices,
+ devices, ndevices) < 0)
+ ret = -1;
+ virBlkioDeviceWeightArrayClear(devices, ndevices);
+ VIR_FREE(devices);
} else {
qemuReportError(VIR_ERR_INVALID_ARG,
- _("Parameter `%s' not supported"),
param->field);
+ _("Parameter `%s' not supported"),
+ param->field);
ret = -1;
}
}
@@ -6127,7 +6164,7 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
persistentDef->blkio.weight = params[i].value.ui;
} else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
virBlkioDeviceWeightPtr devices = NULL;
- int ndevices;
+ size_t ndevices;
if (param->type != VIR_TYPED_PARAM_STRING) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
_("invalid type for device_weight tunable,
"
@@ -6135,17 +6172,18 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
ret = -1;
continue;
}
- if (parseBlkioWeightDeviceStr(params[i].value.s,
- &devices,
- &ndevices) < 0) {
+ if (qemuDomainParseDeviceWeightStr(params[i].value.s,
+ &devices,
+ &ndevices) < 0) {
ret = -1;
continue;
}
- virBlkioDeviceWeightArrayClear(persistentDef->blkio.devices,
- persistentDef->blkio.ndevices);
- VIR_FREE(persistentDef->blkio.devices);
- persistentDef->blkio.devices = devices;
- persistentDef->blkio.ndevices = ndevices;
+ if (qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
+ &vm->def->blkio.ndevices,
+ devices, ndevices) < 0)
+ ret = -1;
+ virBlkioDeviceWeightArrayClear(devices, ndevices);
+ VIR_FREE(devices);
} else {
qemuReportError(VIR_ERR_INVALID_ARG,
_("Parameter `%s' not supported"),
diff --git a/tools/virsh.pod b/tools/virsh.pod
index d606f99..01b8538 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1055,7 +1055,9 @@ I<--weight> is in range [100, 1000].
B<device-weights> is a single string listing one or more device/weight
pairs, in the format of /path/to/device,weight,/path/to/device,weight.
Each weight is in the range [100, 1000], or the value 0 to remove that
-device from per-device listings.
+device from per-device listings. Only the devices listed in the string
+are modified; any existing per-device weights for other devices remain
+unchanged.
If I<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
--
1.7.7.3