qemu: amend existing table of device weights

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.
This commit is contained in:
Eric Blake 2011-11-29 14:00:17 -07:00
parent 9b524ff040
commit 22cf6d46f4
2 changed files with 62 additions and 22 deletions

View File

@ -5890,8 +5890,8 @@ cleanup:
* for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800 * for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
*/ */
static int static int
parseBlkioWeightDeviceStr(char *deviceWeightStr, qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
virBlkioDeviceWeightPtr *dw, int *size) virBlkioDeviceWeightPtr *dw, size_t *size)
{ {
char *temp; char *temp;
int ndevices = 0; int ndevices = 0;
@ -5968,6 +5968,41 @@ cleanup:
return -1; 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, static int qemuDomainSetBlkioParameters(virDomainPtr dom,
virTypedParameterPtr params, virTypedParameterPtr params,
int nparams, int nparams,
@ -6059,7 +6094,7 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
ret = -1; ret = -1;
} }
} else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) { } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
int ndevices; size_t ndevices;
virBlkioDeviceWeightPtr devices = NULL; virBlkioDeviceWeightPtr devices = NULL;
if (param->type != VIR_TYPED_PARAM_STRING) { if (param->type != VIR_TYPED_PARAM_STRING) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s", qemuReportError(VIR_ERR_INVALID_ARG, "%s",
@ -6069,9 +6104,9 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
continue; continue;
} }
if (parseBlkioWeightDeviceStr(params[i].value.s, if (qemuDomainParseDeviceWeightStr(params[i].value.s,
&devices, &devices,
&ndevices) < 0) { &ndevices) < 0) {
ret = -1; ret = -1;
continue; continue;
} }
@ -6091,14 +6126,16 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
ret = -1; ret = -1;
continue; continue;
} }
virBlkioDeviceWeightArrayClear(vm->def->blkio.devices, if (qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
vm->def->blkio.ndevices); &vm->def->blkio.ndevices,
VIR_FREE(vm->def->blkio.devices); devices, ndevices) < 0)
vm->def->blkio.devices = devices; ret = -1;
vm->def->blkio.ndevices = ndevices; virBlkioDeviceWeightArrayClear(devices, ndevices);
VIR_FREE(devices);
} else { } else {
qemuReportError(VIR_ERR_INVALID_ARG, qemuReportError(VIR_ERR_INVALID_ARG,
_("Parameter `%s' not supported"), param->field); _("Parameter `%s' not supported"),
param->field);
ret = -1; ret = -1;
} }
} }
@ -6130,7 +6167,7 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
persistentDef->blkio.weight = params[i].value.ui; 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)) {
virBlkioDeviceWeightPtr devices = NULL; virBlkioDeviceWeightPtr devices = NULL;
int ndevices; size_t ndevices;
if (param->type != VIR_TYPED_PARAM_STRING) { if (param->type != VIR_TYPED_PARAM_STRING) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s", qemuReportError(VIR_ERR_INVALID_ARG, "%s",
_("invalid type for device_weight tunable, " _("invalid type for device_weight tunable, "
@ -6138,17 +6175,18 @@ static int qemuDomainSetBlkioParameters(virDomainPtr dom,
ret = -1; ret = -1;
continue; continue;
} }
if (parseBlkioWeightDeviceStr(params[i].value.s, if (qemuDomainParseDeviceWeightStr(params[i].value.s,
&devices, &devices,
&ndevices) < 0) { &ndevices) < 0) {
ret = -1; ret = -1;
continue; continue;
} }
virBlkioDeviceWeightArrayClear(persistentDef->blkio.devices, if (qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
persistentDef->blkio.ndevices); &vm->def->blkio.ndevices,
VIR_FREE(persistentDef->blkio.devices); devices, ndevices) < 0)
persistentDef->blkio.devices = devices; ret = -1;
persistentDef->blkio.ndevices = ndevices; virBlkioDeviceWeightArrayClear(devices, ndevices);
VIR_FREE(devices);
} else { } else {
qemuReportError(VIR_ERR_INVALID_ARG, qemuReportError(VIR_ERR_INVALID_ARG,
_("Parameter `%s' not supported"), _("Parameter `%s' not supported"),

View File

@ -1085,7 +1085,9 @@ I<--weight> is in range [100, 1000].
B<device-weights> is a single string listing one or more device/weight 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. 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 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<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest. If I<--config> is specified, affect the next boot of a persistent guest.