
On 2011年12月29日 15:33, Hu Tao wrote:
* src/qemu/qemu_driver.c: implement the qemu driver support --- src/qemu/qemu_driver.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 353 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a840c1f..c04a5de 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -119,6 +119,8 @@
#define QEMU_NB_BLKIO_PARAM 2
+#define QEMU_NB_BANDWIDTH_PARAM 6 + static void processWatchdogEvent(void *data, void *opaque);
static int qemudShutdown(void); @@ -7852,6 +7854,355 @@ qemudDomainInterfaceStats (virDomainPtr dom, #endif
static int +qemuDomainSetInterfaceParameters(virDomainPtr dom, + const char *device, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + int i; + virCgroupPtr group = NULL; + virDomainObjPtr vm = NULL; + virDomainDefPtr persistentDef = NULL; + int ret = -1; + virDomainNetDefPtr net = NULL, persistentNet = NULL; + virNetDevBandwidthPtr bandwidth; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + qemuDriverLock(driver); + + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (vm == NULL) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), dom->uuid); + goto cleanup; + } + + if (virDomainLiveConfigHelperMethod(driver->caps, vm,&flags, +&persistentDef)< 0) + goto cleanup; + + if (flags& VIR_DOMAIN_AFFECT_LIVE) { + net = virDomainNetFind(vm->def, device); + if (!net) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Can't find device %s"), device); + goto cleanup;
This can cause libvirtd to crash, as "bandwidth" is not initialized yet.
+ } + } + if (flags& VIR_DOMAIN_AFFECT_CONFIG) { + persistentNet = virDomainNetFind(persistentDef, device); + if (!persistentNet) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Can't find device %s"), device); + ret = -1; + goto cleanup;
Likewise
+ } + } + + if (VIR_ALLOC(bandwidth)< 0) { + virReportOOMError(); + goto cleanup; + } + if (VIR_ALLOC(bandwidth->in)< 0) { + virReportOOMError(); + goto cleanup; + } + memset(bandwidth->in, 0, sizeof(*bandwidth->in)); + if (VIR_ALLOC(bandwidth->out)< 0) { + virReportOOMError(); + goto cleanup; + } + memset(bandwidth->out, 0, sizeof(*bandwidth->out)); + + for (i = 0; i< nparams; i++) { + virTypedParameterPtr param =¶ms[i]; + + if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE)) { + if (param->type != VIR_TYPED_PARAM_UINT) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for bandwidth average tunable, expected a 'unsigned int'")); + goto cleanup; + } + + bandwidth->in->average = params[i].value.ui; + } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_PEAK)) { + if (param->type != VIR_TYPED_PARAM_UINT) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for bandwidth peak tunable, expected a 'unsigned int'")); + goto cleanup; + } + + bandwidth->in->peak = params[i].value.ui; + } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_BURST)) { + if (param->type != VIR_TYPED_PARAM_UINT) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for bandwidth burst tunable, expected a 'unsigned int'")); + goto cleanup; + } + + bandwidth->in->burst = params[i].value.ui; + } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE)) { + if (param->type != VIR_TYPED_PARAM_UINT) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for bandwidth average tunable, expected a 'unsigned int'")); + goto cleanup; + } + + bandwidth->out->average = params[i].value.ui; + } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK)) { + if (param->type != VIR_TYPED_PARAM_UINT) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for bandwidth peak tunable, expected a 'unsigned int'")); + goto cleanup; + } + + bandwidth->out->peak = params[i].value.ui; + } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_BURST)) { + if (param->type != VIR_TYPED_PARAM_UINT) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for bandwidth burst tunable, expected a 'unsigned int'")); + goto cleanup; + } + + bandwidth->out->burst = params[i].value.ui; + } else { + qemuReportError(VIR_ERR_INVALID_ARG, + _("Parameter `%s' not supported"), + param->field); + goto cleanup; + } + } + + /* average is mandatory, peak and burst is optional. So if no + * average is given, we free inbound/outbound here which causes + * inbound/outbound won't be set. */ + if (!bandwidth->in->average) + VIR_FREE(bandwidth->in); + if (!bandwidth->out->average) + VIR_FREE(bandwidth->out); + + if (flags& VIR_DOMAIN_AFFECT_LIVE) { + virNetDevBandwidthPtr newBandwidth; + + if (VIR_ALLOC(newBandwidth)< 0) { + virReportOOMError(); + goto cleanup; + } + + memset(newBandwidth, 0, sizeof(newBandwidth)); + + /* virNetDevBandwidthSet() will clear any previous value of + * bandwidth parameters, so merge with old bandwidth parameters + * here to prevent them from losing. */ + if (bandwidth->in || net->bandwidth->in) {
Similiar, as bandwidth->in can be free()ed if no "average" is given.
+ if (VIR_ALLOC(newBandwidth->in)< 0) { + virReportOOMError(); + goto cleanup; + } + if (bandwidth->in) + memcpy(newBandwidth->in, bandwidth->in, sizeof(*newBandwidth->in)); + else if (net->bandwidth->in) + memcpy(newBandwidth->in, net->bandwidth->in, sizeof(*newBandwidth->in)); + } + if (bandwidth->out || net->bandwidth->out) {
Just like bandwidth->in.
+ if (VIR_ALLOC(newBandwidth->out)< 0) { + virReportOOMError(); + goto cleanup; + } + if (bandwidth->out) + memcpy(newBandwidth->out, bandwidth->out, sizeof(*newBandwidth->out)); + else if (net->bandwidth->out) + memcpy(newBandwidth->out, net->bandwidth->out, sizeof(*newBandwidth->out)); + } + + if (virNetDevBandwidthSet(net->ifname, newBandwidth)< 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot set bandwidth limits on %s"), + device); + ret = -1; + goto cleanup; + } + + virNetDevBandwidthFree(net->bandwidth); + net->bandwidth = newBandwidth; + } + if (flags& VIR_DOMAIN_AFFECT_CONFIG) { + if (!persistentNet->bandwidth) { + persistentNet->bandwidth = bandwidth; + bandwidth = NULL; + } else { + if (bandwidth->in) { + VIR_FREE(persistentNet->bandwidth->in); + persistentNet->bandwidth->in = bandwidth->in; + bandwidth->in = NULL; + } + if (bandwidth->out) { + VIR_FREE(persistentNet->bandwidth->out); + persistentNet->bandwidth->out = bandwidth->out; + bandwidth->out = NULL; + } + } + + if (virDomainSaveConfig(driver->configDir, persistentDef)< 0) + goto cleanup; + } + + ret = 0; +cleanup: + if (bandwidth) { + VIR_FREE(bandwidth->in); + VIR_FREE(bandwidth->out); + VIR_FREE(bandwidth); + }
This can be simplified using virNetDevBandwidthFree. Will push with attached patch squashed in.