[libvirt] [PATCHv4 5/6] Implement virDomain{G, S}etNumaParameters for the qemu driver
Hu Tao
hutao at cn.fujitsu.com
Tue Dec 20 06:48:53 UTC 2011
On Mon, Dec 19, 2011 at 05:42:02PM -0700, Eric Blake wrote:
> From: Hu Tao <hutao at cn.fujitsu.com>
>
> ---
> src/qemu/qemu_driver.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 262 insertions(+), 0 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 660d771..3f8167f 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -97,6 +97,8 @@
>
> #define QEMU_NB_BLOCK_IO_TUNE_PARAM 6
>
> +#define QEMU_NB_NUMA_PARAM 2
> +
> #if HAVE_LINUX_KVM_H
> # include <linux/kvm.h>
> #endif
> @@ -6602,6 +6604,264 @@ cleanup:
> }
>
> static int
> +qemuDomainSetNumaParameters(virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams,
> + unsigned int flags)
> +{
> + struct qemud_driver *driver = dom->conn->privateData;
> + int i;
> + virDomainDefPtr persistentDef = NULL;
> + virCgroupPtr group = NULL;
> + virDomainObjPtr vm = NULL;
> + int ret = -1;
> +
> + 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) {
> + if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID,
> + "%s", _("cgroup cpuset controller is not mounted"));
> + goto cleanup;
> + }
> +
> + if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
> + qemuReportError(VIR_ERR_INTERNAL_ERROR,
> + _("cannot find cgroup for domain %s"),
> + vm->def->name);
> + goto cleanup;
> + }
> + }
> +
> + ret = 0;
> + for (i = 0; i < nparams; i++) {
> + virTypedParameterPtr param = ¶ms[i];
> +
> + if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
> + if (param->type != VIR_TYPED_PARAM_INT) {
> + qemuReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("invalid type for numa strict tunable, "
> + "expected an 'int'"));
> + ret = -1;
> + continue;
> + }
> +
> + if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("can't change numa mode for running domain"));
> + ret = -1;
> + goto cleanup;
> + }
> +
> + if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> + persistentDef->numatune.memory.mode = params[i].value.i;
> + }
> + } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
> + int rc;
> + if (param->type != VIR_TYPED_PARAM_STRING) {
> + qemuReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("invalid type for numa nodeset tunable, "
> + "expected a 'string'"));
> + ret = -1;
> + continue;
> + }
> +
> + if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> + if (vm->def->numatune.memory.mode !=
> + VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("change of nodeset for running domain "
> + "requires strict numa mode"));
> + ret = -1;
> + continue;
> + }
> + rc = virCgroupSetCpusetMems(group, params[i].value.s);
> + if (rc != 0) {
> + virReportSystemError(-rc, "%s",
> + _("unable to set numa tunable"));
> + ret = -1;
> + continue;
> + }
> + /* XXX FIXME - should we also be updating vm->def
> + * here? If not, then we need to fix dumpxml to always
> + * read from cgroups rather than trusting vm->def. */
> + }
> +
> + if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> + char oldnodemask[VIR_CPU_MAPLEN(VIR_DOMAIN_CPUMASK_LEN)];
should be
char oldnodemask[VIR_DOMAIN_CPUMASK_LEN];
> + memcpy(oldnodemask, persistentDef->numatune.memory.nodemask,
> + VIR_DOMAIN_CPUMASK_LEN);
> + if (virDomainCpuSetParse(params[i].value.s,
> + 0,
> + persistentDef->numatune.memory.nodemask,
> + VIR_DOMAIN_CPUMASK_LEN) < 0) {
> + memcpy(persistentDef->numatune.memory.nodemask,
> + oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
> + ret = -1;
> + continue;
> + }
> + }
> + } else {
> + qemuReportError(VIR_ERR_INVALID_ARG,
> + _("Parameter `%s' not supported"), param->field);
> + ret = -1;
> + }
> + }
> +
> + if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> + if (virDomainSaveConfig(driver->configDir, persistentDef) < 0)
> + ret = -1;
> + }
> +
> +cleanup:
> + virCgroupFree(&group);
> + if (vm)
> + virDomainObjUnlock(vm);
> + qemuDriverUnlock(driver);
> + return ret;
> +}
> +
> +static int
> +qemuDomainGetNumaParameters(virDomainPtr dom,
> + 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;
> + char *nodeset = NULL;
> + int ret = -1;
> + int rc;
> +
> + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
> + VIR_DOMAIN_AFFECT_CONFIG |
> + VIR_TYPED_PARAM_STRING_OKAY, -1);
> +
> + qemuDriverLock(driver);
> +
> + /* 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;
> +
> + 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 ((*nparams) == 0) {
> + *nparams = QEMU_NB_NUMA_PARAM;
> + ret = 0;
> + goto cleanup;
> + }
> +
> + if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> + if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID,
> + "%s", _("cgroup memory controller is not mounted"));
> + goto cleanup;
> + }
> +
> + if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
> + qemuReportError(VIR_ERR_INTERNAL_ERROR,
> + _("cannot find cgroup for domain %s"),
> + vm->def->name);
> + goto cleanup;
> + }
> + }
> +
> + for (i = 0; i < QEMU_NB_NUMA_PARAM && i < *nparams; i++) {
> + virMemoryParameterPtr param = ¶ms[i];
> +
> + switch (i) {
> + case 0: /* fill numa mode here */
> + if (!virStrcpyStatic(param->field, VIR_DOMAIN_NUMA_MODE)) {
> + qemuReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Field '%s' too long for destination"),
> + VIR_DOMAIN_NUMA_MODE);
> + goto cleanup;
> + }
> + param->type = VIR_TYPED_PARAM_INT;
> + if (flags & VIR_DOMAIN_AFFECT_CONFIG)
> + param->value.i = persistentDef->numatune.memory.mode;
> + else
> + param->value.i = vm->def->numatune.memory.mode;
> + break;
> +
> + case 1: /* fill numa nodeset here */
> + if (!virStrcpyStatic(param->field, VIR_DOMAIN_NUMA_NODESET)) {
> + qemuReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Field '%s' too long for destination"),
> + VIR_DOMAIN_NUMA_NODESET);
> + goto cleanup;
> + }
> + if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> + char *mask = persistentDef->numatune.memory.nodemask;
> + if (mask)
> + nodeset = virDomainCpuSetFormat(mask,
> + VIR_DOMAIN_CPUMASK_LEN);
> + else
> + nodeset = strdup("");
> + } else {
> + rc = virCgroupGetCpusetMems(group, &nodeset);
> + if (rc != 0) {
> + virReportSystemError(-rc, "%s",
> + _("unable to get numa nodeset"));
> + goto cleanup;
> + }
> + }
> + if (!nodeset) {
> + virReportOOMError();
> + goto cleanup;
> + }
> + param->type = VIR_TYPED_PARAM_STRING;
> + param->value.s = nodeset;
> + break;
> +
> + default:
> + break;
> + /* should not hit here */
> + }
> + }
> +
> + if (*nparams > QEMU_NB_NUMA_PARAM)
> + *nparams = QEMU_NB_NUMA_PARAM;
> + ret = 0;
> +
> +cleanup:
> + virCgroupFree(&group);
> + if (vm)
> + virDomainObjUnlock(vm);
> + qemuDriverUnlock(driver);
> + return ret;
> +}
> +
> +static int
> qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
> unsigned long long period, long long quota)
> {
> @@ -11362,6 +11622,8 @@ static virDriver qemuDriver = {
> .nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.8 */
> .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
> .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
> + .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
> + .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
> };
>
>
> --
> 1.7.7.4
--
Thanks,
Hu Tao
More information about the libvir-list
mailing list