--- include/libvirt/libvirt-domain.h | 9 +++ src/conf/domain_conf.c | 28 +++++++ src/conf/domain_conf.h | 3 + src/driver-hypervisor.h | 8 ++ src/libvirt-domain.c | 81 +++++++++++++++++++++ src/libvirt_public.syms | 6 ++ src/qemu/qemu_driver.c | 141 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_process.c | 65 ++++++++++++++++- src/remote/remote_daemon_dispatch.c | 45 ++++++++++++ src/remote/remote_driver.c | 2 + src/remote/remote_protocol.x | 28 ++++++- src/remote_protocol-structs | 12 +++ tools/virsh-domain.c | 74 +++++++++++++++++++ 13 files changed, 499 insertions(+), 3 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index da773b7..598db28 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4767,4 +4767,13 @@ int virDomainSetLifecycleAction(virDomainPtr domain, unsigned int action, unsigned int flags); +/* + * resctrl API + */ +int virDomainSetResctrlMon(virDomainPtr domain, + int enable, int disable); + +int virDomainGetResctrlMonSts(virDomainPtr domain, + char **sts); + #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5be773c..0ada3dc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -18885,6 +18885,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, xmlNodePtr *nodes = NULL; virBitmapPtr vcpus = NULL; virResctrlAllocPtr alloc = virResctrlAllocNew(); + virResctrlMonPtr mon= virResctrlMonNew(); virDomainCachetuneDefPtr tmp_cachetune = NULL; char *tmp = NULL; char *vcpus_str = NULL; @@ -18898,6 +18899,9 @@ virDomainCachetuneDefParse(virDomainDefPtr def, if (!alloc) goto cleanup; + if (!mon) + goto cleanup; + if (VIR_ALLOC(tmp_cachetune) < 0) goto cleanup; @@ -18970,8 +18974,12 @@ virDomainCachetuneDefParse(virDomainDefPtr def, if (virResctrlAllocSetID(alloc, alloc_id) < 0) goto cleanup; + if (virResctrlMonSetID(mon, alloc_id) < 0) + goto cleanup; + VIR_STEAL_PTR(tmp_cachetune->vcpus, vcpus); VIR_STEAL_PTR(tmp_cachetune->alloc, alloc); + VIR_STEAL_PTR(tmp_cachetune->mon, mon); if (VIR_APPEND_ELEMENT(def->cachetunes, def->ncachetunes, tmp_cachetune) < 0) goto cleanup; @@ -18990,6 +18998,20 @@ virDomainCachetuneDefParse(virDomainDefPtr def, } +static int +virDomainResctrlDefParse(virDomainDefPtr def, + xmlXPathContextPtr ctxr ATTRIBUTE_UNUSED) +{ + virResctrlMonPtr mon= virResctrlMonNew(); + if (virResctrlMonSetID(mon, "vcpu-rest") < 0) + return -1; + + def->resctrlmon_noalloc = mon; + + return 0; +} + + static virDomainDefPtr virDomainDefParseXML(xmlDocPtr xml, xmlNodePtr root, @@ -19585,6 +19607,12 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); + if (virDomainResctrlDefParse(def, ctxt) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot extract resctrl")); + goto error; + } + if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu) < 0) goto error; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 8a8121b..2febe62 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2234,6 +2234,7 @@ typedef virDomainCachetuneDef *virDomainCachetuneDefPtr; struct _virDomainCachetuneDef { virBitmapPtr vcpus; virResctrlAllocPtr alloc; + virResctrlMonPtr mon; }; @@ -2389,6 +2390,8 @@ struct _virDomainDef { virDomainCputune cputune; + virResctrlMonPtr resctrlmon_noalloc; + virDomainCachetuneDefPtr *cachetunes; size_t ncachetunes; diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index aa99cbb..c2e5d2a 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1309,6 +1309,12 @@ typedef int unsigned int action, unsigned int flags); +typedef int +(*virDrvDomainSetResctrlMon)(virDomainPtr domain, + int enable, int disable); + +typedef char * +(*virDrvDomainGetResctrlMonSts)(virDomainPtr domain); typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1558,6 +1564,8 @@ struct _virHypervisorDriver { virDrvDomainSetLifecycleAction domainSetLifecycleAction; virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU; virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU; + virDrvDomainSetResctrlMon domainSetResctrlMon; + virDrvDomainGetResctrlMonSts domainGetResctrlMonSts; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index d44b553..07a19a6 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -12154,3 +12154,84 @@ int virDomainSetLifecycleAction(virDomainPtr domain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainSetResctrlMon: + * @domain: a domain object + * @enable: true(non-zero) for enbling resctrl mon group. + * @disable: true(non-zero) for disbling resctrl mon group. + * valid if @enable is false + * + * Enable or disable resctrl monitoring. + * + * Returns -1 in case of failure, 0 in case of success. + */ +int +virDomainSetResctrlMon(virDomainPtr domain, + int enable, int disable) +{ + int ret; + virConnectPtr conn; + + virResetLastError(); + + if(!disable && !enable) + return 0; + + virCheckDomainReturn(domain, -1); + + conn = domain->conn; + + if (conn->driver->domainSetResctrlMon) { + ret = conn->driver->domainSetResctrlMon(domain, + enable, disable); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(domain->conn); + return -1; +} + + +/** + * virDomainGetResctrlMonSts: + * @domain: a domain object + * @status: pointer of a string buffer for holding resctrl mon + * group status string, caller is responsible for free it. + * + * Get domain resctrl status. + * + * Returns -1 in case of failure, 0 in case of success. + */ +int +virDomainGetResctrlMonSts(virDomainPtr domain, + char **status) +{ + int ret = -1; + virConnectPtr conn; + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + + conn = domain->conn; + + if (conn->driver->domainGetResctrlMonSts) { + *status = conn->driver->domainGetResctrlMonSts(domain); + if (*status) + ret = 0; + + goto done; + } + + virReportUnsupportedError(); + done: + virDispatchError(domain->conn); + return ret; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 4f54b84..fb3eef5 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -798,4 +798,10 @@ LIBVIRT_4.5.0 { virGetLastErrorDomain; } LIBVIRT_4.4.0; +LIBVIRT_4.6.0 { + global: + virDomainSetResctrlMon; + virDomainGetResctrlMonSts; +} LIBVIRT_4.5.0; + # .... define new API here using predicted next version number .... diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 38ea865..4075daa 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -108,6 +108,7 @@ #include "virnuma.h" #include "dirname.h" #include "netdev_bandwidth_conf.h" +#include "virresctrl.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -21437,6 +21438,144 @@ qemuDomainSetLifecycleAction(virDomainPtr dom, } +static int +qemuDomainSetResctrlMon(virDomainPtr dom, + int enable ,int disable) +{ + int ret = -1; + virDomainObjPtr vm; + virResctrlMonAct act = VIR_RESCTRL_MONACT_NONE;; + int i = 0; + unsigned int maxvcpus = 0; + + /* The 'enable' action will override the 'disable' one */ + if(disable) + act = VIR_RESCTRL_MONACT_DISABLE; + if(enable) + act = VIR_RESCTRL_MONACT_ENABLE; + + if (act == VIR_RESCTRL_MONACT_NONE) + return 0; + + if (!(vm = qemuDomObjFromDomain(dom))) + return ret; + + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain is not running")); + goto cleanup; + } + + /* If 'resctrl' is enabled in xml configuation file through 'cachetune' + * section, this interface doesn't work. return 1 for this case */ + if (vm->def->ncachetunes != 0){ + VIR_DEBUG("resctrl monitoring interface is governed by domain " + "configration 'cachetune' sections. Interface disabled.\n"); + ret = 1; + goto cleanup; + } + + if (act == VIR_RESCTRL_MONACT_ENABLE) { + + if (!vm->def->resctrlmon_noalloc){ + virReportError(VIR_ERR_NO_DOMAIN, + _("resctrlmon_noalloc should be allocated.")); + goto cleanup; + } + + if(!virResctrlMonIsRunning(vm->def->resctrlmon_noalloc)) { + + if (virResctrlMonCreate(NULL, + vm->def->resctrlmon_noalloc, priv->machineName) < 0) + goto cleanup; + + /* Set vcpus */ + maxvcpus = virDomainDefGetVcpusMax(vm->def); + for (i = 0; i < maxvcpus; i++) { + virDomainVcpuDefPtr vcpu + = virDomainDefGetVcpu(vm->def, i); + + if (!vcpu->online) + continue; + + pid_t vcpupid = qemuDomainGetVcpuPid(vm, i); + if (virResctrlMonAddPID(vm->def->resctrlmon_noalloc, + vcpupid) < 0) + goto cleanup; + } + } + + VIR_DEBUG("resctrl monitoring is enabled"); + } else if (act == VIR_RESCTRL_MONACT_DISABLE){ + if (!vm->def->resctrlmon_noalloc){ + virReportError(VIR_ERR_NO_DOMAIN, + _("resctrlmon_noalloc should be allocated.")); + goto cleanup; + } + + if(virResctrlMonIsRunning(vm->def->resctrlmon_noalloc)) { + if (virResctrlMonRemove(vm->def->resctrlmon_noalloc) < 0){ + virReportError(VIR_ERR_NO_DOMAIN, + _("Error in remove resctrl mon group.")); + goto cleanup; + } + } + + VIR_DEBUG("resctrl monitoring is disabled\n"); + } + + ret = 0; +cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + +static char * +qemuDomainGetResctrlMonSts(virDomainPtr dom) +{ + virDomainObjPtr vm; + char *sts = NULL; + + if (!(vm = qemuDomObjFromDomain(dom))) + return sts; + + if (vm->def->ncachetunes != 0){ + VIR_DEBUG("resctrl monitoring interface is governed by domain " + "'cachetune' sections. resctrl monitoring is compulsively enabled.\n"); + + /* only check cachetune[0] for domain resctrl mon group status */ + if (!virResctrlMonIsRunning(vm->def->cachetunes[0]->mon)) { + if (virAsprintf(&sts, "Disabled") < 0) + goto cleanup; + } else { + if (virAsprintf(&sts, "Enabled (forced by cachetune)") < 0) + goto cleanup; + } + + } else { + + if (vm->def->resctrlmon_noalloc && + virResctrlMonIsRunning(vm->def->resctrlmon_noalloc)){ + if (virAsprintf(&sts, "Enabled") < 0) + goto cleanup; + + } else { + if (virAsprintf(&sts, "Disabled") < 0) + goto cleanup; + } + } + + VIR_DEBUG("resctrl monitoring status: %s\n", sts); + +cleanup: + virDomainObjEndAPI(&vm); + return sts; +} + + static virHypervisorDriver qemuHypervisorDriver = { .name = QEMU_DRIVER_NAME, .connectURIProbe = qemuConnectURIProbe, @@ -21660,6 +21799,8 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */ .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */ .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */ + .domainSetResctrlMon = qemuDomainSetResctrlMon, /*FIXME: assign proper ver string */ + .domainGetResctrlMonSts = qemuDomainGetResctrlMonSts, /*FIXME: assign proper ver string */ }; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 1606f4c..4fab0e1 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2461,6 +2461,11 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, vm->def->cachetunes[i]->alloc, priv->machineName) < 0) goto cleanup; + + if (virResctrlMonCreate(vm->def->cachetunes[i]->alloc, + vm->def->cachetunes[i]->mon, + priv->machineName) < 0) + goto cleanup; } ret = 0; @@ -5259,6 +5264,7 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, &vcpu->sched) < 0) return -1; + for (i = 0; i < vm->def->ncachetunes; i++) { virDomainCachetuneDefPtr ct = vm->def->cachetunes[i]; @@ -5279,6 +5285,10 @@ qemuProcessSetupVcpus(virDomainObjPtr vm) virDomainVcpuDefPtr vcpu; unsigned int maxvcpus = virDomainDefGetVcpusMax(vm->def); size_t i; + virBitmapPtr vcpuleft = NULL; + int ret = -1; + + qemuDomainObjPrivatePtr priv = vm->privateData; if ((vm->def->cputune.period || vm->def->cputune.quota) && !virCgroupHasController(((qemuDomainObjPrivatePtr) vm->privateData)->cgroup, @@ -5308,17 +5318,52 @@ qemuProcessSetupVcpus(virDomainObjPtr vm) return 0; } + /* To monitor whole domain's cache occupancy information + * create mon group for un-covered VCPUs */ + if (!(vcpuleft = virBitmapNew(maxvcpus + 1))) + goto cleanup; + + virBitmapClearAll(vcpuleft); + for (i = 0; i < maxvcpus; i++) { vcpu = virDomainDefGetVcpu(vm->def, i); if (!vcpu->online) continue; + if ( virBitmapSetBit(vcpuleft, i) < 0) + goto cleanup; + if (qemuProcessSetupVcpu(vm, i) < 0) return -1; } - return 0; + for (i = 0; i < vm->def->ncachetunes; i++) { + virDomainCachetuneDefPtr ct = vm->def->cachetunes[i]; + virBitmapSubtract(vcpuleft, ct->vcpus); + } + + + if (vm->def->ncachetunes && + !virBitmapIsAllClear(vcpuleft)){ + + if (virResctrlMonCreate(NULL, vm->def->resctrlmon_noalloc, priv->machineName) < 0) + goto cleanup; + + for (i = 0; i < maxvcpus; i++) { + if (virBitmapIsBitSet(vcpuleft, i)){ + pid_t vcpupid = qemuDomainGetVcpuPid(vm, i); + + if (virResctrlMonAddPID(vm->def->resctrlmon_noalloc, vcpupid) < 0) + goto cleanup; + } + } + } + + ret = 0; +cleanup: + virBitmapFree(vcpuleft); + return ret; } @@ -6895,8 +6940,14 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* Remove resctrl allocation after cgroups are cleaned up which makes it * kind of safer (although removing the allocation should work even with * pids in tasks file */ - for (i = 0; i < vm->def->ncachetunes; i++) + for (i = 0; i < vm->def->ncachetunes; i++){ virResctrlAllocRemove(vm->def->cachetunes[i]->alloc); + virResctrlMonRemove(vm->def->cachetunes[i]->mon); + } + + if(vm->def->resctrlmon_noalloc) + virResctrlMonRemove(vm->def->resctrlmon_noalloc); + qemuProcessRemoveDomainStatus(driver, vm); @@ -7620,8 +7671,18 @@ qemuProcessReconnect(void *opaque) if (virResctrlAllocDeterminePath(obj->def->cachetunes[i]->alloc, priv->machineName) < 0) goto error; + + if (virResctrlMonDeterminePath(obj->def->cachetunes[i]->mon, + priv->machineName) < 0) + goto error; + } + if(obj->def->resctrlmon_noalloc && + virResctrlMonDeterminePath(obj->def->resctrlmon_noalloc, + priv->machineName) < 0) + goto error; + /* update domain state XML with possibly updated state in virDomainObj */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, obj, driver->caps) < 0) goto error; diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 81d0445..2ef0e5e 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -7107,3 +7107,48 @@ remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors, } return -1; } + +static int remoteDispatchDomainGetResctrlMonSts( + virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_get_resctrl_mon_sts_args *args, + remote_domain_get_resctrl_mon_sts_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + char *sts = NULL; + char **sts_p = NULL; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + + if ((rv = virDomainGetResctrlMonSts(dom, &sts)) < 0) + goto cleanup; + + if (VIR_ALLOC(sts_p) < 0) + goto cleanup; + + if (VIR_STRDUP(*sts_p, sts) < 0) + goto cleanup; + + ret->sts = sts_p; + rv = 0; + +cleanup: + if (rv < 0) { + virNetMessageSaveError(rerr); + VIR_FREE(sts_p); + } + virObjectUnref(dom); + VIR_FREE(sts); + return rv; +} diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index c22993c..4a6b101 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8451,6 +8451,8 @@ static virHypervisorDriver hypervisor_driver = { .domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */ .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 */ .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 4.4.0 */ + .domainSetResctrlMon = remoteDomainSetResctrlMon, /*FIXME: assign proper ver string */ + .domainGetResctrlMonSts = remoteDomainGetResctrlMonSts, /*FIXME: assign proper ver string */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index a0ab7e9..9242a61 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3480,6 +3480,20 @@ struct remote_connect_baseline_hypervisor_cpu_ret { remote_nonnull_string cpu; }; +struct remote_domain_set_resctrl_mon_args { + remote_nonnull_domain dom; + int enable; + int disable; +}; + +struct remote_domain_get_resctrl_mon_sts_args { + remote_nonnull_domain dom; +}; + +struct remote_domain_get_resctrl_mon_sts_ret { /* insert@1 */ + remote_string sts; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -6187,5 +6201,17 @@ enum remote_procedure { * @generate: both * @acl: connect:write */ - REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394 + REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394, + + /** + * @generate: both + * @acl: domain:write + */ + REMOTE_PROC_DOMAIN_SET_RESCTRL_MON = 395, + + /** + * @generate: client + * @acl: domain:read + */ + REMOTE_PROC_DOMAIN_GET_RESCTRL_MON_STS = 396 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 0c4cfc6..ed6a782 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2907,6 +2907,16 @@ struct remote_connect_baseline_hypervisor_cpu_args { struct remote_connect_baseline_hypervisor_cpu_ret { remote_nonnull_string cpu; }; +struct remote_domain_set_resctrl_mon_args { + remote_nonnull_domain dom; + int enable; + int disable; +} +struct remote_domain_get_resctrl_mon_sts_args { + remote_nonnull_domain dom; +}; +struct remote_domain_get_resctrl_mon_sts_ret { + remote_string sts; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3302,4 +3312,6 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_DETACH_DEVICE_ALIAS = 392, REMOTE_PROC_CONNECT_COMPARE_HYPERVISOR_CPU = 393, REMOTE_PROC_CONNECT_BASELINE_HYPERVISOR_CPU = 394, + REMOTE_PROC_DOMAIN_SET_RESCTRL_MON = 395, + REMOTE_PROC_DOMAIN_GET_RESCTRL_MON_STS = 396, }; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 6aa79f1..4ae8ed2 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -7677,6 +7677,74 @@ cmdIOThreadDel(vshControl *ctl, const vshCmd *cmd) return ret; } +static const vshCmdInfo info_resctrl[] = { + {.name = "help", + .data = N_("get or set hardware CPU resource monitoring functions") + }, + {.name = "desc", + .data = N_("Enable or disable resctrl monitoring for a guest domain.\n" + " To get resctrl status use following" + " command: \n\n" + " virsh # resctrl <domain>") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_resctrl[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE), + {.name = "enable", + .type = VSH_OT_BOOL, + .help = N_("Enable resctrl function such as monitoring cache occupancy " + "or memory bandwidth.") + }, + {.name = "disable", + .type = VSH_OT_BOOL, + .help = N_("Disable hardware function such as monitoring cache occupancy " + "or memory bandwidth.") + }, + {.name = NULL} +}; + + +static bool +cmdResctrl(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + bool ret = false; + char *ressts = NULL; + + bool enable = vshCommandOptBool(cmd, "enable"); + bool disable= vshCommandOptBool(cmd, "disable"); + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if(!enable && !disable){ + if (virDomainGetResctrlMonSts(dom, &ressts) < 0) + goto cleanup; + + if (!ressts) + goto cleanup; + + } else { + if (virDomainSetResctrlMon(dom, enable, disable) < 0) + goto cleanup; + + if (virDomainGetResctrlMonSts(dom, &ressts) < 0) + goto cleanup; + + if (!ressts) + goto cleanup; + } + + vshPrint(ctl,"RDT Monitoring Status: %s\n", ressts); + ret = true; +cleanup: + VIR_FREE(ressts); + virshDomainFree(dom); + return ret; +} + /* * "cpu-stats" command */ @@ -13799,6 +13867,12 @@ const vshCmdDef domManagementCmds[] = { .flags = 0 }, #endif + {.name = "resctrl", + .handler = cmdResctrl, + .opts = opts_resctrl, + .info = info_resctrl, + .flags = 0 + }, {.name = "cpu-stats", .handler = cmdCPUStats, .opts = opts_cpu_stats, -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list