With this patch,user can set throttle blkio cgroup for
lxc domain through virsh tool.
The functions are copied from qemu_driver.
Signed-off-by: Guan Qiang <hzguanqiang(a)corp.netease.com>
Signed-off-by: Gao feng <gaofeng(a)cn.fujitsu.com>
---
src/lxc/lxc_driver.c | 649 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 624 insertions(+), 25 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index c499182..1f73b52 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1545,6 +1545,20 @@ static int lxcStateCleanup(void)
return 0;
}
+static int
+lxcConnectSupportsFeature(virConnectPtr conn, int feature)
+{
+ if (virConnectSupportsFeatureEnsureACL(conn) < 0)
+ return -1;
+
+ switch (feature) {
+ case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static int lxcConnectGetVersion(virConnectPtr conn, unsigned long *version)
{
@@ -1910,6 +1924,159 @@ lxcDomainGetSchedulerParameters(virDomainPtr domain,
return lxcDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
}
+static int
+lxcDomainParseBlkioDeviceStr(char *blkioDeviceStr, const char *type,
+ virBlkioDevicePtr *dev, size_t *size)
+{
+ char *temp;
+ int ndevices = 0;
+ int nsep = 0;
+ size_t i;
+ virBlkioDevicePtr result = NULL;
+
+ *dev = NULL;
+ *size = 0;
+
+ if (STREQ(blkioDeviceStr, ""))
+ return 0;
+
+ temp = blkioDeviceStr;
+ while (temp) {
+ temp = strchr(temp, ',');
+ if (temp) {
+ temp++;
+ nsep++;
+ }
+ }
+
+ /* A valid string must have even number of fields, hence an odd
+ * number of commas. */
+ if (!(nsep & 1))
+ goto error;
+
+ ndevices = (nsep + 1) / 2;
+
+ if (VIR_ALLOC_N(result, ndevices) < 0)
+ return -1;
+
+ i = 0;
+ temp = blkioDeviceStr;
+ while (temp) {
+ char *p = temp;
+
+ /* device path */
+ p = strchr(p, ',');
+ if (!p)
+ goto error;
+
+ if (VIR_STRNDUP(result[i].path, temp, p - temp) < 0)
+ goto cleanup;
+
+ /* value */
+ temp = p + 1;
+
+ 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++;
+
+ if (*p == '\0')
+ break;
+ else if (*p != ',')
+ goto error;
+ temp = p + 1;
+ }
+
+ if (!i)
+ VIR_FREE(result);
+
+ *dev = result;
+ *size = i;
+
+ return 0;
+
+error:
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unable to parse device weight '%s'"),
blkioDeviceStr);
+cleanup:
+ virBlkioDeviceArrayClear(result, ndevices);
+ VIR_FREE(result);
+ return -1;
+}
+
+static int
+lxcDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
+ size_t *dest_size,
+ virBlkioDevicePtr src_array,
+ size_t src_size,
+ const char *type)
+{
+ size_t i, j;
+ virBlkioDevicePtr dest, src;
+
+ for (i = 0; i < src_size; i++) {
+ bool found = false;
+
+ src = &src_array[i];
+ for (j = 0; j < *dest_size; j++) {
+ dest = &(*dest_array)[j];
+ if (STREQ(src->path, dest->path)) {
+ found = true;
+
+ 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 && !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;
+
+ 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;
+ }
+ }
+
+ return 0;
+}
+
static int
lxcDomainSetBlkioParameters(virDomainPtr dom,
@@ -1918,26 +2085,37 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
unsigned int flags)
{
virLXCDriverPtr driver = dom->conn->privateData;
- virCapsPtr caps = NULL;
size_t i;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
int ret = -1;
+ virLXCDriverConfigPtr cfg = NULL;
+ virCapsPtr caps = NULL;
virLXCDomainObjPrivatePtr priv;
- virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
if (virTypedParamsValidate(params, nparams,
VIR_DOMAIN_BLKIO_WEIGHT,
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;
if (!(vm = lxcDomObjFromDomain(dom)))
- goto cleanup;
+ return -1;
priv = vm->privateData;
+ cfg = virLXCDriverGetConfig(driver);
if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
@@ -1945,8 +2123,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
if (!(caps = virLXCDriverGetCapabilities(driver, false)))
goto cleanup;
- if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
- vm, &flags, &persistentDef) < 0)
+ if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
+ &persistentDef) < 0)
goto cleanup;
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
@@ -1955,7 +2133,10 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
_("blkio cgroup isn't mounted"));
goto cleanup;
}
+ }
+ ret = 0;
+ if (flags & VIR_DOMAIN_AFFECT_LIVE) {
for (i = 0; i < nparams; i++) {
virTypedParameterPtr param = ¶ms[i];
@@ -1963,14 +2144,86 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("out of blkio weight range."));
- goto cleanup;
+ ret = -1;
+ continue;
}
if (virCgroupSetBlkioWeight(priv->cgroup, params[i].value.ui) < 0)
- goto cleanup;
+ ret = -1;
+ } 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 (lxcDomainParseBlkioDeviceStr(params[i].value.s,
+ param->field,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ continue;
+ }
+ 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 (virCgroupSetBlkioDeviceReadIops(priv->cgroup,
+ devices[j].path,
+ 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 (virCgroupSetBlkioDeviceWriteIops(priv->cgroup,
+ devices[j].path,
+ 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 (virCgroupSetBlkioDeviceReadBps(priv->cgroup,
+ devices[j].path,
+ devices[j].rbps) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+ } else {
+ for (j = 0; j < ndevices; j++) {
+ if (virCgroupSetBlkioDeviceWriteBps(priv->cgroup,
+ devices[j].path,
+ devices[j].wbps) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+ }
+ if (j != ndevices ||
+ lxcDomainMergeBlkioDevice(&vm->def->blkio.devices,
+ &vm->def->blkio.ndevices,
+ devices, ndevices, param->field) <
0)
+ ret = -1;
+ virBlkioDeviceArrayClear(devices, ndevices);
+ VIR_FREE(devices);
}
}
}
+ if (ret < 0)
+ goto cleanup;
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
/* Clang can't see that if we get here, persistentDef was set. */
sa_assert(persistentDef);
@@ -1982,18 +2235,39 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("out of blkio weight range."));
- goto cleanup;
+ ret = -1;
+ continue;
}
persistentDef->blkio.weight = params[i].value.ui;
+ } 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 (lxcDomainParseBlkioDeviceStr(params[i].value.s,
+ params[i].field,
+ &devices,
+ &ndevices) < 0) {
+ ret = -1;
+ continue;
+ }
+ if (lxcDomainMergeBlkioDevice(&persistentDef->blkio.devices,
+ &persistentDef->blkio.ndevices,
+ devices, ndevices, param->field) <
0)
+ ret = -1;
+ virBlkioDeviceArrayClear(devices, ndevices);
+ VIR_FREE(devices);
}
}
if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
- goto cleanup;
+ ret = -1;
}
- ret = 0;
cleanup:
if (vm)
virObjectUnlock(vm);
@@ -2003,7 +2277,8 @@ cleanup:
}
-#define LXC_NB_BLKIO_PARAM 1
+#define LXC_NB_BLKIO_PARAM 6
+
static int
lxcDomainGetBlkioParameters(virDomainPtr dom,
virTypedParameterPtr params,
@@ -2011,25 +2286,34 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
unsigned int flags)
{
virLXCDriverPtr driver = dom->conn->privateData;
- virCapsPtr caps = NULL;
- size_t i;
+ size_t i, j;
virDomainObjPtr vm = NULL;
virDomainDefPtr persistentDef = NULL;
unsigned int val;
int ret = -1;
+ virCapsPtr caps = NULL;
virLXCDomainObjPrivatePtr priv;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
- VIR_DOMAIN_AFFECT_CONFIG, -1);
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ /* We blindly return a string, and let libvirt.c and
+ * remote_driver.c do the filtering on behalf of older clients
+ * that can't parse it. */
+ flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
if (!(vm = lxcDomObjFromDomain(dom)))
- goto cleanup;
+ return -1;
priv = vm->privateData;
if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
+ if (!(caps = virLXCDriverGetCapabilities(driver, false)))
+ goto cleanup;
+
if ((*nparams) == 0) {
/* Current number of blkio parameters supported by cgroups */
*nparams = LXC_NB_BLKIO_PARAM;
@@ -2037,11 +2321,8 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
goto cleanup;
}
- if (!(caps = virLXCDriverGetCapabilities(driver, false)))
- goto cleanup;
-
- if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
- vm, &flags, &persistentDef) < 0)
+ if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
+ &persistentDef) < 0)
goto cleanup;
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
@@ -2064,7 +2345,151 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
goto cleanup;
break;
- /* coverity[dead_error_begin] */
+ case 1: /* blkiotune.device_weight */
+ 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].weight)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%u",
+ vm->def->blkio.devices[j].path,
+ vm->def->blkio.devices[j].weight);
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ param->value.s = virBufferContentAndReset(&buf);
+ }
+ if (virTypedParameterAssign(param,
+ VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
+ VIR_TYPED_PARAM_STRING,
+ param->value.s) < 0)
+ 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 */
@@ -2073,16 +2498,189 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
} else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
virTypedParameterPtr param = ¶ms[i];
+ val = 0;
+ param->value.ui = 0;
+ param->type = VIR_TYPED_PARAM_UINT;
switch (i) {
case 0: /* fill blkio weight here */
- if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
- VIR_TYPED_PARAM_UINT,
- persistentDef->blkio.weight) < 0)
+ if (virStrcpyStatic(param->field, VIR_DOMAIN_BLKIO_WEIGHT) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLKIO_WEIGHT);
+ goto cleanup;
+ }
+ param->value.ui = persistentDef->blkio.weight;
+ break;
+
+ case 1: /* blkiotune.device_weight */
+ 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].weight)
+ continue;
+ if (comma)
+ virBufferAddChar(&buf, ',');
+ else
+ comma = true;
+ virBufferAsprintf(&buf, "%s,%u",
+ persistentDef->blkio.devices[j].path,
+ persistentDef->blkio.devices[j].weight);
+ }
+ 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_WEIGHT) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%s' too long"),
+ VIR_DOMAIN_BLKIO_DEVICE_WEIGHT);
+ goto cleanup;
+ }
+ 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;
- /* coverity[dead_error_begin] */
default:
break;
/* should not hit here */
@@ -4623,6 +5221,7 @@ static virDriver lxcDriver = {
.name = LXC_DRIVER_NAME,
.connectOpen = lxcConnectOpen, /* 0.4.2 */
.connectClose = lxcConnectClose, /* 0.4.2 */
+ .connectSupportsFeature = lxcConnectSupportsFeature, /* 1.1.4 */
.connectGetVersion = lxcConnectGetVersion, /* 0.4.6 */
.connectGetHostname = lxcConnectGetHostname, /* 0.6.3 */
.connectGetSysinfo = lxcConnectGetSysinfo, /* 1.0.5 */
--
1.8.3.1