]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: amend existing table of device weights
authorEric Blake <eblake@redhat.com>
Tue, 29 Nov 2011 21:00:17 +0000 (14:00 -0700)
committerEric Blake <eblake@redhat.com>
Wed, 30 Nov 2011 19:18:18 +0000 (12:18 -0700)
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
tools/virsh.pod

index 75c4aa8942558138496e29b331cd9bc7a8b30a1a..39bd1bc87a24e325fad7e20fbb2c823d54284543 100644 (file)
@@ -5890,8 +5890,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;
@@ -5968,6 +5968,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,
@@ -6059,7 +6094,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",
@@ -6069,9 +6104,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;
                 }
@@ -6091,14 +6126,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;
             }
         }
@@ -6130,7 +6167,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, "
@@ -6138,17 +6175,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"),
index b681db55db6e80b5b44543ac9ca372fe97f003fc..5131ade4b6b5ab4a47191b430683c825b00afba4 100644 (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
 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.