Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
src/qemu/qemu.conf | 5 ++-
src/qemu/qemu_conf.c | 3 +-
src/qemu/qemu_driver.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/cgroup.c | 7 ++++
src/util/cgroup.h | 1 +
5 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 4ec5e6c..5f75b3e 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -158,18 +158,19 @@
# - 'memory' - use for memory tunables
# - 'blkio' - use for block devices I/O tunables
# - 'cpuset' - use for CPUs and memory nodes
+# - 'cpuacct' - use for CPUs' account
#
# NB, even if configured here, they won't be used unless
# the administrator has mounted cgroups, e.g.:
#
# mkdir /dev/cgroup
-# mount -t cgroup -o devices,cpu,memory,blkio,cpuset none /dev/cgroup
+# mount -t cgroup -o devices,cpu,memory,blkio,cpuset,cpuacct none /dev/cgroup
#
# They can be mounted anywhere, and different controllers
# can be mounted in different locations. libvirt will detect
# where they are located.
#
-# cgroup_controllers = [ "cpu", "devices", "memory",
"blkio", "cpuset" ]
+# cgroup_controllers = [ "cpu", "devices", "memory",
"blkio", "cpuset", "cpuacct" ]
# This is the basic set of devices allowed / required by
# all virtual machines.
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index bc0a646..4775638 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -307,7 +307,8 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
(1 << VIR_CGROUP_CONTROLLER_DEVICES) |
(1 << VIR_CGROUP_CONTROLLER_MEMORY) |
(1 << VIR_CGROUP_CONTROLLER_BLKIO) |
- (1 << VIR_CGROUP_CONTROLLER_CPUSET);
+ (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
+ (1 << VIR_CGROUP_CONTROLLER_CPUACCT);
}
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
if (driver->cgroupControllers & (1 << i)) {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 82bab67..3d023eb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11194,6 +11194,79 @@ cleanup:
return ret;
}
+static int
+qemuGetPcpusUsage(virDomainPtr dom,
+ unsigned long long *usages,
+ int *nr_usages,
+ unsigned int flags)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ virCgroupPtr group = NULL;
+ virDomainObjPtr vm = NULL;
+ char *pos, *raw;
+ unsigned long long val;
+ int nr_cpus = 0;
+ int ret = -1;
+ int rc;
+ bool isActive;
+
+ virCheckFlags(0, -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;
+ }
+
+ isActive = virDomainObjIsActive(vm);
+
+ if (!isActive) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain is not running"));
+ goto cleanup;
+ }
+
+ if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUACCT)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cgroup CPUACCT 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;
+ }
+
+ rc = virCgroupGetCpuacctPcpusUsage(group, &raw);
+ if (rc != 0) {
+ virReportSystemError(-rc, "%s", _("unable to get cpu
account"));
+ goto cleanup;
+ }
+
+ pos = raw;
+ while (virStrToLong_ull(pos, &pos, 10, &val) >= 0) {
+ if (nr_cpus < *nr_usages) {
+ usages[nr_cpus] = val;
+ }
+ nr_cpus++;
+ }
+
+ VIR_FREE(raw);
+ *nr_usages = nr_cpus;
+ ret = 0;
+
+cleanup:
+ virCgroupFree(&group);
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
static virDomainPtr qemuDomainAttach(virConnectPtr conn,
unsigned int pid,
@@ -11997,6 +12070,7 @@ static virDriver qemuDriver = {
.domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
.domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
.domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
+ .domainGetPcpusUsage = qemuGetPcpusUsage, /* 0.9.10 */
};
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 25f2691..114eeb5 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -1554,6 +1554,13 @@ int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long
*usage)
"cpuacct.usage", usage);
}
+int virCgroupGetCpuacctPcpusUsage(virCgroupPtr group, char **usage)
+{
+ return virCgroupGetValueStr(group,
+ VIR_CGROUP_CONTROLLER_CPUACCT,
+ "cpuacct.usage_percpu", usage);
+}
+
int virCgroupSetFreezerState(virCgroupPtr group, const char *state)
{
return virCgroupSetValueStr(group,
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index 8d75735..f3c4b7d 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -115,6 +115,7 @@ int virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota);
int virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota);
int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage);
+int virCgroupGetCpuacctPcpusUsage(virCgroupPtr group, char **usage);
int virCgroupSetFreezerState(virCgroupPtr group, const char *state);
int virCgroupGetFreezerState(virCgroupPtr group, char **state);
--
1.7.4.4