[libvirt] [RFC PATCH v1 6/7] deploy the newly introduced virCgroupItem.

Hu Tao hutao at cn.fujitsu.com
Wed Jan 16 02:53:08 UTC 2013


This patch deploys the newly introduced virCgroupItem and
removes the old cgroup code.
---
 daemon/libvirtd.c         |    4 +
 src/conf/domain_audit.c   |   16 +-
 src/conf/domain_audit.h   |    6 +-
 src/conf/domain_conf.h    |    5 +
 src/libvirt_private.syms  |   10 +-
 src/lxc/lxc_cgroup.c      |   91 ++--
 src/lxc/lxc_conf.h        |    2 +-
 src/lxc/lxc_driver.c      |  268 ++++------
 src/lxc/lxc_process.c     |   56 +--
 src/qemu/qemu_cgroup.c    |  287 ++++-------
 src/qemu/qemu_cgroup.h    |   17 +-
 src/qemu/qemu_conf.h      |    2 +-
 src/qemu/qemu_driver.c    |  478 ++++++------------
 src/qemu/qemu_hotplug.c   |   44 +-
 src/qemu/qemu_migration.c |   36 +-
 src/qemu/qemu_process.c   |   29 +-
 src/util/vircgroup.c      | 1181 ++++++++++++---------------------------------
 src/util/vircgroup.h      |   94 ++--
 18 files changed, 813 insertions(+), 1813 deletions(-)

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 7cb99b1..92e3292 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1442,6 +1442,9 @@ int main(int argc, char **argv) {
         VIR_FORCE_CLOSE(statuswrite);
     }
 
+    if (virCgroupInit() < 0)
+        goto cleanup;
+
     /* Initialize drivers & then start accepting new clients from network */
     if (daemonStateInit(srv) < 0) {
         ret = VIR_DAEMON_ERR_INIT;
@@ -1501,6 +1504,7 @@ cleanup:
     daemonConfigFree(config);
 
     virStateCleanup();
+    virCgroupUninit();
 
     return ret;
 }
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 7082804..6c7efe8 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -420,12 +420,12 @@ cleanup:
  * Log an audit message about an attempted cgroup device ACL change.
  */
 void
-virDomainAuditCgroup(virDomainObjPtr vm, virCgroupPtr cgroup,
+virDomainAuditCgroup(virDomainObjPtr vm, virCgroupItemPtr cgroup,
                      const char *reason, const char *extra, bool success)
 {
     char uuidstr[VIR_UUID_STRING_BUFLEN];
     char *vmname;
-    char *controller = NULL;
+    char *path = NULL;
     char *detail;
     const char *virt;
 
@@ -440,10 +440,8 @@ virDomainAuditCgroup(virDomainObjPtr vm, virCgroupPtr cgroup,
         virt = "?";
     }
 
-    ignore_value(virCgroupPathOfController(cgroup,
-                                           VIR_CGROUP_CONTROLLER_DEVICES,
-                                           NULL, &controller));
-    detail = virAuditEncode("cgroup", VIR_AUDIT_STR(controller));
+    ignore_value(virCgroupItemPath(cgroup, false, &path));
+    detail = virAuditEncode("cgroup", VIR_AUDIT_STR(path));
 
     VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
               "virt=%s resrc=cgroup reason=%s %s uuid=%s %s class=%s",
@@ -451,7 +449,7 @@ virDomainAuditCgroup(virDomainObjPtr vm, virCgroupPtr cgroup,
               detail ? detail : "cgroup=?", extra);
 
     VIR_FREE(vmname);
-    VIR_FREE(controller);
+    VIR_FREE(path);
     VIR_FREE(detail);
 }
 
@@ -468,7 +466,7 @@ virDomainAuditCgroup(virDomainObjPtr vm, virCgroupPtr cgroup,
  * Log an audit message about an attempted cgroup device ACL change.
  */
 void
-virDomainAuditCgroupMajor(virDomainObjPtr vm, virCgroupPtr cgroup,
+virDomainAuditCgroupMajor(virDomainObjPtr vm, virCgroupItemPtr cgroup,
                           const char *reason, int maj, const char *name,
                           const char *perms, bool success)
 {
@@ -498,7 +496,7 @@ virDomainAuditCgroupMajor(virDomainObjPtr vm, virCgroupPtr cgroup,
  * a specific device.
  */
 void
-virDomainAuditCgroupPath(virDomainObjPtr vm, virCgroupPtr cgroup,
+virDomainAuditCgroupPath(virDomainObjPtr vm, virCgroupItemPtr cgroup,
                          const char *reason, const char *path, const char *perms,
                          int rc)
 {
diff --git a/src/conf/domain_audit.h b/src/conf/domain_audit.h
index 381fe37..573f592 100644
--- a/src/conf/domain_audit.h
+++ b/src/conf/domain_audit.h
@@ -66,14 +66,14 @@ void virDomainAuditHostdev(virDomainObjPtr vm,
                            bool success)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 void virDomainAuditCgroup(virDomainObjPtr vm,
-                          virCgroupPtr group,
+                          virCgroupItemPtr group,
                           const char *reason,
                           const char *extra,
                           bool success)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(4);
 void virDomainAuditCgroupMajor(virDomainObjPtr vm,
-                               virCgroupPtr group,
+                               virCgroupItemPtr group,
                                const char *reason,
                                int maj,
                                const char *name,
@@ -82,7 +82,7 @@ void virDomainAuditCgroupMajor(virDomainObjPtr vm,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6);
 void virDomainAuditCgroupPath(virDomainObjPtr vm,
-                              virCgroupPtr group,
+                              virCgroupItemPtr group,
                               const char *reason,
                               const char *path,
                               const char *perms,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 2ac338c..23ff2c9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -48,6 +48,7 @@
 # include "device_conf.h"
 # include "virbitmap.h"
 # include "virstoragefile.h"
+# include "vircgroup.h"
 
 /* forward declarations of all device types, required by
  * virDomainDeviceDef
@@ -1843,6 +1844,10 @@ struct _virDomainDef {
 
     /* Application-specific custom metadata */
     xmlNodePtr metadata;
+
+    virCgroupItemPtr cgroup[VIR_CGROUP_CONTROLLER_LAST];
+    virCgroupItemPtr (*vcpuCgroups)[VIR_CGROUP_CONTROLLER_LAST];
+    virCgroupItemPtr emulatorCgroup[VIR_CGROUP_CONTROLLER_LAST];
 };
 
 enum virDomainTaintFlags {
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 636c49d..82621ab 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -72,8 +72,6 @@ virCapabilitiesSetMacPrefix;
 
 
 # cgroup.h
-virCgroupAddTask;
-virCgroupAddTaskController;
 virCgroupAllowDevice;
 virCgroupAllowDeviceMajor;
 virCgroupAllowDevicePath;
@@ -83,10 +81,6 @@ virCgroupDenyAllDevices;
 virCgroupDenyDevice;
 virCgroupDenyDeviceMajor;
 virCgroupDenyDevicePath;
-virCgroupForDomain;
-virCgroupForDriver;
-virCgroupForEmulator;
-virCgroupForVcpu;
 virCgroupFree;
 virCgroupGetAppRoot;
 virCgroupGetBlkioWeight;
@@ -105,6 +99,7 @@ virCgroupGetMemoryUsage;
 virCgroupGetMemSwapHardLimit;
 virCgroupGetMemSwapUsage;
 virCgroupInit;
+virCgroupItemAddTask;
 virCgroupItemFree;
 virCgroupItemKeyPath;
 virCgroupItemNew;
@@ -114,9 +109,8 @@ virCgroupKill;
 virCgroupKillPainfully;
 virCgroupKillRecursive;
 virCgroupMounted;
-virCgroupMoveTask;
+virCgroupNew;
 virCgroupPathOfController;
-virCgroupRemove;
 virCgroupSetBlkioDeviceWeight;
 virCgroupSetBlkioWeight;
 virCgroupSetCpuCfsPeriod;
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index 1984c5f..8363383 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -32,7 +32,7 @@
 #define VIR_FROM_THIS VIR_FROM_LXC
 
 static int virLXCCgroupSetupCpuTune(virDomainDefPtr def,
-                                    virCgroupPtr cgroup)
+                                    virCgroupItemPtr cgroup)
 {
     int ret = -1;
     if (def->cputune.shares != 0) {
@@ -69,7 +69,7 @@ cleanup:
 
 
 static int virLXCCgroupSetupBlkioTune(virDomainDefPtr def,
-                                      virCgroupPtr cgroup)
+                                      virCgroupItemPtr cgroup)
 {
     int ret = -1;
 
@@ -90,7 +90,7 @@ cleanup:
 
 
 static int virLXCCgroupSetupMemTune(virDomainDefPtr def,
-                                    virCgroupPtr cgroup)
+                                    virCgroupItemPtr cgroup)
 {
     int ret = -1;
     int rc;
@@ -139,21 +139,21 @@ cleanup:
 }
 
 
-static int virLXCCgroupGetMemSwapUsage(virCgroupPtr cgroup,
+static int virLXCCgroupGetMemSwapUsage(virCgroupItemPtr cgroup,
                                        virLXCMeminfoPtr meminfo)
 {
     return virCgroupGetMemSwapUsage(cgroup, &meminfo->swapusage);
 }
 
 
-static int virLXCCgroupGetMemSwapTotal(virCgroupPtr cgroup,
+static int virLXCCgroupGetMemSwapTotal(virCgroupItemPtr cgroup,
                                        virLXCMeminfoPtr meminfo)
 {
     return virCgroupGetMemSwapHardLimit(cgroup, &meminfo->swaptotal);
 }
 
 
-static int virLXCCgroupGetMemUsage(virCgroupPtr cgroup,
+static int virLXCCgroupGetMemUsage(virCgroupItemPtr cgroup,
                                    virLXCMeminfoPtr meminfo)
 {
     int ret;
@@ -166,14 +166,14 @@ static int virLXCCgroupGetMemUsage(virCgroupPtr cgroup,
 }
 
 
-static int virLXCCgroupGetMemTotal(virCgroupPtr cgroup,
+static int virLXCCgroupGetMemTotal(virCgroupItemPtr cgroup,
                                    virLXCMeminfoPtr meminfo)
 {
     return virCgroupGetMemoryHardLimit(cgroup, &meminfo->memtotal);
 }
 
 
-static int virLXCCgroupGetMemStat(virCgroupPtr cgroup,
+static int virLXCCgroupGetMemStat(virCgroupItemPtr cgroup,
                                   virLXCMeminfoPtr meminfo)
 {
     int ret = 0;
@@ -182,8 +182,7 @@ static int virLXCCgroupGetMemStat(virCgroupPtr cgroup,
     char *line = NULL;
     size_t n;
 
-    ret = virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.stat", &statFile);
+    ret = virCgroupItemKeyPath(cgroup, "memory.stat", &statFile);
     if (ret != 0) {
         virReportSystemError(-ret, "%s",
                              _("cannot get the path of MEMORY cgroup controller"));
@@ -240,13 +239,13 @@ cleanup:
 int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo)
 {
     int ret;
-    virCgroupPtr cgroup;
+    virCgroupItemPtr cgroup;
 
-    ret = virCgroupGetAppRoot(&cgroup);
-    if (ret < 0) {
-        virReportSystemError(-ret, "%s",
+    cgroup = virCgroupGetAppRoot(VIR_CGROUP_CONTROLLER_MEMORY, false);
+    if (!cgroup) {
+        virReportSystemError(-1, "%s",
                              _("Unable to get cgroup for container"));
-        return ret;
+        return -1;
     }
 
     ret = virLXCCgroupGetMemStat(cgroup, meminfo);
@@ -275,7 +274,6 @@ int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo)
 
     ret = 0;
 cleanup:
-    virCgroupFree(&cgroup);
     return ret;
 }
 
@@ -296,7 +294,7 @@ virLXCSetupHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED,
                                const char *path,
                                void *opaque)
 {
-    virCgroupPtr cgroup = opaque;
+    virCgroupItemPtr cgroup = opaque;
     int rc;
 
     VIR_DEBUG("Process path '%s' for USB device", path);
@@ -318,7 +316,7 @@ virLXCTeardownHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED,
                                   const char *path,
                                   void *opaque)
 {
-    virCgroupPtr cgroup = opaque;
+    virCgroupItemPtr cgroup = opaque;
     int rc;
 
     VIR_DEBUG("Process path '%s' for USB device", path);
@@ -336,7 +334,7 @@ virLXCTeardownHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED,
 
 
 static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
-                                      virCgroupPtr cgroup)
+                                      virCgroupItemPtr cgroup)
 {
     int ret = -1;
     int rc;
@@ -471,51 +469,52 @@ cleanup:
 
 int virLXCCgroupSetup(virDomainDefPtr def)
 {
-    virCgroupPtr driver = NULL;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr driver[VIR_CGROUP_CONTROLLER_LAST];
     int ret = -1;
     int rc;
+    int i;
 
-    rc = virCgroupForDriver("lxc", &driver, 1, 0);
-    if (rc != 0) {
-        virReportSystemError(-rc, "%s",
-                             _("Unable to get cgroup for driver"));
-        goto cleanup;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        driver[i] = virCgroupItemNew(i, "lxc", virCgroupGetAppRoot(i, true));
+        def->cgroup[i] = virCgroupItemNew(i, def->name, driver[i]);
     }
 
-    rc = virCgroupForDomain(driver, def->name, &cgroup, 1);
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("Unable to create cgroup for domain %s"),
-                             def->name);
+    if (virLXCCgroupSetupCpuTune(def,
+                                 def->cgroup[VIR_CGROUP_CONTROLLER_CPU]) < 0)
         goto cleanup;
-    }
 
-    if (virLXCCgroupSetupCpuTune(def, cgroup) < 0)
+    if (virLXCCgroupSetupBlkioTune(def,
+                                   def->cgroup[VIR_CGROUP_CONTROLLER_BLKIO]) < 0)
         goto cleanup;
 
-    if (virLXCCgroupSetupBlkioTune(def, cgroup) < 0)
+    if (virLXCCgroupSetupMemTune(def,
+                                 def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY]) < 0)
         goto cleanup;
 
-    if (virLXCCgroupSetupMemTune(def, cgroup) < 0)
+    if (virLXCCgroupSetupDeviceACL(def,
+                                   def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES]) < 0)
         goto cleanup;
 
-    if (virLXCCgroupSetupDeviceACL(def, cgroup) < 0)
-        goto cleanup;
-
-    rc = virCgroupAddTask(cgroup, getpid());
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("Unable to add task %d to cgroup for domain %s"),
-                             getpid(), def->name);
-        goto cleanup;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        rc = virCgroupItemAddTask(def->cgroup[i], getpid());
+        if (rc != 0) {
+            virReportSystemError(-rc,
+                                 _("Unable to add task %d to cgroup for domain %s"),
+                                 getpid(), def->name);
+            goto cleanup;
+        }
     }
 
     ret = 0;
 
 cleanup:
-    virCgroupFree(&cgroup);
-    virCgroupFree(&driver);
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        if (ret != 0) {
+            virCgroupItemFree(def->cgroup[i]);
+            def->cgroup[i] = NULL;
+        }
+        virCgroupItemFree(driver[i]);
+    }
 
     return ret;
 }
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index d45e0a0..03d9ba3 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -52,7 +52,7 @@ struct _virLXCDriver {
 
     virCapsPtr caps;
 
-    virCgroupPtr cgroup;
+    virCgroupItemPtr cgroup[VIR_CGROUP_CONTROLLER_LAST];
 
     size_t nactive;
     virStateInhibitCallback inhibitCallback;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 8050ce6..d6d5a94 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -526,7 +526,7 @@ static int lxcDomainGetInfo(virDomainPtr dom,
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = NULL;
     int ret = -1, rc;
 
     lxcDriverLock(driver);
@@ -546,7 +546,8 @@ static int lxcDomainGetInfo(virDomainPtr dom,
         info->cpuTime = 0;
         info->memory = vm->def->mem.cur_balloon;
     } else {
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
+        cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUACCT];
+        if (!cgroup) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Unable to get cgroup for %s"), vm->def->name);
             goto cleanup;
@@ -557,6 +558,14 @@ static int lxcDomainGetInfo(virDomainPtr dom,
                            "%s", _("Cannot read cputime for domain"));
             goto cleanup;
         }
+
+        cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+        if (!cgroup) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unable to get cgroup for %s"), vm->def->name);
+            goto cleanup;
+        }
+
         if ((rc = virCgroupGetMemoryUsage(cgroup, &(info->memory))) < 0) {
             virReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Cannot read memory usage for domain"));
@@ -575,8 +584,6 @@ static int lxcDomainGetInfo(virDomainPtr dom,
 
 cleanup:
     lxcDriverUnlock(driver);
-    if (cgroup)
-        virCgroupFree(&cgroup);
     if (vm)
         virDomainObjUnlock(vm);
     return ret;
@@ -707,7 +714,7 @@ cleanup:
 static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
     virLXCDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = NULL;
     int ret = -1;
 
     lxcDriverLock(driver);
@@ -733,13 +740,8 @@ static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
         goto cleanup;
     }
 
-    if (driver->cgroup == NULL) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       "%s", _("cgroups must be configured on the host"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+    if (!cgroup) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unable to get cgroup for %s"), vm->def->name);
         goto cleanup;
@@ -756,8 +758,6 @@ static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
-    if (cgroup)
-        virCgroupFree(&cgroup);
     return ret;
 }
 
@@ -769,7 +769,7 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = NULL;
     virDomainObjPtr vm = NULL;
     int ret = -1;
     int rc;
@@ -796,7 +796,8 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
         goto cleanup;
     }
 
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+    if (!cgroup) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -831,8 +832,6 @@ lxcDomainSetMemoryParameters(virDomainPtr dom,
     }
 
 cleanup:
-    if (cgroup)
-        virCgroupFree(&cgroup);
     if (vm)
         virDomainObjUnlock(vm);
     lxcDriverUnlock(driver);
@@ -847,7 +846,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = NULL;
     virDomainObjPtr vm = NULL;
     unsigned long long val;
     int ret = -1;
@@ -873,7 +872,8 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
         goto cleanup;
     }
 
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+    if (!cgroup) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unable to get cgroup for %s"), vm->def->name);
         goto cleanup;
@@ -930,8 +930,6 @@ lxcDomainGetMemoryParameters(virDomainPtr dom,
     ret = 0;
 
 cleanup:
-    if (cgroup)
-        virCgroupFree(&cgroup);
     if (vm)
         virDomainObjUnlock(vm);
     lxcDriverUnlock(driver);
@@ -1407,7 +1405,7 @@ static int lxcStartup(bool privileged,
                       void *opaque ATTRIBUTE_UNUSED)
 {
     char *ld;
-    int rc;
+    int i;
 
     /* Valgrind gets very annoyed when we clone containers, so
      * disable LXC when under valgrind
@@ -1450,14 +1448,9 @@ static int lxcStartup(bool privileged,
     lxc_driver->log_libvirtd = 0; /* by default log to container logfile */
     lxc_driver->have_netns = lxcCheckNetNsSupport();
 
-    rc = virCgroupForDriver("lxc", &lxc_driver->cgroup, privileged, 1);
-    if (rc < 0) {
-        char buf[1024] ATTRIBUTE_UNUSED;
-        VIR_DEBUG("Unable to create cgroup for LXC driver: %s",
-                  virStrerror(-rc, buf, sizeof(buf)));
-        /* Don't abort startup. We will explicitly report to
-         * the user when they try to start a VM
-         */
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        lxc_driver->cgroup[i] = virCgroupItemNew(i, "lxc",
+                                                 virCgroupGetAppRoot(i, privileged));
     }
 
     /* Call function to load lxc driver configuration information */
@@ -1592,7 +1585,7 @@ static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *versio
  * Return 1 when CFS bandwidth is supported, 0 when CFS bandwidth is not
  * supported, -1 on error.
  */
-static int lxcGetCpuBWStatus(virCgroupPtr cgroup)
+static int lxcGetCpuBWStatus(virCgroupItemPtr cgroup)
 {
     char *cfs_period_path = NULL;
     int ret = -1;
@@ -1600,8 +1593,8 @@ static int lxcGetCpuBWStatus(virCgroupPtr cgroup)
     if (!cgroup)
         return 0;
 
-    if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
-                                  "cpu.cfs_period_us", &cfs_period_path) < 0) {
+    if (virCgroupItemKeyPath(cgroup, "cpu.cfs_period_us",
+                             &cfs_period_path) < 0) {
         VIR_INFO("cannot get the path of cgroup CPU controller");
         ret = 0;
         goto cleanup;
@@ -1626,7 +1619,7 @@ static bool lxcCgroupControllerActive(virLXCDriverPtr driver,
         return false;
     if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
         return false;
-    if (!virCgroupMounted(driver->cgroup, controller))
+    if (!virCgroupMounted(controller))
         return false;
 #if 0
     if (driver->cgroupControllers & (1 << controller))
@@ -1652,7 +1645,7 @@ static char *lxcGetSchedulerType(virDomainPtr domain,
     }
 
     if (nparams) {
-        rc = lxcGetCpuBWStatus(driver->cgroup);
+        rc = lxcGetCpuBWStatus(driver->cgroup[VIR_CGROUP_CONTROLLER_CPU]);
         if (rc < 0)
             goto cleanup;
         else if (rc == 0)
@@ -1672,7 +1665,7 @@ cleanup:
 
 
 static int
-lxcGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
+lxcGetVcpuBWLive(virCgroupItemPtr cgroup, unsigned long long *period,
                  long long *quota)
 {
     int rc;
@@ -1695,7 +1688,7 @@ lxcGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
 }
 
 
-static int lxcSetVcpuBWLive(virCgroupPtr cgroup, unsigned long long period,
+static int lxcSetVcpuBWLive(virCgroupItemPtr cgroup, unsigned long long period,
                             long long quota)
 {
     int rc;
@@ -1752,7 +1745,7 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr vmdef = NULL;
     int ret = -1;
@@ -1791,18 +1784,12 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
             goto cleanup;
     }
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
-            virReportError(VIR_ERR_OPERATION_INVALID,
-                           "%s", _("cgroup CPU controller is not mounted"));
-            goto cleanup;
-        }
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPU];
+    if ((flags & VIR_DOMAIN_AFFECT_LIVE) && !group) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find cgroup for domain %s"),
                            vm->def->name);
             goto cleanup;
-        }
     }
 
     for (i = 0; i < nparams; i++) {
@@ -1869,7 +1856,6 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom,
 
 cleanup:
     virDomainDefFree(vmdef);
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     lxcDriverUnlock(driver);
@@ -1891,7 +1877,7 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom,
                                unsigned int flags)
 {
     virLXCDriverPtr driver = dom->conn->privateData;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef;
     unsigned long long shares = 0;
@@ -1908,7 +1894,7 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom,
     lxcDriverLock(driver);
 
     if (*nparams > 1) {
-        rc = lxcGetCpuBWStatus(driver->cgroup);
+        rc = lxcGetCpuBWStatus(driver->cgroup[VIR_CGROUP_CONTROLLER_CPU]);
         if (rc < 0)
             goto cleanup;
         cpu_bw_status = !!rc;
@@ -1935,13 +1921,8 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom,
         goto out;
     }
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       "%s", _("cgroup CPU controller is not mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPU];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -1988,7 +1969,6 @@ out:
     ret = 0;
 
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     lxcDriverUnlock(driver);
@@ -2012,7 +1992,7 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef = NULL;
     int ret = -1;
@@ -2039,14 +2019,9 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
                                         &persistentDef) < 0)
         goto cleanup;
 
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_BLKIO];
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
-            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                           _("blkio cgroup isn't mounted"));
-            goto cleanup;
-        }
-
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+        if (!group) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find cgroup for domain %s"), vm->def->name);
             goto cleanup;
@@ -2097,7 +2072,6 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
 
     ret = 0;
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     lxcDriverUnlock(driver);
@@ -2114,7 +2088,7 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef = NULL;
     unsigned int val;
@@ -2144,14 +2118,10 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
                                         &persistentDef) < 0)
         goto cleanup;
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
-            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                           _("blkio cgroup isn't mounted"));
-            goto cleanup;
-        }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_BLKIO];
 
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+        if (!group) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find cgroup for domain %s"), vm->def->name);
             goto cleanup;
@@ -2203,8 +2173,6 @@ lxcDomainGetBlkioParameters(virDomainPtr dom,
     ret = 0;
 
 cleanup:
-    if (group)
-        virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     lxcDriverUnlock(driver);
@@ -2374,7 +2342,7 @@ cleanup:
     return ret;
 }
 
-static int lxcFreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
+static int lxcFreezeContainer(virDomainObjPtr vm)
 {
     int timeout = 1000; /* In milliseconds */
     int check_interval = 1; /* In milliseconds */
@@ -2382,10 +2350,9 @@ static int lxcFreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
     int waited_time = 0;
     int ret = -1;
     char *state = NULL;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_FREEZER];
 
-    if (!(driver->cgroup &&
-          virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
+    if (!cgroup)
         return -1;
 
     /* From here on, we know that cgroup != NULL.  */
@@ -2462,7 +2429,6 @@ error:
     ret = -1;
 
 cleanup:
-    virCgroupFree(&cgroup);
     VIR_FREE(state);
     return ret;
 }
@@ -2492,7 +2458,7 @@ static int lxcDomainSuspend(virDomainPtr dom)
     }
 
     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
-        if (lxcFreezeContainer(driver, vm) < 0) {
+        if (lxcFreezeContainer(vm) < 0) {
             virReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Suspend operation failed"));
             goto cleanup;
@@ -2517,18 +2483,16 @@ cleanup:
     return ret;
 }
 
-static int lxcUnfreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
+static int lxcUnfreezeContainer(virDomainObjPtr vm)
 {
     int ret;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_FREEZER];
 
-    if (!(driver->cgroup &&
-        virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
+    if (!cgroup)
         return -1;
 
     ret = virCgroupSetFreezerState(cgroup, "THAWED");
 
-    virCgroupFree(&cgroup);
     return ret;
 }
 
@@ -2557,7 +2521,7 @@ static int lxcDomainResume(virDomainPtr dom)
     }
 
     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
-        if (lxcUnfreezeContainer(driver, vm) < 0) {
+        if (lxcUnfreezeContainer(vm) < 0) {
             virReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Resume operation failed"));
             goto cleanup;
@@ -3100,7 +3064,7 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainDiskDefPtr def = dev->data.disk;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int ret = -1;
     char *dst;
     struct stat sb;
@@ -3185,17 +3149,7 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
                                         vm->def, def) < 0)
         goto cleanup;
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot find cgroup for domain %s"), vm->def->name);
-        goto cleanup;
-    }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
 
     if (virCgroupAllowDevicePath(group, def->src,
                                  (def->readonly ?
@@ -3215,8 +3169,6 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
 cleanup:
     def->src = tmpsrc;
     virDomainAuditDisk(vm, NULL, def->src, "attach", ret == 0);
-    if (group)
-        virCgroupFree(&group);
     if (dst && created && ret < 0)
         unlink(dst);
     return ret;
@@ -3370,7 +3322,7 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
     mode_t mode;
     bool created = false;
     usbDevice *usb = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
 
     if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -3405,13 +3357,8 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
         goto cleanup;
     }
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -3469,7 +3416,6 @@ cleanup:
         unlink(dstfile);
 
     usbFreeDevice(usb);
-    virCgroupFree(&group);
     VIR_FREE(src);
     VIR_FREE(dstfile);
     VIR_FREE(dstdir);
@@ -3485,7 +3431,7 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevDefPtr def = dev->data.hostdev;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int ret = -1;
     char *dst = NULL;
     char *vroot = NULL;
@@ -3554,13 +3500,9 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
                                           vm->def, def, vroot) < 0)
         goto cleanup;
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
 
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -3581,8 +3523,6 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
 
 cleanup:
     virDomainAuditHostdev(vm, def, "attach", ret == 0);
-    if (group)
-        virCgroupFree(&group);
     if (dst && created && ret < 0)
         unlink(dst);
     VIR_FREE(dst);
@@ -3598,7 +3538,7 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevDefPtr def = dev->data.hostdev;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int ret = -1;
     char *dst = NULL;
     char *vroot = NULL;
@@ -3667,13 +3607,8 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
                                           vm->def, def, vroot) < 0)
         goto cleanup;
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -3694,8 +3629,6 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
 
 cleanup:
     virDomainAuditHostdev(vm, def, "attach", ret == 0);
-    if (group)
-        virCgroupFree(&group);
     if (dst && created && ret < 0)
         unlink(dst);
     VIR_FREE(dst);
@@ -3812,13 +3745,12 @@ lxcDomainAttachDeviceLive(virConnectPtr conn,
 
 
 static int
-lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
-                              virDomainObjPtr vm,
+lxcDomainDetachDeviceDiskLive(virDomainObjPtr vm,
                               virDomainDeviceDefPtr dev)
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainDiskDefPtr def = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int i, ret = -1;
     char *dst;
 
@@ -3844,13 +3776,8 @@ lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
         goto cleanup;
     }
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -3876,8 +3803,6 @@ lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver,
 
 cleanup:
     VIR_FREE(dst);
-    if (group)
-        virCgroupFree(&group);
     return ret;
 }
 
@@ -3955,7 +3880,7 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevDefPtr def = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int idx, ret = -1;
     char *dst;
     char *vroot;
@@ -3983,13 +3908,8 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
         goto cleanup;
     }
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -4024,19 +3944,17 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver,
 cleanup:
     usbFreeDevice(usb);
     VIR_FREE(dst);
-    virCgroupFree(&group);
     return ret;
 }
 
 
 static int
-lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
-                                        virDomainObjPtr vm,
+lxcDomainDetachDeviceHostdevStorageLive(virDomainObjPtr vm,
                                         virDomainDeviceDefPtr dev)
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevDefPtr def = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int i, ret = -1;
     char *dst = NULL;
 
@@ -4062,13 +3980,8 @@ lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
         goto cleanup;
     }
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -4094,20 +4007,17 @@ lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
 
 cleanup:
     VIR_FREE(dst);
-    if (group)
-        virCgroupFree(&group);
     return ret;
 }
 
 
 static int
-lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
-                                     virDomainObjPtr vm,
+lxcDomainDetachDeviceHostdevMiscLive(virDomainObjPtr vm,
                                      virDomainDeviceDefPtr dev)
 {
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevDefPtr def = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     int i, ret = -1;
     char *dst = NULL;
 
@@ -4133,13 +4043,8 @@ lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
         goto cleanup;
     }
 
-    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("devices cgroup isn't mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -4165,8 +4070,6 @@ lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver,
 
 cleanup:
     VIR_FREE(dst);
-    if (group)
-        virCgroupFree(&group);
     return ret;
 }
 
@@ -4190,16 +4093,15 @@ lxcDomainDetachDeviceHostdevSubsysLive(virLXCDriverPtr driver,
 
 
 static int
-lxcDomainDetachDeviceHostdevCapsLive(virLXCDriverPtr driver,
-                                       virDomainObjPtr vm,
-                                       virDomainDeviceDefPtr dev)
+lxcDomainDetachDeviceHostdevCapsLive(virDomainObjPtr vm,
+                                     virDomainDeviceDefPtr dev)
 {
     switch (dev->data.hostdev->source.caps.type) {
     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
-        return lxcDomainDetachDeviceHostdevStorageLive(driver, vm, dev);
+        return lxcDomainDetachDeviceHostdevStorageLive(vm, dev);
 
     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
-        return lxcDomainDetachDeviceHostdevMiscLive(driver, vm, dev);
+        return lxcDomainDetachDeviceHostdevMiscLive(vm, dev);
 
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -4228,7 +4130,7 @@ lxcDomainDetachDeviceHostdevLive(virLXCDriverPtr driver,
         return lxcDomainDetachDeviceHostdevSubsysLive(driver, vm, dev);
 
     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
-        return lxcDomainDetachDeviceHostdevCapsLive(driver, vm, dev);
+        return lxcDomainDetachDeviceHostdevCapsLive(vm, dev);
 
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -4248,7 +4150,7 @@ lxcDomainDetachDeviceLive(virLXCDriverPtr driver,
 
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
-        ret = lxcDomainDetachDeviceDiskLive(driver, vm, dev);
+        ret = lxcDomainDetachDeviceDiskLive(vm, dev);
         break;
 
     case VIR_DOMAIN_DEVICE_NET:
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 1a89e4a..30c8a89 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -218,7 +218,6 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
                                  virDomainObjPtr vm,
                                  virDomainShutoffReason reason)
 {
-    virCgroupPtr cgroup;
     int i;
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virNetDevVPortProfilePtr vport = NULL;
@@ -274,11 +273,8 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
 
     virDomainConfVMNWFilterTeardown(vm);
 
-    if (driver->cgroup &&
-        virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0) {
-        virCgroupRemove(cgroup);
-        virCgroupFree(&cgroup);
-    }
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) 
+        virCgroupItemFree(vm->def->cgroup[i]);
 
     /* now that we know it's stopped call the hook if present */
     if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
@@ -683,8 +679,8 @@ int virLXCProcessStop(virLXCDriverPtr driver,
                       virDomainObjPtr vm,
                       virDomainShutoffReason reason)
 {
-    virCgroupPtr group = NULL;
     int rc;
+    int i;
 
     VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d",
               vm->def->name, (int)vm->pid, (int)reason);
@@ -705,24 +701,26 @@ int virLXCProcessStop(virLXCDriverPtr driver,
         VIR_FREE(vm->def->seclabels[0]->imagelabel);
     }
 
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) == 0) {
-        rc = virCgroupKillPainfully(group);
-        if (rc < 0) {
-            virReportSystemError(-rc, "%s",
-                                 _("Failed to kill container PIDs"));
-            rc = -1;
-            goto cleanup;
-        }
-        if (rc == 1) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("Some container PIDs refused to die"));
-            rc = -1;
-            goto cleanup;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        if (vm->def->cgroup[i]) {
+            rc = virCgroupKillPainfully(vm->def->cgroup[i]);
+            if (rc < 0) {
+                virReportSystemError(-rc, "%s",
+                                     _("Failed to kill container PIDs"));
+                rc = -1;
+                goto cleanup;
+            }
+            if (rc == 1) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Some container PIDs refused to die"));
+                rc = -1;
+                goto cleanup;
+            }
+        } else {
+            /* If cgroup doesn't exist, the VM pids must have already
+             * died and so we're just cleaning up stale state
+             */
         }
-    } else {
-        /* If cgroup doesn't exist, the VM pids must have already
-         * died and so we're just cleaning up stale state
-         */
     }
 
     virLXCProcessCleanup(driver, vm, reason);
@@ -730,7 +728,6 @@ int virLXCProcessStop(virLXCDriverPtr driver,
     rc = 0;
 
 cleanup:
-    virCgroupFree(&group);
     return rc;
 }
 
@@ -924,20 +921,17 @@ int virLXCProcessStart(virConnectPtr conn,
         return -1;
     }
 
-    if (!virCgroupMounted(lxc_driver->cgroup,
-                          VIR_CGROUP_CONTROLLER_CPUACCT)) {
+    if (!virCgroupMounted(VIR_CGROUP_CONTROLLER_CPUACCT)) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Unable to find 'cpuacct' cgroups controller mount"));
         return -1;
     }
-    if (!virCgroupMounted(lxc_driver->cgroup,
-                          VIR_CGROUP_CONTROLLER_DEVICES)) {
+    if (!virCgroupMounted(VIR_CGROUP_CONTROLLER_DEVICES)) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Unable to find 'devices' cgroups controller mount"));
         return -1;
     }
-    if (!virCgroupMounted(lxc_driver->cgroup,
-                          VIR_CGROUP_CONTROLLER_MEMORY)) {
+    if (!virCgroupMounted(VIR_CGROUP_CONTROLLER_MEMORY)) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Unable to find 'memory' cgroups controller mount"));
         return -1;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 6527146..c409323 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -48,11 +48,9 @@ static const char *const defaultDeviceACL[] = {
 bool qemuCgroupControllerActive(virQEMUDriverPtr driver,
                                 int controller)
 {
-    if (driver->cgroup == NULL)
-        return false;
     if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
         return false;
-    if (!virCgroupMounted(driver->cgroup, controller))
+    if (driver->cgroup[controller] == NULL)
         return false;
     if (driver->cgroupControllers & (1 << controller))
         return true;
@@ -89,7 +87,7 @@ qemuSetupDiskPathAllow(virDomainDiskDefPtr disk,
 
 
 int qemuSetupDiskCgroup(virDomainObjPtr vm,
-                        virCgroupPtr cgroup,
+                        virCgroupItemPtr cgroup,
                         virDomainDiskDefPtr disk)
 {
     qemuCgroupData data = { vm, cgroup };
@@ -128,7 +126,7 @@ qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
 
 
 int qemuTeardownDiskCgroup(virDomainObjPtr vm,
-                           virCgroupPtr cgroup,
+                           virCgroupItemPtr cgroup,
                            virDomainDiskDefPtr disk)
 {
     qemuCgroupData data = { vm, cgroup };
@@ -192,7 +190,8 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
                     virDomainObjPtr vm,
                     virBitmapPtr nodemask)
 {
-    virCgroupPtr cgroup = NULL;
+    char *path;
+    virCgroupItemPtr cgroup = NULL;
     int rc;
     unsigned int i;
     const char *const *deviceACL =
@@ -200,17 +199,19 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
         (const char *const *)driver->cgroupDeviceACL :
         defaultDeviceACL;
 
-    if (driver->cgroup == NULL)
-        return 0; /* Not supported, so claim success */
-
-    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 1);
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("Unable to create cgroup for %s"),
-                             vm->def->name);
-        goto cleanup;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        vm->def->cgroup[i] = virCgroupItemNew(i, vm->def->name, driver->cgroup[i]);
+        /* XXX: This is a dirty hack to create the cgroup item path before
+         * any qemu processes bring up. The reason to do so is virCgroup creates
+         * cgroup item path as needed, and maintains the information. But if the
+         * path is created by a sub-process(see qemuProcessHook), we can't know it
+         * and virCgroup will behave incorrectly.
+         */
+        virCgroupItemPath(vm->def->cgroup[i], true, &path);
     }
 
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
         qemuCgroupData data = { vm, cgroup };
         rc = virCgroupDenyAllDevices(cgroup);
@@ -300,6 +301,8 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
         }
     }
 
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_BLKIO];
+
     if (vm->def->blkio.weight != 0) {
         if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
             rc = virCgroupSetBlkioWeight(cgroup, vm->def->blkio.weight);
@@ -339,6 +342,8 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
         }
     }
 
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
         unsigned long long hard_limit = vm->def->mem.hard_limit;
 
@@ -392,6 +397,8 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
         VIR_WARN("Could not autoset a RSS limit for domain %s", vm->def->name);
     }
 
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPU];
+
     if (vm->def->cputune.shares != 0) {
         if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
             rc = virCgroupSetCpuShares(cgroup, vm->def->cputune.shares);
@@ -407,6 +414,8 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
         }
     }
 
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUSET];
+
     if ((vm->def->numatune.memory.nodemask ||
          (vm->def->numatune.memory.placement_mode ==
           VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_AUTO)) &&
@@ -434,18 +443,13 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
         }
     }
 done:
-    virCgroupFree(&cgroup);
     return 0;
 
 cleanup:
-    if (cgroup) {
-        virCgroupRemove(cgroup);
-        virCgroupFree(&cgroup);
-    }
     return -1;
 }
 
-int qemuSetupCgroupVcpuBW(virCgroupPtr cgroup, unsigned long long period,
+int qemuSetupCgroupVcpuBW(virCgroupItemPtr cgroup, unsigned long long period,
                           long long quota)
 {
     int rc;
@@ -493,7 +497,7 @@ cleanup:
     return -1;
 }
 
-int qemuSetupCgroupVcpuPin(virCgroupPtr cgroup,
+int qemuSetupCgroupVcpuPin(virCgroupItemPtr cgroup,
                            virDomainVcpuPinDefPtr *vcpupin,
                            int nvcpupin,
                            int vcpuid)
@@ -509,7 +513,7 @@ int qemuSetupCgroupVcpuPin(virCgroupPtr cgroup,
     return -1;
 }
 
-int qemuSetupCgroupEmulatorPin(virCgroupPtr cgroup,
+int qemuSetupCgroupEmulatorPin(virCgroupItemPtr cgroup,
                                virBitmapPtr cpumask)
 {
     int rc = 0;
@@ -538,68 +542,48 @@ cleanup:
 
 int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr vm)
 {
-    virCgroupPtr cgroup = NULL;
-    virCgroupPtr cgroup_vcpu = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainDefPtr def = vm->def;
     int rc;
     unsigned int i, j;
     unsigned long long period = vm->def->cputune.period;
     long long quota = vm->def->cputune.quota;
-
-    if ((period || quota) &&
-        (!driver->cgroup ||
-         !qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU))) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("cgroup cpu is required for scheduler tuning"));
-        return -1;
-    }
-
-    /* We are trying to setup cgroups for CPU pinning, which can also be done
-     * with virProcessInfoSetAffinity, thus the lack of cgroups is not fatal
-     * here.
-     */
-    if (driver->cgroup == NULL)
-        return 0;
-
-    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("Unable to find cgroup for %s"),
-                             vm->def->name);
-        goto cleanup;
-    }
+    char *vcpuName = NULL;
 
     if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
         /* If we don't know VCPU<->PID mapping or all vcpu runs in the same
          * thread, we cannot control each vcpu.
          */
         VIR_WARN("Unable to get vcpus' pids.");
-        virCgroupFree(&cgroup);
         return 0;
     }
 
+    if (VIR_ALLOC_N(vm->def->vcpuCgroups, priv->nvcpupids) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
     for (i = 0; i < priv->nvcpupids; i++) {
-        rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 1);
-        if (rc < 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create vcpu cgroup for %s(vcpu:"
-                                   " %d)"),
-                                 vm->def->name, i);
+        if (virAsprintf(&vcpuName, "vcpu%d", i) < 0)
             goto cleanup;
-        }
 
-        /* move the thread for vcpu to sub dir */
-        rc = virCgroupAddTask(cgroup_vcpu, priv->vcpupids[i]);
-        if (rc < 0) {
-            virReportSystemError(-rc,
-                                 _("unable to add vcpu %d task %d to cgroup"),
-                                 i, priv->vcpupids[i]);
-            goto cleanup;
-        }
+        for (j = 0; j < VIR_CGROUP_CONTROLLER_LAST; j++)
+            vm->def->vcpuCgroups[i][j] = virCgroupItemNew(j,
+                                                          vcpuName,
+                                                          vm->def->cgroup[j]);
+
+        if ((period || quota) && vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPU]) {
+            rc = virCgroupItemAddTask(vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPU],
+                                      priv->vcpupids[i]);
+            if (rc < 0) {
+                virReportSystemError(-rc,
+                                     _("unable to add vcpu %d task %d to cgroup"),
+                                     i, priv->vcpupids[i]);
+                goto cleanup;
+            }
 
-        if (period || quota) {
-            if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
+            if (qemuSetupCgroupVcpuBW(vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPU],
+                                      period, quota) < 0)
                 goto cleanup;
         }
 
@@ -611,7 +595,16 @@ int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr vm)
                 if (def->cputune.vcpupin[j]->vcpuid != i)
                     continue;
 
-                if (qemuSetupCgroupVcpuPin(cgroup_vcpu,
+                rc = virCgroupItemAddTask(vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPUSET],
+                                          priv->vcpupids[i]);
+                if (rc < 0) {
+                    virReportSystemError(-rc,
+                                         _("unable to add vcpu %d task %d to cgroup"),
+                                         i, priv->vcpupids[i]);
+                    goto cleanup;
+                }
+
+                if (qemuSetupCgroupVcpuPin(vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPUSET],
                                            def->cputune.vcpupin,
                                            def->cputune.nvcpupin,
                                            i) < 0)
@@ -620,24 +613,17 @@ int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr vm)
                 break;
             }
         }
-
-        virCgroupFree(&cgroup_vcpu);
     }
 
-    virCgroupFree(&cgroup);
     return 0;
 
 cleanup:
-    if (cgroup_vcpu) {
-        virCgroupRemove(cgroup_vcpu);
-        virCgroupFree(&cgroup_vcpu);
-    }
-
-    if (cgroup) {
-        virCgroupRemove(cgroup);
-        virCgroupFree(&cgroup);
+    if (vm->def->vcpuCgroups) {
+        for (i = 0; i < priv->nvcpupids; i++) {
+            for (j = 0; j < VIR_CGROUP_CONTROLLER_LAST; j++)
+                virCgroupItemFree(vm->def->vcpuCgroups[i][j]);
+        }
     }
-
     return -1;
 }
 
@@ -647,52 +633,11 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
 {
     virBitmapPtr cpumask = NULL;
     virBitmapPtr cpumap = NULL;
-    virCgroupPtr cgroup = NULL;
-    virCgroupPtr cgroup_emulator = NULL;
     virDomainDefPtr def = vm->def;
     unsigned long long period = vm->def->cputune.emulator_period;
     long long quota = vm->def->cputune.emulator_quota;
-    int rc, i;
-
-    if ((period || quota) &&
-        (!driver->cgroup ||
-         !qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU))) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("cgroup cpu is required for scheduler tuning"));
-        return -1;
-    }
-
-    if (driver->cgroup == NULL)
-        return 0; /* Not supported, so claim success */
-
-    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("Unable to find cgroup for %s"),
-                             vm->def->name);
-        goto cleanup;
-    }
-
-    rc = virCgroupForEmulator(cgroup, &cgroup_emulator, 1);
-    if (rc < 0) {
-        virReportSystemError(-rc,
-                             _("Unable to create emulator cgroup for %s"),
-                             vm->def->name);
-        goto cleanup;
-    }
-
-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
-        if (!qemuCgroupControllerActive(driver, i))
-            continue;
-        rc = virCgroupMoveTask(cgroup, cgroup_emulator, i);
-        if (rc < 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to move tasks from domain cgroup to "
-                                   "emulator cgroup in controller %d for %s"),
-                                 i, vm->def->name);
-            goto cleanup;
-        }
-    }
+    int rc = -1;
+    int i;
 
     if (def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
         if (!(cpumap = qemuPrepareCpumap(driver, nodemask)))
@@ -704,97 +649,29 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
         cpumask = def->cpumask;
     }
 
-    if (cpumask) {
-        if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
-            rc = qemuSetupCgroupEmulatorPin(cgroup_emulator, cpumask);
-            if (rc < 0)
-                goto cleanup;
-        }
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        def->emulatorCgroup[i] = virCgroupItemNew(i, "emulator", def->cgroup[i]);
+    }
+
+    if (cpumask && def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPUSET]) {
+        rc = qemuSetupCgroupEmulatorPin(def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPUSET],
+                                        cpumask);
+        if (rc < 0)
+            goto cleanup;
         cpumask = NULL; /* sanity */
     }
 
-    if (period || quota) {
-        if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
-            if ((rc = qemuSetupCgroupVcpuBW(cgroup_emulator, period,
-                                            quota)) < 0)
-                goto cleanup;
-        }
+    if ((period || quota) && def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPU]) {
+        if ((rc = qemuSetupCgroupVcpuBW(def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPU],
+                                        period, quota)) < 0)
+            goto cleanup;
     }
 
-    virCgroupFree(&cgroup_emulator);
-    virCgroupFree(&cgroup);
-    virBitmapFree(cpumap);
     return 0;
 
 cleanup:
-    virBitmapFree(cpumap);
-
-    if (cgroup_emulator) {
-        virCgroupRemove(cgroup_emulator);
-        virCgroupFree(&cgroup_emulator);
-    }
-
-    if (cgroup) {
-        virCgroupRemove(cgroup);
-        virCgroupFree(&cgroup);
-    }
-
-    return rc;
-}
-
-int qemuRemoveCgroup(virQEMUDriverPtr driver,
-                     virDomainObjPtr vm,
-                     int quiet)
-{
-    virCgroupPtr cgroup;
-    int rc;
-
-    if (driver->cgroup == NULL)
-        return 0; /* Not supported, so claim success */
-
-    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
-    if (rc != 0) {
-        if (!quiet)
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unable to find cgroup for %s"),
-                           vm->def->name);
-        return rc;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        virCgroupItemFree(def->emulatorCgroup[i]);
     }
-
-    rc = virCgroupRemove(cgroup);
-    virCgroupFree(&cgroup);
     return rc;
 }
-
-int qemuAddToCgroup(virQEMUDriverPtr driver,
-                    virDomainDefPtr def)
-{
-    virCgroupPtr cgroup = NULL;
-    int ret = -1;
-    int rc;
-
-    if (driver->cgroup == NULL)
-        return 0; /* Not supported, so claim success */
-
-    rc = virCgroupForDomain(driver->cgroup, def->name, &cgroup, 0);
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("unable to find cgroup for domain %s"),
-                             def->name);
-        goto cleanup;
-    }
-
-    rc = virCgroupAddTask(cgroup, getpid());
-    if (rc != 0) {
-        virReportSystemError(-rc,
-                             _("unable to add domain %s task %d to cgroup"),
-                             def->name, getpid());
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    virCgroupFree(&cgroup);
-    return ret;
-}
diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
index 75ef514..6444c2a 100644
--- a/src/qemu/qemu_cgroup.h
+++ b/src/qemu/qemu_cgroup.h
@@ -30,17 +30,17 @@
 
 struct _qemuCgroupData {
     virDomainObjPtr vm;
-    virCgroupPtr cgroup;
+    virCgroupItemPtr cgroup;
 };
 typedef struct _qemuCgroupData qemuCgroupData;
 
 bool qemuCgroupControllerActive(virQEMUDriverPtr driver,
                                 int controller);
 int qemuSetupDiskCgroup(virDomainObjPtr vm,
-                        virCgroupPtr cgroup,
+                        virCgroupItemPtr cgroup,
                         virDomainDiskDefPtr disk);
 int qemuTeardownDiskCgroup(virDomainObjPtr vm,
-                           virCgroupPtr cgroup,
+                           virCgroupItemPtr cgroup,
                            virDomainDiskDefPtr disk);
 int qemuSetupHostUsbDeviceCgroup(usbDevice *dev,
                                  const char *path,
@@ -48,22 +48,17 @@ int qemuSetupHostUsbDeviceCgroup(usbDevice *dev,
 int qemuSetupCgroup(virQEMUDriverPtr driver,
                     virDomainObjPtr vm,
                     virBitmapPtr nodemask);
-int qemuSetupCgroupVcpuBW(virCgroupPtr cgroup,
+int qemuSetupCgroupVcpuBW(virCgroupItemPtr cgroup,
                           unsigned long long period,
                           long long quota);
-int qemuSetupCgroupVcpuPin(virCgroupPtr cgroup,
+int qemuSetupCgroupVcpuPin(virCgroupItemPtr cgroup,
                            virDomainVcpuPinDefPtr *vcpupin,
                            int nvcpupin,
                            int vcpuid);
-int qemuSetupCgroupEmulatorPin(virCgroupPtr cgroup, virBitmapPtr cpumask);
+int qemuSetupCgroupEmulatorPin(virCgroupItemPtr cgroup, virBitmapPtr cpumask);
 int qemuSetupCgroupForVcpu(virQEMUDriverPtr driver, virDomainObjPtr vm);
 int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
                                virBitmapPtr nodemask);
-int qemuRemoveCgroup(virQEMUDriverPtr driver,
-                     virDomainObjPtr vm,
-                     int quiet);
-int qemuAddToCgroup(virQEMUDriverPtr driver,
-                    virDomainDefPtr def);
 
 #endif /* __QEMU_CGROUP_H__ */
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 965eff7..9162914 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -69,7 +69,7 @@ struct _virQEMUDriver {
     unsigned int qemuVersion;
     int nextvmid;
 
-    virCgroupPtr cgroup;
+    virCgroupItemPtr cgroup[VIR_CGROUP_CONTROLLER_LAST];
     int cgroupControllers;
     char **cgroupDeviceACL;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 39175f4..d795abe 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -650,11 +650,11 @@ qemuStartup(bool privileged,
 {
     char *base;
     char *driverConf = NULL;
-    int rc;
     virConnectPtr conn = NULL;
     char ebuf[1024];
     char *membase = NULL;
     char *mempath = NULL;
+    int i;
 
     if (VIR_ALLOC(qemu_driver) < 0)
         return -1;
@@ -795,17 +795,16 @@ qemuStartup(bool privileged,
         virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) < 0)
         goto out_of_memory;
 
-    rc = virCgroupForDriver("qemu", &qemu_driver->cgroup, privileged, 1);
-    if (rc < 0) {
-        VIR_INFO("Unable to create cgroup for driver: %s",
-                 virStrerror(-rc, ebuf, sizeof(ebuf)));
-    }
-
     if (qemuLoadDriverConfig(qemu_driver, driverConf) < 0) {
         goto error;
     }
     VIR_FREE(driverConf);
 
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        qemu_driver->cgroup[i] = virCgroupItemNew(i, "qemu",
+                                                  virCgroupGetAppRoot(i, privileged));
+    }
+
     /* Allocate bitmap for remote display port reservations. We cannot
      * do this before the config is loaded properly, since the port
      * numbers are configurable now */
@@ -1146,10 +1145,14 @@ qemuShutdown(void) {
     /* Free domain callback list */
     virDomainEventStateFree(qemu_driver->domainEventState);
 
-    virCgroupFree(&qemu_driver->cgroup);
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
+        virCgroupItemFree(qemu_driver->cgroup[i]);
 
     virLockManagerPluginUnref(qemu_driver->lockManager);
 
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
+        virCgroupItemFree(qemu_driver->cgroup[i]);
+
     qemuDriverUnlock(qemu_driver);
     virMutexDestroy(&qemu_driver->lock);
     virThreadPoolFree(qemu_driver->workerPool);
@@ -3652,7 +3655,7 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
     int ncpupids;
     virCgroupPtr cgroup = NULL;
     virCgroupPtr cgroup_vcpu = NULL;
-    bool cgroup_available = false;
+    //bool cgroup_available = false;
 
     qemuDomainObjEnterMonitor(driver, vm);
 
@@ -3697,6 +3700,7 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
+#if 0 /* XXX */
     if (ncpupids != vcpus) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("got wrong number of vCPU pids from QEMU monitor. "
@@ -3808,6 +3812,7 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
             }
         }
     }
+#endif
 
     priv->nvcpupids = ncpupids;
     VIR_FREE(priv->vcpupids);
@@ -4014,15 +4019,13 @@ qemuDomainPinVcpuFlags(virDomainPtr dom,
         }
 
         /* Configure the corresponding cpuset cgroup before set affinity. */
-        if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
-            if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup_dom, 0) == 0 &&
-                virCgroupForVcpu(cgroup_dom, vcpu, &cgroup_vcpu, 0) == 0 &&
-                qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) < 0) {
-                virReportError(VIR_ERR_OPERATION_INVALID,
-                               _("failed to set cpuset.cpus in cgroup"
-                                 " for vcpu %d"), vcpu);
-                goto cleanup;
-            }
+        if (vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUSET] &&
+            qemuSetupCgroupVcpuPin(vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUSET],
+                                   newVcpuPin, newVcpuPinNum, vcpu) < 0) {
+            virReportError(VIR_ERR_OPERATION_INVALID,
+                           _("failed to set cpuset.cpus in cgroup"
+                             " for vcpu %d"), vcpu);
+            goto cleanup;
         } else {
             if (virProcessSetAffinity(priv->vcpupids[vcpu], pcpumap) < 0) {
                 virReportError(VIR_ERR_SYSTEM_ERROR,
@@ -4255,23 +4258,13 @@ qemuDomainPinEmulator(virDomainPtr dom,
                 goto cleanup;
             }
 
-            if (qemuCgroupControllerActive(driver,
-                                           VIR_CGROUP_CONTROLLER_CPUSET)) {
-                /*
-                 * Configure the corresponding cpuset cgroup.
-                 * If no cgroup for domain or hypervisor exists, do nothing.
-                 */
-                if (virCgroupForDomain(driver->cgroup, vm->def->name,
-                                       &cgroup_dom, 0) == 0) {
-                    if (virCgroupForEmulator(cgroup_dom, &cgroup_emulator, 0) == 0) {
-                        if (qemuSetupCgroupEmulatorPin(cgroup_emulator,
-                                                       newVcpuPin[0]->cpumask) < 0) {
-                            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                                           _("failed to set cpuset.cpus in cgroup"
-                                             " for emulator threads"));
-                            goto cleanup;
-                        }
-                    }
+            if (vm->def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPUSET]) {
+                if (qemuSetupCgroupEmulatorPin(vm->def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPUSET],
+                                               newVcpuPin[0]->cpumask) < 0) {
+                    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                                   _("failed to set cpuset.cpus in cgroup"
+                                     " for emulator threads"));
+                    goto cleanup;
                 }
             } else {
                 if (virProcessSetAffinity(pid, pcpumap) < 0) {
@@ -5804,7 +5797,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
                                virDomainDeviceDefPtr dev)
 {
     virDomainDiskDefPtr disk = dev->data.disk;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
     int ret = -1;
 
     if (disk->driverName != NULL && !STREQ(disk->driverName, "qemu")) {
@@ -5822,16 +5815,10 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
     if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
         goto end;
 
-    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unable to find cgroup for %s"),
-                           vm->def->name);
-            goto end;
-        }
+    if (cgroup)
         if (qemuSetupDiskCgroup(vm, cgroup, disk) < 0)
             goto end;
-    }
+
     switch (disk->device)  {
     case VIR_DOMAIN_DISK_DEVICE_CDROM:
     case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
@@ -5882,8 +5869,6 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
     }
 
 end:
-    if (cgroup)
-        virCgroupFree(&cgroup);
     return ret;
 }
 
@@ -6067,23 +6052,15 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
                               bool force)
 {
     virDomainDiskDefPtr disk = dev->data.disk;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
     int ret = -1;
 
     if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
         goto end;
 
-    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        if (virCgroupForDomain(driver->cgroup,
-                               vm->def->name, &cgroup, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unable to find cgroup for %s"),
-                           vm->def->name);
-            goto end;
-        }
+    if (cgroup)
         if (qemuSetupDiskCgroup(vm, cgroup, disk) < 0)
             goto end;
-    }
 
     switch (disk->device) {
     case VIR_DOMAIN_DISK_DEVICE_CDROM:
@@ -6105,8 +6082,6 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
                       NULLSTR(disk->src));
     }
 end:
-    if (cgroup)
-        virCgroupFree(&cgroup);
     return ret;
 }
 
@@ -6693,39 +6668,6 @@ cleanup:
 }
 
 
-/*
- * check whether the host supports CFS bandwidth
- *
- * Return 1 when CFS bandwidth is supported, 0 when CFS bandwidth is not
- * supported, -1 on error.
- */
-static int qemuGetCpuBWStatus(virCgroupPtr cgroup)
-{
-    char *cfs_period_path = NULL;
-    int ret = -1;
-
-    if (!cgroup)
-        return 0;
-
-    if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
-                                  "cpu.cfs_period_us", &cfs_period_path) < 0) {
-        VIR_INFO("cannot get the path of cgroup CPU controller");
-        ret = 0;
-        goto cleanup;
-    }
-
-    if (access(cfs_period_path, F_OK) < 0) {
-        ret = 0;
-    } else {
-        ret = 1;
-    }
-
-cleanup:
-    VIR_FREE(cfs_period_path);
-    return ret;
-}
-
-
 static char *qemuGetSchedulerType(virDomainPtr dom,
                                   int *nparams)
 {
@@ -6741,10 +6683,10 @@ static char *qemuGetSchedulerType(virDomainPtr dom,
     }
 
     if (nparams) {
-        rc = qemuGetCpuBWStatus(driver->cgroup);
+        rc = virCgroupItemKeyPath(driver->cgroup[VIR_CGROUP_CONTROLLER_CPU],
+                                  "cpu.cfs_period_us",
+                                  NULL);
         if (rc < 0)
-            goto cleanup;
-        else if (rc == 0)
             *nparams = 1;
         else
             *nparams = 5;
@@ -6895,7 +6837,7 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef = NULL;
     int ret = -1;
@@ -6923,23 +6865,14 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
                                         &persistentDef) < 0)
         goto cleanup;
 
+    ret = 0;
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
-            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                           _("blkio cgroup isn't mounted"));
-            goto cleanup;
-        }
-
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot find cgroup for domain %s"),
-                           vm->def->name);
+        group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_BLKIO];
+        if (!group) {
+            ret = -1;
             goto cleanup;
         }
-    }
 
-    ret = 0;
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
         for (i = 0; i < nparams; i++) {
             int rc;
             virTypedParameterPtr param = &params[i];
@@ -7033,7 +6966,6 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
     }
 
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -7048,7 +6980,7 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i, j;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef = NULL;
     unsigned int val;
@@ -7084,21 +7016,12 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
                                         &persistentDef) < 0)
         goto cleanup;
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
-            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                           _("blkio cgroup isn't mounted"));
-            goto cleanup;
-        }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_BLKIO];
 
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot find cgroup for domain %s"), vm->def->name);
+    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+        if (!group)
             goto cleanup;
-        }
-    }
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
         for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
             virTypedParameterPtr param = &params[i];
             val = 0;
@@ -7218,8 +7141,6 @@ qemuDomainGetBlkioParameters(virDomainPtr dom,
     ret = 0;
 
 cleanup:
-    if (group)
-        virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -7235,7 +7156,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i;
     virDomainDefPtr persistentDef = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virTypedParameterPtr hard_limit = NULL;
     virTypedParameterPtr swap_hard_limit = NULL;
@@ -7273,19 +7194,9 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
                                         &persistentDef) < 0)
         goto cleanup;
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
-            virReportError(VIR_ERR_OPERATION_INVALID,
-                           "%s", _("cgroup memory controller is not mounted"));
-            goto cleanup;
-        }
-
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot find cgroup for domain %s"), vm->def->name);
-            goto cleanup;
-        }
-    }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+    if (!group)
+        goto cleanup;
 
     for (i = 0; i < nparams; i++) {
         if (STREQ(params[i].field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
@@ -7388,7 +7299,6 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
     }
 
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -7403,7 +7313,7 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef = NULL;
     int ret = -1;
@@ -7430,19 +7340,9 @@ qemuDomainGetMemoryParameters(virDomainPtr dom,
                                         &persistentDef) < 0)
         goto cleanup;
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
-            virReportError(VIR_ERR_OPERATION_INVALID,
-                           "%s", _("cgroup memory controller is not mounted"));
-            goto cleanup;
-        }
-
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot find cgroup for domain %s"), vm->def->name);
-            goto cleanup;
-        }
-    }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+    if (!group)
+        goto cleanup;
 
     if ((*nparams) == 0) {
         /* Current number of memory parameters supported by cgroups */
@@ -7547,8 +7447,6 @@ out:
     ret = 0;
 
 cleanup:
-    if (group)
-        virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -7564,7 +7462,7 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i;
     virDomainDefPtr persistentDef = NULL;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     int ret = -1;
 
@@ -7593,18 +7491,9 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
         goto cleanup;
 
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
-            virReportError(VIR_ERR_OPERATION_INVALID,
-                           "%s", _("cgroup cpuset controller is not mounted"));
+        group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUSET];
+        if (!group)
             goto cleanup;
-        }
-
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot find cgroup for domain %s"),
-                           vm->def->name);
-            goto cleanup;
-        }
     }
 
     ret = 0;
@@ -7697,7 +7586,6 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
     }
 
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -7712,7 +7600,7 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr persistentDef = NULL;
     char *nodeset = NULL;
@@ -7749,18 +7637,9 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
     }
 
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
-            virReportError(VIR_ERR_OPERATION_INVALID,
-                           "%s", _("cgroup memory controller is not mounted"));
+        group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_MEMORY];
+        if (!group)
             goto cleanup;
-        }
-
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(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++) {
@@ -7810,7 +7689,6 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
 
 cleanup:
     VIR_FREE(nodeset);
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -7818,13 +7696,13 @@ cleanup:
 }
 
 static int
-qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
-                   unsigned long long period, long long quota)
+qemuSetVcpusBWLive(virDomainObjPtr vm,
+                   unsigned long long period,
+                   long long quota)
 {
     int i;
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virCgroupPtr cgroup_vcpu = NULL;
-    int rc;
+    virCgroupItemPtr cgroup = NULL;
 
     if (period == 0 && quota == 0)
         return 0;
@@ -7835,36 +7713,30 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
      */
     if (priv->nvcpupids != 0 && priv->vcpupids[0] != vm->pid) {
         for (i = 0; i < priv->nvcpupids; i++) {
-            rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 0);
-            if (rc < 0) {
-                virReportSystemError(-rc,
-                                     _("Unable to find vcpu cgroup for %s(vcpu:"
-                                       " %d)"),
-                                     vm->def->name, i);
-                goto cleanup;
-            }
+            if (vm->def->vcpuCgroups &&
+                vm->def->vcpuCgroups[i])
+                cgroup = vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPU];
 
-            if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
-                goto cleanup;
+            if (!cgroup)
+               goto cleanup;
 
-            virCgroupFree(&cgroup_vcpu);
+            if (qemuSetupCgroupVcpuBW(cgroup, period, quota) < 0)
+                goto cleanup;
         }
     }
 
     return 0;
 
 cleanup:
-    virCgroupFree(&cgroup_vcpu);
     return -1;
 }
 
 static int
-qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
+qemuSetEmulatorBandwidthLive(virDomainObjPtr vm,
                              unsigned long long period, long long quota)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virCgroupPtr cgroup_emulator = NULL;
-    int rc;
+    virCgroupItemPtr cgroup = vm->def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPU];
 
     if (period == 0 && quota == 0)
         return 0;
@@ -7873,22 +7745,15 @@ qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
         return 0;
     }
 
-    rc = virCgroupForEmulator(cgroup, &cgroup_emulator, 0);
-    if (rc < 0) {
-        virReportSystemError(-rc,
-                             _("Unable to find emulator cgroup for %s"),
-                             vm->def->name);
+    if (!cgroup)
         goto cleanup;
-    }
 
-    if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
+    if (qemuSetupCgroupVcpuBW(cgroup, period, quota) < 0)
         goto cleanup;
 
-    virCgroupFree(&cgroup_emulator);
     return 0;
 
 cleanup:
-    virCgroupFree(&cgroup_emulator);
     return -1;
 }
 
@@ -7909,7 +7774,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     int i;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     virDomainDefPtr vmdef = NULL;
     unsigned long long value_ul;
@@ -7954,18 +7819,12 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
             goto cleanup;
     }
 
-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
-            virReportError(VIR_ERR_OPERATION_INVALID,
-                           "%s", _("cgroup CPU controller is not mounted"));
-            goto cleanup;
-        }
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot find cgroup for domain %s"),
-                           vm->def->name);
-            goto cleanup;
-        }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPU];
+    if ((flags & VIR_DOMAIN_AFFECT_LIVE) && !group) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("cannot find cgroup for domain %s"),
+                       vm->def->name);
+        goto cleanup;
     }
 
     for (i = 0; i < nparams; i++) {
@@ -7991,7 +7850,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
                               QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
 
             if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
-                if ((rc = qemuSetVcpusBWLive(vm, group, value_ul, 0)))
+                if ((rc = qemuSetVcpusBWLive(vm, value_ul, 0)))
                     goto cleanup;
 
                 vm->def->cputune.period = value_ul;
@@ -8005,7 +7864,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
                               QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
 
             if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
-                if ((rc = qemuSetVcpusBWLive(vm, group, 0, value_l)))
+                if ((rc = qemuSetVcpusBWLive(vm, 0, value_l)))
                     goto cleanup;
 
                 vm->def->cputune.quota = value_l;
@@ -8019,7 +7878,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
                               QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
 
             if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
-                if ((rc = qemuSetEmulatorBandwidthLive(vm, group, value_ul, 0)))
+                if ((rc = qemuSetEmulatorBandwidthLive(vm, value_ul, 0)))
                     goto cleanup;
 
                 vm->def->cputune.emulator_period = value_ul;
@@ -8033,7 +7892,7 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
                               QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
 
             if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
-                if ((rc = qemuSetEmulatorBandwidthLive(vm, group, 0, value_l)))
+                if ((rc = qemuSetEmulatorBandwidthLive(vm, 0, value_l)))
                     goto cleanup;
 
                 vm->def->cputune.emulator_quota = value_l;
@@ -8061,7 +7920,6 @@ qemuSetSchedulerParametersFlags(virDomainPtr dom,
 
 cleanup:
     virDomainDefFree(vmdef);
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -8081,7 +7939,7 @@ qemuSetSchedulerParameters(virDomainPtr dom,
 }
 
 static int
-qemuGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
+qemuGetVcpuBWLive(virCgroupItemPtr cgroup, unsigned long long *period,
                   long long *quota)
 {
     int rc;
@@ -8104,10 +7962,10 @@ qemuGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
 }
 
 static int
-qemuGetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
+qemuGetVcpusBWLive(virDomainObjPtr vm,
                    unsigned long long *period, long long *quota)
 {
-    virCgroupPtr cgroup_vcpu = NULL;
+    virCgroupItemPtr cgroup = NULL;
     qemuDomainObjPrivatePtr priv = NULL;
     int rc;
     int ret = -1;
@@ -8115,41 +7973,30 @@ qemuGetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
     priv = vm->privateData;
     if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
         /* We do not create sub dir for each vcpu */
-        rc = qemuGetVcpuBWLive(cgroup, period, quota);
-        if (rc < 0)
-            goto cleanup;
-
-        if (*quota > 0)
-            *quota /= vm->def->vcpus;
-        goto out;
-    }
-
-    /* get period and quota for vcpu0 */
-    rc = virCgroupForVcpu(cgroup, 0, &cgroup_vcpu, 0);
-    if (!cgroup_vcpu) {
-        virReportSystemError(-rc,
-                             _("Unable to find vcpu cgroup for %s(vcpu: 0)"),
-                             vm->def->name);
-        goto cleanup;
+        cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPU];
+    } else {
+        /* get period and quota for vcpu0 */
+        cgroup = vm->def->vcpuCgroups[0][VIR_CGROUP_CONTROLLER_CPU];
     }
 
-    rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
+    rc = qemuGetVcpuBWLive(cgroup, period, quota);
     if (rc < 0)
         goto cleanup;
 
-out:
+    if (*quota > 0)
+        *quota /= vm->def->vcpus;
+
     ret = 0;
 
 cleanup:
-    virCgroupFree(&cgroup_vcpu);
     return ret;
 }
 
 static int
-qemuGetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
+qemuGetEmulatorBandwidthLive(virDomainObjPtr vm,
                              unsigned long long *period, long long *quota)
 {
-    virCgroupPtr cgroup_emulator = NULL;
+    virCgroupItemPtr cgroup = NULL;
     qemuDomainObjPrivatePtr priv = NULL;
     int rc;
     int ret = -1;
@@ -8162,23 +8009,23 @@ qemuGetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
         return 0;
     }
 
+    cgroup = vm->def->emulatorCgroup[VIR_CGROUP_CONTROLLER_CPU];
+
     /* get period and quota for emulator */
-    rc = virCgroupForEmulator(cgroup, &cgroup_emulator, 0);
-    if (!cgroup_emulator) {
-        virReportSystemError(-rc,
+    if (!cgroup) {
+        virReportSystemError(VIR_ERR_INTERNAL_ERROR,
                              _("Unable to find emulator cgroup for %s"),
                              vm->def->name);
         goto cleanup;
     }
 
-    rc = qemuGetVcpuBWLive(cgroup_emulator, period, quota);
+    rc = qemuGetVcpuBWLive(cgroup, period, quota);
     if (rc < 0)
         goto cleanup;
 
     ret = 0;
 
 cleanup:
-    virCgroupFree(&cgroup_emulator);
     return ret;
 }
 
@@ -8189,7 +8036,7 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
                                 unsigned int flags)
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     unsigned long long shares;
     unsigned long long period;
@@ -8212,10 +8059,12 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
     flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
 
     if (*nparams > 1) {
-        rc = qemuGetCpuBWStatus(driver->cgroup);
+        rc = virCgroupItemKeyPath(driver->cgroup[VIR_CGROUP_CONTROLLER_CPU],
+                                  "cpu.cfs_period_us",
+                                  NULL);
         if (rc < 0)
-            goto cleanup;
-        cpu_bw_status = !!rc;
+            cpu_bw_status = 0;
+        cpu_bw_status = 1;
     }
 
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -8241,13 +8090,8 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
         goto out;
     }
 
-    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       "%s", _("cgroup CPU controller is not mounted"));
-        goto cleanup;
-    }
-
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPU];
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -8261,13 +8105,13 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
     }
 
     if (*nparams > 1 && cpu_bw_status) {
-        rc = qemuGetVcpusBWLive(vm, group, &period, &quota);
+        rc = qemuGetVcpusBWLive(vm, &period, &quota);
         if (rc != 0)
             goto cleanup;
     }
 
     if (*nparams > 3 && cpu_bw_status) {
-        rc = qemuGetEmulatorBandwidthLive(vm, group, &emulator_period,
+        rc = qemuGetEmulatorBandwidthLive(vm, &emulator_period,
                                           &emulator_quota);
         if (rc != 0)
             goto cleanup;
@@ -8320,7 +8164,6 @@ out:
     ret = 0;
 
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
@@ -10373,7 +10216,6 @@ typedef enum {
 static int
 qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
                                   virDomainObjPtr vm,
-                                  virCgroupPtr cgroup,
                                   virDomainDiskDefPtr disk,
                                   const char *file,
                                   qemuDomainDiskChainMode mode)
@@ -10386,6 +10228,7 @@ qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
     virStorageFileMetadataPtr origchain = disk->backingChain;
     bool origreadonly = disk->readonly;
     int ret = -1;
+    virCgroupItemPtr cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
 
     disk->src = (char *) file; /* casting away const is safe here */
     disk->format = VIR_STORAGE_FILE_RAW;
@@ -10840,7 +10683,6 @@ cleanup:
 static int
 qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
                                          virDomainObjPtr vm,
-                                         virCgroupPtr cgroup,
                                          virDomainSnapshotDiskDefPtr snap,
                                          virDomainDiskDefPtr disk,
                                          virDomainDiskDefPtr persistDisk,
@@ -10890,9 +10732,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     virStorageFileFreeMetadata(disk->backingChain);
     disk->backingChain = NULL;
 
-    if (qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, source,
+    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
                                           VIR_DISK_CHAIN_READ_WRITE) < 0) {
-        qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, source,
+        qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
                                           VIR_DISK_CHAIN_NO_ACCESS);
         goto cleanup;
     }
@@ -10934,7 +10776,6 @@ cleanup:
 static void
 qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
                                        virDomainObjPtr vm,
-                                       virCgroupPtr cgroup,
                                        virDomainDiskDefPtr origdisk,
                                        virDomainDiskDefPtr disk,
                                        virDomainDiskDefPtr persistDisk,
@@ -10951,7 +10792,7 @@ qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
-    qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, origdisk->src,
+    qemuDomainPrepareDiskChainElement(driver, vm, disk, origdisk->src,
                                       VIR_DISK_CHAIN_NO_ACCESS);
     if (need_unlink && stat(disk->src, &st) == 0 &&
         S_ISREG(st.st_mode) && unlink(disk->src) < 0)
@@ -10988,7 +10829,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     int i;
     bool persist = false;
     bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
-    virCgroupPtr cgroup = NULL;
 
     if (!virDomainObjIsActive(vm)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
@@ -10997,7 +10837,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     }
 
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
-        virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) {
+        !vm->def->cgroup) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unable to find cgroup for %s"),
                        vm->def->name);
@@ -11040,7 +10880,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
             }
         }
 
-        ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm, cgroup,
+        ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
                                                        &snap->def->disks[i],
                                                        vm->def->disks[i],
                                                        persistDisk, actions,
@@ -11069,7 +10909,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
                         persistDisk = vm->newDef->disks[indx];
                 }
 
-                qemuDomainSnapshotUndoSingleDiskActive(driver, vm, cgroup,
+                qemuDomainSnapshotUndoSingleDiskActive(driver, vm,
                                                        snap->def->dom->disks[i],
                                                        vm->def->disks[i],
                                                        persistDisk,
@@ -11080,8 +10920,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
 cleanup:
-    virCgroupFree(&cgroup);
-
     if (ret == 0 || !qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION)) {
         if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0 ||
             (persist && virDomainSaveConfig(driver->configDir, vm->newDef) < 0))
@@ -12769,7 +12607,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
     virDomainBlockJobInfo info;
     const char *format = virStorageFileFormatTypeToString(disk->mirrorFormat);
     bool resume = false;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
     char *oldsrc = NULL;
     int oldformat;
     virStorageFileMetadataPtr oldchain = NULL;
@@ -12830,7 +12668,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
      * we know for sure that there is a backing chain.  */
     if (disk->mirrorFormat && disk->mirrorFormat != VIR_STORAGE_FILE_RAW &&
         qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
-        virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) < 0) {
+        !cgroup < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unable to find cgroup for %s"),
                        vm->def->name);
@@ -12895,8 +12733,6 @@ qemuDomainBlockPivot(virConnectPtr conn,
     disk->mirroring = false;
 
 cleanup:
-    if (cgroup)
-        virCgroupFree(&cgroup);
     if (resume && virDomainObjIsActive(vm) &&
         qemuProcessStartCPUs(driver, vm, conn,
                              VIR_DOMAIN_RUNNING_UNPAUSED,
@@ -13127,7 +12963,7 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
     struct stat st;
     bool need_unlink = false;
     char *mirror = NULL;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = NULL;
 
     /* Preliminaries: find the disk we are editing, sanity checks */
     virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
@@ -13142,8 +12978,10 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
                        _("domain is not running"));
         goto cleanup;
     }
+
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
-        virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) < 0) {
+        !cgroup) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unable to find cgroup for %s"),
                        vm->def->name);
@@ -13250,9 +13088,9 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
         goto endjob;
     }
 
-    if (qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, dest,
+    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
                                           VIR_DISK_CHAIN_READ_WRITE) < 0) {
-        qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, dest,
+        qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
                                           VIR_DISK_CHAIN_NO_ACCESS);
         goto endjob;
     }
@@ -13264,7 +13102,7 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
     virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0);
     qemuDomainObjExitMonitor(driver, vm);
     if (ret < 0) {
-        qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, dest,
+        qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
                                           VIR_DISK_CHAIN_NO_ACCESS);
         goto endjob;
     }
@@ -13286,8 +13124,6 @@ endjob:
     }
 
 cleanup:
-    if (cgroup)
-        virCgroupFree(&cgroup);
     VIR_FREE(device);
     if (vm)
         virDomainObjUnlock(vm);
@@ -13342,7 +13178,7 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
     virStorageFileMetadataPtr top_meta = NULL;
     const char *top_parent = NULL;
     const char *base_canon = NULL;
-    virCgroupPtr cgroup = NULL;
+    virCgroupItemPtr cgroup = NULL;
     bool clean_access = false;
 
     virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
@@ -13419,6 +13255,8 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
         goto endjob;
     }
 
+    cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
+
     /* For the commit to succeed, we must allow qemu to open both the
      * 'base' image and the parent of 'top' as read/write; 'top' might
      * not have a parent, or might already be read-write.  XXX It
@@ -13427,17 +13265,17 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
      * operation succeeds, but doing that requires tracking the
      * operation in XML across libvirtd restarts.  */
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES) &&
-        virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) < 0) {
+        !cgroup) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unable to find cgroup for %s"),
                        vm->def->name);
         goto endjob;
     }
     clean_access = true;
-    if (qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, base_canon,
+    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, base_canon,
                                           VIR_DISK_CHAIN_READ_WRITE) < 0 ||
         (top_parent && top_parent != disk->src &&
-         qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk,
+         qemuDomainPrepareDiskChainElement(driver, vm, disk,
                                            top_parent,
                                            VIR_DISK_CHAIN_READ_WRITE) < 0))
         goto endjob;
@@ -13451,15 +13289,13 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
 endjob:
     if (ret < 0 && clean_access) {
         /* Revert access to read-only, if possible.  */
-        qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk, base_canon,
+        qemuDomainPrepareDiskChainElement(driver, vm, disk, base_canon,
                                           VIR_DISK_CHAIN_READ_ONLY);
         if (top_parent && top_parent != disk->src)
-            qemuDomainPrepareDiskChainElement(driver, vm, cgroup, disk,
+            qemuDomainPrepareDiskChainElement(driver, vm, disk,
                                               top_parent,
                                               VIR_DISK_CHAIN_READ_ONLY);
     }
-    if (cgroup)
-        virCgroupFree(&cgroup);
     if (qemuDomainObjEndJob(driver, vm) == 0) {
         vm = NULL;
         goto cleanup;
@@ -14081,7 +13917,7 @@ cleanup:
 
 /* qemuDomainGetCPUStats() with start_cpu == -1 */
 static int
-qemuDomainGetTotalcpuStats(virCgroupPtr group,
+qemuDomainGetTotalcpuStats(virCgroupItemPtr group,
                            virTypedParameterPtr params,
                            int nparams)
 {
@@ -14143,28 +13979,24 @@ qemuDomainGetTotalcpuStats(virCgroupPtr group,
  *   s3 = t03 + t13
  */
 static int
-getSumVcpuPercpuStats(virCgroupPtr group,
-                      unsigned int nvcpu,
+getSumVcpuPercpuStats(virDomainObjPtr vm,
                       unsigned long long *sum_cpu_time,
                       unsigned int num)
 {
     int ret = -1;
     int i;
     char *buf = NULL;
-    virCgroupPtr group_vcpu = NULL;
+    virCgroupItemPtr group = NULL;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
 
-    for (i = 0; i < nvcpu; i++) {
+    for (i = 0; i < priv->nvcpupids; i++) {
         char *pos;
         unsigned long long tmp;
         int j;
 
-        if (virCgroupForVcpu(group, i, &group_vcpu, 0) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("error accessing cgroup cpuacct for vcpu"));
-            goto cleanup;
-        }
+        group = vm->def->vcpuCgroups[i][VIR_CGROUP_CONTROLLER_CPUACCT];
 
-        if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
+        if (virCgroupGetCpuacctPercpuUsage(group, &buf) < 0)
             goto cleanup;
 
         pos = buf;
@@ -14177,20 +14009,17 @@ getSumVcpuPercpuStats(virCgroupPtr group,
             sum_cpu_time[j] += tmp;
         }
 
-        virCgroupFree(&group_vcpu);
         VIR_FREE(buf);
     }
 
     ret = 0;
 cleanup:
-    virCgroupFree(&group_vcpu);
     VIR_FREE(buf);
     return ret;
 }
 
 static int
 qemuDomainGetPercpuStats(virDomainObjPtr vm,
-                         virCgroupPtr group,
                          virTypedParameterPtr params,
                          unsigned int nparams,
                          int start_cpu,
@@ -14203,7 +14032,6 @@ qemuDomainGetPercpuStats(virDomainObjPtr vm,
     unsigned long long *sum_cpu_time = NULL;
     unsigned long long *sum_cpu_pos;
     unsigned int n = 0;
-    qemuDomainObjPrivatePtr priv = vm->privateData;
     virTypedParameterPtr ent;
     int param_idx;
     unsigned long long cpu_time;
@@ -14230,7 +14058,8 @@ qemuDomainGetPercpuStats(virDomainObjPtr vm,
     }
 
     /* we get percpu cputime accounting info. */
-    if (virCgroupGetCpuacctPercpuUsage(group, &buf))
+    if (virCgroupGetCpuacctPercpuUsage(vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUACCT],
+                                       &buf))
         goto cleanup;
     pos = buf;
     memset(params, 0, nparams * ncpus);
@@ -14270,7 +14099,7 @@ qemuDomainGetPercpuStats(virDomainObjPtr vm,
         virReportOOMError();
         goto cleanup;
     }
-    if (getSumVcpuPercpuStats(group, priv->nvcpupids, sum_cpu_time, n) < 0)
+    if (getSumVcpuPercpuStats(vm, sum_cpu_time, n) < 0)
         goto cleanup;
 
     sum_cpu_pos = sum_cpu_time;
@@ -14303,7 +14132,7 @@ qemuDomainGetCPUStats(virDomainPtr domain,
                 unsigned int flags)
 {
     virQEMUDriverPtr driver = domain->conn->privateData;
-    virCgroupPtr group = NULL;
+    virCgroupItemPtr group = NULL;
     virDomainObjPtr vm = NULL;
     int ret = -1;
     bool isActive;
@@ -14326,13 +14155,9 @@ qemuDomainGetCPUStats(virDomainPtr domain,
         goto cleanup;
     }
 
-    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUACCT)) {
-        virReportError(VIR_ERR_OPERATION_INVALID,
-                       "%s", _("cgroup CPUACCT controller is not mounted"));
-        goto cleanup;
-    }
+    group = vm->def->cgroup[VIR_CGROUP_CONTROLLER_CPUACCT];
 
-    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
+    if (!group) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
         goto cleanup;
@@ -14341,10 +14166,9 @@ qemuDomainGetCPUStats(virDomainPtr domain,
     if (start_cpu == -1)
         ret = qemuDomainGetTotalcpuStats(group, params, nparams);
     else
-        ret = qemuDomainGetPercpuStats(vm, group, params, nparams,
+        ret = qemuDomainGetPercpuStats(vm, params, nparams,
                                        start_cpu, ncpus);
 cleanup:
-    virCgroupFree(&group);
     if (vm)
         virDomainObjUnlock(vm);
     qemuDriverUnlock(driver);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 19172e1..3007f06 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1093,24 +1093,16 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
     }
 
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        virCgroupPtr cgroup = NULL;
         usbDevice *usb;
         qemuCgroupData data;
 
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unable to find cgroup for %s"),
-                           vm->def->name);
-            goto error;
-        }
-
         if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus,
                                 hostdev->source.subsys.u.usb.device,
                                 NULL)) == NULL)
             goto error;
 
         data.vm = vm;
-        data.cgroup = cgroup;
+        data.cgroup = vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES];
         if (usbDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup, &data) < 0)
             goto error;
     }
@@ -1981,7 +1973,6 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
     int i, ret = -1;
     virDomainDiskDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virCgroupPtr cgroup = NULL;
     char *drivestr = NULL;
 
     i = qemuFindDisk(vm->def, dev->data.disk->dst);
@@ -2001,15 +1992,6 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
-    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unable to find cgroup for %s"),
-                           vm->def->name);
-            goto cleanup;
-        }
-    }
-
     if (!virDomainDeviceAddressIsValid(&detach->info,
                                        VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -2063,8 +2045,10 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
                                             vm->def, dev->data.disk) < 0)
         VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
 
-    if (cgroup != NULL) {
-        if (qemuTeardownDiskCgroup(vm, cgroup, dev->data.disk) < 0)
+    if (vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES]) {
+        if (qemuTeardownDiskCgroup(vm,
+                                   vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES],
+                                   dev->data.disk) < 0)
             VIR_WARN("Failed to teardown cgroup for disk path %s",
                      NULLSTR(dev->data.disk->src));
     }
@@ -2075,7 +2059,6 @@ int qemuDomainDetachPciDiskDevice(virQEMUDriverPtr driver,
     ret = 0;
 
 cleanup:
-    virCgroupFree(&cgroup);
     VIR_FREE(drivestr);
     return ret;
 }
@@ -2087,7 +2070,6 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
     int i, ret = -1;
     virDomainDiskDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virCgroupPtr cgroup = NULL;
     char *drivestr = NULL;
 
     i = qemuFindDisk(vm->def, dev->data.disk->dst);
@@ -2114,15 +2096,6 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
-    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
-        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Unable to find cgroup for %s"),
-                           vm->def->name);
-            goto cleanup;
-        }
-    }
-
     /* build the actual drive id string as the disk->info.alias doesn't
      * contain the QEMU_DRIVE_HOST_PREFIX that is passed to qemu */
     if (virAsprintf(&drivestr, "%s%s",
@@ -2155,8 +2128,10 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
                                             vm->def, dev->data.disk) < 0)
         VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
 
-    if (cgroup != NULL) {
-        if (qemuTeardownDiskCgroup(vm, cgroup, dev->data.disk) < 0)
+    if (vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES]) {
+        if (qemuTeardownDiskCgroup(vm,
+                                   vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES],
+                                   dev->data.disk) < 0)
             VIR_WARN("Failed to teardown cgroup for disk path %s",
                      NULLSTR(dev->data.disk->src));
     }
@@ -2168,7 +2143,6 @@ int qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
 
 cleanup:
     VIR_FREE(drivestr);
-    virCgroupFree(&cgroup);
     return ret;
 }
 
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index f17c7ff..cb6f6c7 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3590,7 +3590,6 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
                     enum qemuDomainAsyncJob asyncJob)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virCgroupPtr cgroup = NULL;
     int ret = -1;
     int rc;
     bool restoreLabel = false;
@@ -3623,22 +3622,17 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
          * given cgroup ACL permission.  We might also stumble on
          * a race present in some qemu versions where it does a wait()
          * that botches pclose.  */
-        if (qemuCgroupControllerActive(driver,
-                                       VIR_CGROUP_CONTROLLER_DEVICES)) {
-            if (virCgroupForDomain(driver->cgroup, vm->def->name,
-                                   &cgroup, 0) != 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Unable to find cgroup for %s"),
-                               vm->def->name);
-                goto cleanup;
-            }
-            rc = virCgroupAllowDevicePath(cgroup, path,
+        if (vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES]) {
+            rc = virCgroupAllowDevicePath(vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES],
+                                          path,
                                           VIR_CGROUP_DEVICE_RW);
-            virDomainAuditCgroupPath(vm, cgroup, "allow", path, "rw", rc);
-            if (rc == 1) {
-                /* path was not a device, no further need for cgroup */
-                virCgroupFree(&cgroup);
-            } else if (rc < 0) {
+            virDomainAuditCgroupPath(vm,
+                                     vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES],
+                                     "allow",
+                                     path,
+                                     "rw",
+                                     rc);
+            if (rc < 0) {
                 virReportSystemError(-rc,
                                      _("Unable to allow device %s for %s"),
                                      path, vm->def->name);
@@ -3732,14 +3726,16 @@ cleanup:
                                                  vm->def, path) < 0)
         VIR_WARN("failed to restore save state label on %s", path);
 
-    if (cgroup != NULL) {
-        rc = virCgroupDenyDevicePath(cgroup, path,
+    if (vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES]) {
+        rc = virCgroupDenyDevicePath(vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES],
+                                     path,
                                      VIR_CGROUP_DEVICE_RWM);
-        virDomainAuditCgroupPath(vm, cgroup, "deny", path, "rwm", rc);
+        virDomainAuditCgroupPath(vm,
+                                 vm->def->cgroup[VIR_CGROUP_CONTROLLER_DEVICES],
+                                 "deny", path, "rwm", rc);
         if (rc < 0)
             VIR_WARN("Unable to deny device %s for %s %d",
                      path, vm->def->name, rc);
-        virCgroupFree(&cgroup);
     }
     return ret;
 }
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 713670e..95cec7c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2737,6 +2737,7 @@ static int qemuProcessHook(void *data)
     struct qemuProcessHookData *h = data;
     int ret = -1;
     int fd;
+    int i;
 
     /* Some later calls want pid present */
     h->vm->pid = getpid();
@@ -2768,8 +2769,9 @@ static int qemuProcessHook(void *data)
      * memory allocation is on the correct NUMA node
      */
     VIR_DEBUG("Moving process to cgroup");
-    if (qemuAddToCgroup(h->driver, h->vm->def) < 0)
-        goto cleanup;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        virCgroupItemAddTask(h->vm->def->cgroup[i], getpid());
+    }
 
     /* This must be done after cgroup placement to avoid resetting CPU
      * affinity */
@@ -3655,11 +3657,6 @@ int qemuProcessStart(virConnectPtr conn,
         }
     }
 
-    /* Ensure no historical cgroup for this VM is lying around bogus
-     * settings */
-    VIR_DEBUG("Ensuring no historical cgroup is lying around");
-    qemuRemoveCgroup(driver, vm, 1);
-
     for (i = 0 ; i < vm->def->ngraphics; ++i) {
         virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
         if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
@@ -4175,13 +4172,11 @@ void qemuProcessStop(virQEMUDriverPtr driver,
                      virDomainShutoffReason reason,
                      unsigned int flags)
 {
-    int ret;
-    int retries = 0;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virErrorPtr orig_err;
     virDomainDefPtr def;
     virNetDevVPortProfilePtr vport = NULL;
-    int i;
+    int i, j;
     int logfile = -1;
     char *timestamp;
     char ebuf[1024];
@@ -4344,14 +4339,14 @@ void qemuProcessStop(virQEMUDriverPtr driver,
         networkReleaseActualDevice(net);
     }
 
-retry:
-    if ((ret = qemuRemoveCgroup(driver, vm, 0)) < 0) {
-        if (ret == -EBUSY && (retries++ < 5)) {
-            usleep(200*1000);
-            goto retry;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        virCgroupItemFree(vm->def->cgroup[i]);
+        virCgroupItemFree(vm->def->emulatorCgroup[i]);
+        if (vm->def->vcpuCgroups) {
+            for (j = 0; j < priv->nvcpupids; j++) {
+                virCgroupItemFree(vm->def->vcpuCgroups[j][i]);
+            }
         }
-        VIR_WARN("Failed to remove cgroup for %s",
-                 vm->def->name);
     }
 
     qemuProcessRemoveDomainStatus(driver, vm);
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index baa0af7..c5af032 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -92,6 +92,7 @@ VIR_ONCE_GLOBAL_INIT(virCgroupItem);
 
 static struct virCgroupController cgroupControllers[VIR_CGROUP_CONTROLLER_LAST];
 static virCgroupItemPtr rootCgroupItems[VIR_CGROUP_CONTROLLER_LAST];
+static virCgroupItemPtr appCgroupItems[2][VIR_CGROUP_CONTROLLER_LAST];
 
 static virCgroupItemPtr virCgroupItemRootNew(int type);
 static int virCgroupDetectMounts(struct virCgroupController (*controllers)[VIR_CGROUP_CONTROLLER_LAST]);
@@ -149,13 +150,21 @@ void virCgroupUninit(void)
             virCgroupItemFree(rootCgroupItems[i]);
             rootCgroupItems[i] = NULL;
         }
+        if (appCgroupItems[0][i]) {
+            virCgroupItemFree(appCgroupItems[0][i]);
+            appCgroupItems[0][i] = NULL;
+        }
+        if (appCgroupItems[1][i]) {
+            virCgroupItemFree(appCgroupItems[1][i]);
+            appCgroupItems[1][i] = NULL;
+        }
     }
 }
 
-struct virCgroup {
-    char *path;
+struct _virCgroup {
+    char *name;
 
-    struct virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+    virCgroupItemPtr items[VIR_CGROUP_CONTROLLER_LAST];
 };
 
 typedef enum {
@@ -236,9 +245,6 @@ virCgroupItemPtr virCgroupItemNew(int type,
         return NULL;
 
     if (!parent)
-        parent = rootCgroupItems[type];
-
-    if (!parent)
         return NULL;
 
     cgroupItem = virCgroupHasChildByName(parent, name);
@@ -406,6 +412,7 @@ static int virCgroupItemCpusetInherit(virCgroupItemPtr cgroupItem)
 }
 
 static int virCgroupRemoveRecursively(char *grppath);
+static int virCgroupItemSetMemoryUseHierarchy(virCgroupItemPtr group);
 
 static int virCgroupItemMakePath(virCgroupItemPtr cgroupItem)
 {
@@ -430,7 +437,11 @@ static int virCgroupItemMakePath(virCgroupItemPtr cgroupItem)
             return -errno;
         }
 
-        virCgroupItemCpusetInherit(cgroupItem);
+        if (cgroupItem->controller->type == VIR_CGROUP_CONTROLLER_CPUSET)
+            virCgroupItemCpusetInherit(cgroupItem);
+
+        if (cgroupItem->controller->type == VIR_CGROUP_CONTROLLER_MEMORY)
+            virCgroupItemSetMemoryUseHierarchy(cgroupItem);
     }
 
     return ret;
@@ -470,27 +481,6 @@ int virCgroupItemKeyPath(virCgroupItemPtr cgroupItem,
 }
 
 /**
- * virCgroupFree:
- *
- * @group: The group structure to free
- */
-void virCgroupFree(virCgroupPtr *group)
-{
-    int i;
-
-    if (*group == NULL)
-        return;
-
-    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-        VIR_FREE((*group)->controllers[i].mountPoint);
-        VIR_FREE((*group)->controllers[i].placement);
-    }
-
-    VIR_FREE((*group)->path);
-    VIR_FREE(*group);
-}
-
-/**
  * virCgroupMounted: query whether a cgroup subsystem is mounted or not
  *
  * @cgroup: The group structure to be queried
@@ -498,9 +488,9 @@ void virCgroupFree(virCgroupPtr *group)
  *
  * Returns true if a cgroup is subsystem is mounted.
  */
-bool virCgroupMounted(virCgroupPtr cgroup, int controller)
+bool virCgroupMounted(int controller)
 {
-    return cgroup->controllers[controller].mountPoint != NULL;
+    return cgroupControllers[controller].mountPoint != NULL;
 }
 
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
@@ -627,54 +617,6 @@ no_memory:
 }
 
 
-static int virCgroupDetect(virCgroupPtr group)
-{
-    int any = 0;
-    int rc;
-    int i;
-
-    rc = virCgroupDetectMounts(&group->controllers);
-    if (rc < 0) {
-        VIR_ERROR(_("Failed to detect mounts for %s"), group->path);
-        return rc;
-    }
-
-    /* Check that at least 1 controller is available */
-    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-        if (group->controllers[i].mountPoint != NULL)
-            any = 1;
-    }
-    if (!any)
-        return -ENXIO;
-
-
-    rc = virCgroupDetectPlacement(&group->controllers);
-
-    if (rc == 0) {
-        /* Check that for every mounted controller, we found our placement */
-        for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-            if (!group->controllers[i].mountPoint)
-                continue;
-
-            if (!group->controllers[i].placement) {
-                VIR_ERROR(_("Could not find placement for controller %s at %s"),
-                          virCgroupControllerTypeToString(i),
-                          group->controllers[i].placement);
-                rc = -ENOENT;
-                break;
-            }
-
-            VIR_DEBUG("Detected mount/mapping %i:%s at %s in %s", i,
-                      virCgroupControllerTypeToString(i),
-                      group->controllers[i].mountPoint,
-                      group->controllers[i].placement);
-        }
-    } else {
-        VIR_ERROR(_("Failed to detect mapping for %s"), group->path);
-    }
-
-    return rc;
-}
 #endif
 
 
@@ -683,99 +625,10 @@ int virCgroupPathOfController(virCgroupPtr group,
                               const char *key,
                               char **path)
 {
-    if (controller == -1) {
-        int i;
-        for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-            if (group->controllers[i].mountPoint &&
-                group->controllers[i].placement) {
-                controller = i;
-                break;
-            }
-        }
-    }
-    if (controller == -1)
-        return -ENOSYS;
-
-    if (group->controllers[controller].mountPoint == NULL)
-        return -ENOENT;
-
-    if (group->controllers[controller].placement == NULL)
-        return -ENOENT;
-
-    if (virAsprintf(path, "%s%s%s/%s",
-                    group->controllers[controller].mountPoint,
-                    group->controllers[controller].placement,
-                    STREQ(group->path, "/") ? "" : group->path,
-                    key ? key : "") == -1)
-        return -ENOMEM;
-
-    return 0;
-}
-
-
-static int virCgroupSetValueStr(virCgroupPtr group,
-                                int controller,
-                                const char *key,
-                                const char *value)
-{
-    int rc = 0;
-    char *keypath = NULL;
-
-    rc = virCgroupPathOfController(group, controller, key, &keypath);
-    if (rc != 0)
-        return rc;
-
-    VIR_DEBUG("Set value '%s' to '%s'", keypath, value);
-    rc = virFileWriteStr(keypath, value, 0);
-    if (rc < 0) {
-        rc = -errno;
-        VIR_DEBUG("Failed to write value '%s': %m", value);
-    } else {
-        rc = 0;
-    }
-
-    VIR_FREE(keypath);
-
-    return rc;
-}
-
-static int virCgroupGetValueStr(virCgroupPtr group,
-                                int controller,
-                                const char *key,
-                                char **value)
-{
-    int rc;
-    char *keypath = NULL;
-
-    *value = NULL;
-
-    rc = virCgroupPathOfController(group, controller, key, &keypath);
-    if (rc != 0) {
-        VIR_DEBUG("No path of %s, %s", group->path, key);
-        return rc;
-    }
-
-    VIR_DEBUG("Get value %s", keypath);
-
-    rc = virFileReadAll(keypath, 1024*1024, value);
-    if (rc < 0) {
-        rc = -errno;
-        VIR_DEBUG("Failed to read %s: %m\n", keypath);
-    } else {
-        /* Terminated with '\n' has sometimes harmful effects to the caller */
-        if ((*value)[rc - 1] == '\n')
-            (*value)[rc - 1] = '\0';
-
-        rc = 0;
-    }
-
-    VIR_FREE(keypath);
-
-    return rc;
+    return virCgroupItemKeyPath(group->items[controller], key, path);
 }
 
-static int virCgroupSetValueU64(virCgroupPtr group,
-                                int controller,
+static int virCgroupItemSetValueU64(virCgroupItemPtr group,
                                 const char *key,
                                 unsigned long long int value)
 {
@@ -785,17 +638,14 @@ static int virCgroupSetValueU64(virCgroupPtr group,
     if (virAsprintf(&strval, "%llu", value) == -1)
         return -ENOMEM;
 
-    rc = virCgroupSetValueStr(group, controller, key, strval);
+    rc = virCgroupItemSetValueStr(group, key, strval);
 
     VIR_FREE(strval);
 
     return rc;
 }
 
-
-
-static int virCgroupSetValueI64(virCgroupPtr group,
-                                int controller,
+static int virCgroupItemSetValueI64(virCgroupItemPtr group,
                                 const char *key,
                                 long long int value)
 {
@@ -805,22 +655,21 @@ static int virCgroupSetValueI64(virCgroupPtr group,
     if (virAsprintf(&strval, "%lld", value) == -1)
         return -ENOMEM;
 
-    rc = virCgroupSetValueStr(group, controller, key, strval);
+    rc = virCgroupItemSetValueStr(group, key, strval);
 
     VIR_FREE(strval);
 
     return rc;
 }
 
-static int virCgroupGetValueI64(virCgroupPtr group,
-                                int controller,
+static int virCgroupItemGetValueI64(virCgroupItemPtr group,
                                 const char *key,
                                 long long int *value)
 {
     char *strval = NULL;
     int rc = 0;
 
-    rc = virCgroupGetValueStr(group, controller, key, &strval);
+    rc = virCgroupItemGetValueStr(group, key, &strval);
     if (rc != 0)
         goto out;
 
@@ -832,15 +681,14 @@ out:
     return rc;
 }
 
-static int virCgroupGetValueU64(virCgroupPtr group,
-                                int controller,
-                                const char *key,
-                                unsigned long long int *value)
+static int virCgroupItemGetValueU64(virCgroupItemPtr group,
+                                    const char *key,
+                                    unsigned long long int *value)
 {
     char *strval = NULL;
     int rc = 0;
 
-    rc = virCgroupGetValueStr(group, controller, key, &strval);
+    rc = virCgroupItemGetValueStr(group, key, &strval);
     if (rc != 0)
         goto out;
 
@@ -852,58 +700,16 @@ out:
     return rc;
 }
 
-
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-static int virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
-{
-    int i;
-    int rc = 0;
-    const char *inherit_values[] = {
-        "cpuset.cpus",
-        "cpuset.mems",
-    };
-
-    VIR_DEBUG("Setting up inheritance %s -> %s", parent->path, group->path);
-    for (i = 0; i < ARRAY_CARDINALITY(inherit_values) ; i++) {
-        char *value;
-
-        rc = virCgroupGetValueStr(parent,
-                                  VIR_CGROUP_CONTROLLER_CPUSET,
-                                  inherit_values[i],
-                                  &value);
-        if (rc != 0) {
-            VIR_ERROR(_("Failed to get %s %d"), inherit_values[i], rc);
-            break;
-        }
-
-        VIR_DEBUG("Inherit %s = %s", inherit_values[i], value);
-
-        rc = virCgroupSetValueStr(group,
-                                  VIR_CGROUP_CONTROLLER_CPUSET,
-                                  inherit_values[i],
-                                  value);
-        VIR_FREE(value);
-
-        if (rc != 0) {
-            VIR_ERROR(_("Failed to set %s %d"), inherit_values[i], rc);
-            break;
-        }
-    }
-
-    return rc;
-}
-
-static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
+static int virCgroupItemSetMemoryUseHierarchy(virCgroupItemPtr item)
 {
     int rc = 0;
     unsigned long long value;
     const char *filename = "memory.use_hierarchy";
 
-    rc = virCgroupGetValueU64(group,
-                              VIR_CGROUP_CONTROLLER_MEMORY,
-                              filename, &value);
+    rc = virCgroupItemGetValueU64(item,
+                                  filename, &value);
     if (rc != 0) {
-        VIR_ERROR(_("Failed to read %s/%s (%d)"), group->path, filename, rc);
+        VIR_ERROR(_("Failed to read %s/%s (%d)"), item->path, filename, rc);
         return rc;
     }
 
@@ -911,109 +717,24 @@ static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
     if (value == 1)
         return 0;
 
-    VIR_DEBUG("Setting up %s/%s", group->path, filename);
-    rc = virCgroupSetValueU64(group,
-                              VIR_CGROUP_CONTROLLER_MEMORY,
-                              filename, 1);
+    VIR_DEBUG("Setting up %s/%s", item->path, filename);
+    rc = virCgroupItemSetValueU64(item,
+                                  filename, 1);
 
     if (rc != 0) {
-        VIR_ERROR(_("Failed to set %s/%s (%d)"), group->path, filename, rc);
-    }
-
-    return rc;
-}
-
-static int virCgroupMakeGroup(virCgroupPtr parent,
-                              virCgroupPtr group,
-                              bool create,
-                              unsigned int flags)
-{
-    int i;
-    int rc = 0;
-
-    VIR_DEBUG("Make group %s", group->path);
-    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-        char *path = NULL;
-
-        /* Skip over controllers that aren't mounted */
-        if (!group->controllers[i].mountPoint)
-            continue;
-
-        /* We need to control cpu bandwidth for each vcpu now */
-        if ((flags & VIR_CGROUP_VCPU) &&
-            (i != VIR_CGROUP_CONTROLLER_CPU &&
-             i != VIR_CGROUP_CONTROLLER_CPUACCT &&
-             i != VIR_CGROUP_CONTROLLER_CPUSET)) {
-            /* treat it as unmounted and we can use virCgroupAddTask */
-            VIR_FREE(group->controllers[i].mountPoint);
-            continue;
-        }
-
-        rc = virCgroupPathOfController(group, i, "", &path);
-        if (rc < 0)
-            return rc;
-        /* As of Feb 2011, clang can't see that the above function
-         * call did not modify group. */
-        sa_assert(group->controllers[i].mountPoint);
-
-        VIR_DEBUG("Make controller %s", path);
-        if (access(path, F_OK) != 0) {
-            if (!create ||
-                mkdir(path, 0755) < 0) {
-                /* With a kernel that doesn't support multi-level directory
-                 * for blkio controller, libvirt will fail and disable all
-                 * other controllers even though they are available. So
-                 * treat blkio as unmounted if mkdir fails. */
-                if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
-                    rc = 0;
-                    VIR_FREE(group->controllers[i].mountPoint);
-                    VIR_FREE(path);
-                    continue;
-                } else {
-                    rc = -errno;
-                    VIR_FREE(path);
-                    break;
-                }
-            }
-            if (group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint != NULL &&
-                (i == VIR_CGROUP_CONTROLLER_CPUSET ||
-                 STREQ(group->controllers[i].mountPoint, group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint))) {
-                rc = virCgroupCpuSetInherit(parent, group);
-                if (rc != 0) {
-                    VIR_FREE(path);
-                    break;
-                }
-            }
-            /*
-             * Note that virCgroupSetMemoryUseHierarchy should always be
-             * called prior to creating subcgroups and attaching tasks.
-             */
-            if ((flags & VIR_CGROUP_MEM_HIERACHY) &&
-                (group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint != NULL) &&
-                (i == VIR_CGROUP_CONTROLLER_MEMORY ||
-                 STREQ(group->controllers[i].mountPoint, group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint))) {
-                rc = virCgroupSetMemoryUseHierarchy(group);
-                if (rc != 0) {
-                    VIR_FREE(path);
-                    break;
-                }
-            }
-        }
-
-        VIR_FREE(path);
+        VIR_ERROR(_("Failed to set %s/%s (%d)"), item->path, filename, rc);
     }
 
     return rc;
 }
 
-
-static int virCgroupNew(const char *path,
-                        virCgroupPtr *group)
+int virCgroupNew(const char *name,
+                 virCgroupPtr parent,
+                 virCgroupPtr *group)
 {
     int rc = 0;
-    char *typpath = NULL;
+    int i;
 
-    VIR_DEBUG("New group %s", path);
     *group = NULL;
 
     if (VIR_ALLOC((*group)) != 0) {
@@ -1021,66 +742,48 @@ static int virCgroupNew(const char *path,
         goto err;
     }
 
-    if (!((*group)->path = strdup(path))) {
+    if (!((*group)->name = strdup(name))) {
         rc = -ENOMEM;
         goto err;
     }
 
-    rc = virCgroupDetect(*group);
-    if (rc < 0)
-        goto err;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
+        (*group)->items[i] = virCgroupItemNew(i, name, parent->items[i]);
 
     return rc;
 err:
-    virCgroupFree(group);
+    VIR_FREE(*group);
     *group = NULL;
 
-    VIR_FREE(typpath);
-
     return rc;
 }
 
-static int virCgroupAppRoot(bool privileged,
-                            virCgroupPtr *group,
-                            bool create)
+/**
+ * virCgroupFree:
+ *
+ * @group: The group to be removed
+ *
+ * fre @group and its cgroup items.
+ *
+ */
+void virCgroupFree(virCgroupPtr *group)
 {
-    virCgroupPtr rootgrp = NULL;
-    int rc;
+    int i;
 
-    rc = virCgroupNew("/", &rootgrp);
-    if (rc != 0)
-        return rc;
+    if (!group)
+        return;
 
-    if (privileged) {
-        rc = virCgroupNew("/libvirt", group);
-    } else {
-        char *rootname;
-        char *username;
-        username = virGetUserName(getuid());
-        if (!username) {
-            rc = -ENOMEM;
-            goto cleanup;
-        }
-        rc = virAsprintf(&rootname, "/libvirt-%s", username);
-        VIR_FREE(username);
-        if (rc < 0) {
-            rc = -ENOMEM;
-            goto cleanup;
-        }
+    if (!*group)
+        return;
 
-        rc = virCgroupNew(rootname, group);
-        VIR_FREE(rootname);
-    }
-    if (rc != 0)
-        goto cleanup;
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
+        virCgroupItemFree((*group)->items[i]);
 
-    rc = virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE);
+    VIR_FREE((*group)->name);
+    VIR_FREE(*group);
 
-cleanup:
-    virCgroupFree(&rootgrp);
-    return rc;
+    return;
 }
-#endif
 
 #if defined _DIRENT_HAVE_D_TYPE
 static int virCgroupRemoveRecursively(char *grppath)
@@ -1140,93 +843,22 @@ static int virCgroupRemoveRecursively(char *grppath ATTRIBUTE_UNUSED)
 #endif
 
 /**
- * virCgroupRemove:
- *
- * @group: The group to be removed
- *
- * It first removes all child groups recursively
- * in depth first order and then removes @group
- * because the presence of the child groups
- * prevents removing @group.
+ * virCgroupItemAddTask:
  *
- * Returns: 0 on success
- */
-int virCgroupRemove(virCgroupPtr group)
-{
-    int rc = 0;
-    int i;
-    char *grppath = NULL;
-
-    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-        /* Skip over controllers not mounted */
-        if (!group->controllers[i].mountPoint)
-            continue;
-
-        if (virCgroupPathOfController(group,
-                                      i,
-                                      NULL,
-                                      &grppath) != 0)
-            continue;
-
-        VIR_DEBUG("Removing cgroup %s and all child cgroups", grppath);
-        rc = virCgroupRemoveRecursively(grppath);
-        VIR_FREE(grppath);
-    }
-
-    return rc;
-}
-
-/**
- * virCgroupAddTask:
- *
- * @group: The cgroup to add a task to
+ * @item: The cgroup item to add a task to
  * @pid: The pid of the task to add
  *
  * Returns: 0 on success
  */
-int virCgroupAddTask(virCgroupPtr group, pid_t pid)
-{
-    int rc = 0;
-    int i;
-
-    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
-        /* Skip over controllers not mounted */
-        if (!group->controllers[i].mountPoint)
-            continue;
-
-        rc = virCgroupSetValueU64(group, i, "tasks", (unsigned long long)pid);
-        if (rc != 0)
-            break;
-    }
-
-    return rc;
-}
-
-/**
- * virCgroupAddTaskController:
- *
- * @group: The cgroup to add a task to
- * @pid: The pid of the task to add
- * @controller: The cgroup controller to be operated on
- *
- * Returns: 0 on success or -errno on failure
- */
-int virCgroupAddTaskController(virCgroupPtr group, pid_t pid, int controller)
+int virCgroupItemAddTask(virCgroupItemPtr item, pid_t pid)
 {
-    if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
-        return -EINVAL;
-
-    if (!group->controllers[controller].mountPoint)
-        return -EINVAL;
-
-    return virCgroupSetValueU64(group, controller, "tasks",
-                                (unsigned long long)pid);
+    return virCgroupItemSetValueU64(item, "tasks",
+                                    (unsigned long long)pid);
 }
 
 
-static int virCgroupAddTaskStrController(virCgroupPtr group,
-                                        const char *pidstr,
-                                        int controller)
+static int virCgroupItemAddTaskStr(virCgroupItemPtr item,
+                                   const char *pidstr)
 {
     char *str = NULL, *cur = NULL, *next = NULL;
     unsigned long long p = 0;
@@ -1242,7 +874,7 @@ static int virCgroupAddTaskStrController(virCgroupPtr group,
         if (rc != 0)
             goto cleanup;
 
-        rc = virCgroupAddTaskController(group, p, controller);
+        rc = virCgroupItemAddTask(item, p);
         if (rc != 0)
             goto cleanup;
 
@@ -1261,35 +893,23 @@ cleanup:
 }
 
 /**
- * virCgroupMoveTask:
+ * virCgroupItemMoveTask:
  *
- * @src_group: The source cgroup where all tasks are removed from
- * @dest_group: The destination where all tasks are added to
- * @controller: The cgroup controller to be operated on
+ * @src: The source cgroup where all tasks are removed from
+ * @dest: The destination where all tasks are added to
  *
  * Returns: 0 on success or -errno on failure
  */
-int virCgroupMoveTask(virCgroupPtr src_group, virCgroupPtr dest_group,
-                      int controller)
+int virCgroupItemMoveTask(virCgroupItemPtr src, virCgroupItemPtr dest)
 {
     int rc = 0, err = 0;
     char *content = NULL;
 
-    if (controller < VIR_CGROUP_CONTROLLER_CPU ||
-        controller > VIR_CGROUP_CONTROLLER_BLKIO)
-        return -EINVAL;
-
-    if (!src_group->controllers[controller].mountPoint ||
-        !dest_group->controllers[controller].mountPoint) {
-        VIR_WARN("no vm cgroup in controller %d", controller);
-        return 0;
-    }
-
-    rc = virCgroupGetValueStr(src_group, controller, "tasks", &content);
+    rc = virCgroupItemGetValueStr(src, "tasks", &content);
     if (rc != 0)
         return rc;
 
-    rc = virCgroupAddTaskStrController(dest_group, content, controller);
+    rc = virCgroupItemAddTaskStr(dest, content);
     if (rc != 0)
         goto cleanup;
 
@@ -1302,229 +922,56 @@ cleanup:
      * We don't need to recover dest_cgroup because cgroup will make sure
      * that one task only resides in one cgroup of the same controller.
      */
-    err = virCgroupAddTaskStrController(src_group, content, controller);
+    err = virCgroupItemAddTaskStr(src, content);
     if (err != 0)
         VIR_ERROR(_("Cannot recover cgroup %s from %s"),
-                  src_group->controllers[controller].mountPoint,
-                  dest_group->controllers[controller].mountPoint);
+                  src->path,
+                  dest->path);
     VIR_FREE(content);
 
     return rc;
 }
 
 /**
- * virCgroupForDriver:
- *
- * @name: name of this driver (e.g., xen, qemu, lxc)
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns 0 on success
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForDriver(const char *name,
-                       virCgroupPtr *group,
-                       bool privileged,
-                       bool create)
-{
-    int rc;
-    char *path = NULL;
-    virCgroupPtr rootgrp = NULL;
-
-    rc = virCgroupAppRoot(privileged, &rootgrp, create);
-    if (rc != 0)
-        goto out;
-
-    if (virAsprintf(&path, "%s/%s", rootgrp->path, name) < 0) {
-        rc = -ENOMEM;
-        goto out;
-    }
-
-    rc = virCgroupNew(path, group);
-    VIR_FREE(path);
-
-    if (rc == 0) {
-        rc = virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE);
-        if (rc != 0)
-            virCgroupFree(group);
-    }
-
-out:
-    virCgroupFree(&rootgrp);
-
-    return rc;
-}
-#else
-int virCgroupForDriver(const char *name ATTRIBUTE_UNUSED,
-                       virCgroupPtr *group ATTRIBUTE_UNUSED,
-                       bool privileged ATTRIBUTE_UNUSED,
-                       bool create ATTRIBUTE_UNUSED)
-{
-    /* Claim no support */
-    return -ENXIO;
-}
-#endif
-
-/**
 * virCgroupGetAppRoot:
 *
-* @group: Pointer to returned virCgroupPtr
+* @type: the type of app cgroup item
 *
-* Returns 0 on success
+* Returns the app cgroup item of type, or NULL on error
 */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupGetAppRoot(virCgroupPtr *group)
-{
-    return virCgroupNew("/", group);
-}
-#else
-int virCgroupGetAppRoot(virCgroupPtr *group ATTRIBUTE_UNUSED)
-{
-    return -ENXIO;
-}
-#endif
-
-/**
- * virCgroupForDomain:
- *
- * @driver: group for driver owning the domain
- * @name: name of the domain
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns 0 on success
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForDomain(virCgroupPtr driver,
-                       const char *name,
-                       virCgroupPtr *group,
-                       bool create)
+virCgroupItemPtr virCgroupGetAppRoot(int type, bool privileged)
 {
+    int p = privileged ? 1 : 0;
+    char *name;
+    char *userName;
     int rc;
-    char *path;
-
-    if (driver == NULL)
-        return -EINVAL;
-
-    if (virAsprintf(&path, "%s/%s", driver->path, name) < 0)
-        return -ENOMEM;
-
-    rc = virCgroupNew(path, group);
-    VIR_FREE(path);
-
-    if (rc == 0) {
-        /*
-         * Create a cgroup with memory.use_hierarchy enabled to
-         * surely account memory usage of lxc with ns subsystem
-         * enabled. (To be exact, memory and ns subsystems are
-         * enabled at the same time.)
-         *
-         * The reason why doing it here, not a upper group, say
-         * a group for driver, is to avoid overhead to track
-         * cumulative usage that we don't need.
-         */
-        rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_MEM_HIERACHY);
-        if (rc != 0)
-            virCgroupFree(group);
-    }
-
-    return rc;
-}
-#else
-int virCgroupForDomain(virCgroupPtr driver ATTRIBUTE_UNUSED,
-                       const char *name ATTRIBUTE_UNUSED,
-                       virCgroupPtr *group ATTRIBUTE_UNUSED,
-                       bool create ATTRIBUTE_UNUSED)
-{
-    return -ENXIO;
-}
-#endif
 
-/**
- * virCgroupForVcpu:
- *
- * @driver: group for the domain
- * @vcpuid: id of the vcpu
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns 0 on success
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForVcpu(virCgroupPtr driver,
-                     int vcpuid,
-                     virCgroupPtr *group,
-                     bool create)
-{
-    int rc;
-    char *path;
-
-    if (driver == NULL)
-        return -EINVAL;
-
-    if (virAsprintf(&path, "%s/vcpu%d", driver->path, vcpuid) < 0)
-        return -ENOMEM;
+    if (type < 0 || type >= VIR_CGROUP_CONTROLLER_LAST)
+        return NULL;
 
-    rc = virCgroupNew(path, group);
-    VIR_FREE(path);
+    if (virCgroupItemInitialize() < 0)
+        return NULL;
 
-    if (rc == 0) {
-        rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_VCPU);
-        if (rc != 0)
-            virCgroupFree(group);
+    if (privileged) {
+        rc = virAsprintf(&name, "libvirt");
+    } else {
+        userName = virGetUserName(getuid());
+        if (!userName)
+            return NULL;
+        rc = virAsprintf(&name, "libvirt-%s", userName);
+        VIR_FREE(userName);
     }
 
-    return rc;
-}
-#else
-int virCgroupForVcpu(virCgroupPtr driver ATTRIBUTE_UNUSED,
-                     int vcpuid ATTRIBUTE_UNUSED,
-                     virCgroupPtr *group ATTRIBUTE_UNUSED,
-                     bool create ATTRIBUTE_UNUSED)
-{
-    return -ENXIO;
-}
-#endif
-
-/**
- * virCgroupForEmulator:
- *
- * @driver: group for the domain
- * @group: Pointer to returned virCgroupPtr
- *
- * Returns: 0 on success or -errno on failure
- */
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-int virCgroupForEmulator(virCgroupPtr driver,
-                         virCgroupPtr *group,
-                         bool create)
-{
-    int rc;
-    char *path;
-
-    if (driver == NULL)
-        return -EINVAL;
-
-    if (virAsprintf(&path, "%s/emulator", driver->path) < 0)
-        return -ENOMEM;
-
-    rc = virCgroupNew(path, group);
-    VIR_FREE(path);
+    if (rc < 0)
+        return NULL;
 
-    if (rc == 0) {
-        rc = virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_VCPU);
-        if (rc != 0)
-            virCgroupFree(group);
-    }
+    if (!appCgroupItems[p][type])
+        appCgroupItems[p][type] = virCgroupItemNew(type, name,
+                                                   rootCgroupItems[type]);
 
-    return rc;
-}
-#else
-int virCgroupForEmulator(virCgroupPtr driver ATTRIBUTE_UNUSED,
-                         virCgroupPtr *group ATTRIBUTE_UNUSED,
-                         bool create ATTRIBUTE_UNUSED)
-{
-    return -ENXIO;
+    return appCgroupItems[p][type];
 }
 
-#endif
 /**
  * virCgroupSetBlkioWeight:
  *
@@ -1533,15 +980,16 @@ int virCgroupForEmulator(virCgroupPtr driver ATTRIBUTE_UNUSED,
  *
  * Returns: 0 on success
  */
-int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
+int virCgroupSetBlkioWeight(virCgroupItemPtr group, unsigned int weight)
 {
     if (weight > 1000 || weight < 100)
         return -EINVAL;
 
-    return virCgroupSetValueU64(group,
-                                VIR_CGROUP_CONTROLLER_BLKIO,
-                                "blkio.weight",
-                                weight);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_BLKIO);
+
+    return virCgroupItemSetValueU64(group,
+                                    "blkio.weight",
+                                    weight);
 }
 
 /**
@@ -1552,13 +1000,15 @@ int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
  *
  * Returns: 0 on success
  */
-int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
+int virCgroupGetBlkioWeight(virCgroupItemPtr group, unsigned int *weight)
 {
     unsigned long long tmp;
     int ret;
-    ret = virCgroupGetValueU64(group,
-                               VIR_CGROUP_CONTROLLER_BLKIO,
-                               "blkio.weight", &tmp);
+
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_BLKIO);
+
+    ret = virCgroupItemGetValueU64(group,
+                                   "blkio.weight", &tmp);
     if (ret == 0)
         *weight = tmp;
     return ret;
@@ -1577,7 +1027,7 @@ int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
  * Returns: 0 on success, -errno on failure
  */
 #if defined(major) && defined(minor)
-int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+int virCgroupSetBlkioDeviceWeight(virCgroupItemPtr group,
                                   const char *path,
                                   unsigned int weight)
 {
@@ -1585,6 +1035,8 @@ int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
     struct stat sb;
     int ret;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_BLKIO);
+
     if (weight && (weight > 1000 || weight < 100))
         return -EINVAL;
 
@@ -1598,10 +1050,9 @@ int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
                     weight) < 0)
         return -errno;
 
-    ret = virCgroupSetValueStr(group,
-                               VIR_CGROUP_CONTROLLER_BLKIO,
-                               "blkio.weight_device",
-                               str);
+    ret = virCgroupItemSetValueStr(group,
+                                   "blkio.weight_device",
+                                   str);
     VIR_FREE(str);
     return ret;
 }
@@ -1623,22 +1074,22 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
  *
  * Returns: 0 on success
  */
-int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb)
+int virCgroupSetMemory(virCgroupItemPtr group, unsigned long long kb)
 {
     unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
     if (kb > maxkb)
         return -EINVAL;
     else if (kb == maxkb)
-        return virCgroupSetValueI64(group,
-                                    VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.limit_in_bytes",
-                                    -1);
+        return virCgroupItemSetValueI64(group,
+                                        "memory.limit_in_bytes",
+                                        -1);
     else
-        return virCgroupSetValueU64(group,
-                                    VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.limit_in_bytes",
-                                    kb << 10);
+        return virCgroupItemSetValueU64(group,
+                                        "memory.limit_in_bytes",
+                                        kb << 10);
 }
 
 /**
@@ -1649,13 +1100,15 @@ int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb)
  *
  * Returns: 0 on success
  */
-int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
+int virCgroupGetMemoryUsage(virCgroupItemPtr group, unsigned long *kb)
 {
     long long unsigned int usage_in_bytes;
     int ret;
-    ret = virCgroupGetValueU64(group,
-                               VIR_CGROUP_CONTROLLER_MEMORY,
-                               "memory.usage_in_bytes", &usage_in_bytes);
+
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
+    ret = virCgroupItemGetValueU64(group,
+                                   "memory.usage_in_bytes", &usage_in_bytes);
     if (ret == 0)
         *kb = (unsigned long) usage_in_bytes >> 10;
     return ret;
@@ -1669,7 +1122,7 @@ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
  *
  * Returns: 0 on success
  */
-int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
+int virCgroupSetMemoryHardLimit(virCgroupItemPtr group, unsigned long long kb)
 {
     return virCgroupSetMemory(group, kb);
 }
@@ -1682,13 +1135,15 @@ int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
  *
  * Returns: 0 on success
  */
-int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
+int virCgroupGetMemoryHardLimit(virCgroupItemPtr group, unsigned long long *kb)
 {
     long long unsigned int limit_in_bytes;
     int ret;
-    ret = virCgroupGetValueU64(group,
-                               VIR_CGROUP_CONTROLLER_MEMORY,
-                               "memory.limit_in_bytes", &limit_in_bytes);
+
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
+    ret = virCgroupItemGetValueU64(group,
+                                   "memory.limit_in_bytes", &limit_in_bytes);
     if (ret == 0)
         *kb = limit_in_bytes >> 10;
     return ret;
@@ -1702,22 +1157,22 @@ int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
  *
  * Returns: 0 on success
  */
-int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
+int virCgroupSetMemorySoftLimit(virCgroupItemPtr group, unsigned long long kb)
 {
     unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
     if (kb > maxkb)
         return -EINVAL;
     else if (kb == maxkb)
-        return virCgroupSetValueI64(group,
-                                    VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.soft_limit_in_bytes",
-                                    -1);
+        return virCgroupItemSetValueI64(group,
+                                        "memory.soft_limit_in_bytes",
+                                        -1);
     else
-        return virCgroupSetValueU64(group,
-                                    VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.soft_limit_in_bytes",
-                                    kb << 10);
+        return virCgroupItemSetValueU64(group,
+                                        "memory.soft_limit_in_bytes",
+                                        kb << 10);
 }
 
 
@@ -1729,13 +1184,15 @@ int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
  *
  * Returns: 0 on success
  */
-int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
+int virCgroupGetMemorySoftLimit(virCgroupItemPtr group, unsigned long long *kb)
 {
     long long unsigned int limit_in_bytes;
     int ret;
-    ret = virCgroupGetValueU64(group,
-                               VIR_CGROUP_CONTROLLER_MEMORY,
-                               "memory.soft_limit_in_bytes", &limit_in_bytes);
+
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
+    ret = virCgroupItemGetValueU64(group,
+                                   "memory.soft_limit_in_bytes", &limit_in_bytes);
     if (ret == 0)
         *kb = limit_in_bytes >> 10;
     return ret;
@@ -1749,22 +1206,22 @@ int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
  *
  * Returns: 0 on success
  */
-int virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
+int virCgroupSetMemSwapHardLimit(virCgroupItemPtr group, unsigned long long kb)
 {
     unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
     if (kb > maxkb)
         return -EINVAL;
     else if (kb == maxkb)
-        return virCgroupSetValueI64(group,
-                                    VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.memsw.limit_in_bytes",
-                                    -1);
+        return virCgroupItemSetValueI64(group,
+                                        "memory.memsw.limit_in_bytes",
+                                        -1);
     else
-        return virCgroupSetValueU64(group,
-                                    VIR_CGROUP_CONTROLLER_MEMORY,
-                                    "memory.memsw.limit_in_bytes",
-                                    kb << 10);
+        return virCgroupItemSetValueU64(group,
+                                        "memory.memsw.limit_in_bytes",
+                                        kb << 10);
 }
 
 /**
@@ -1775,13 +1232,15 @@ int virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
  *
  * Returns: 0 on success
  */
-int virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
+int virCgroupGetMemSwapHardLimit(virCgroupItemPtr group, unsigned long long *kb)
 {
     long long unsigned int limit_in_bytes;
     int ret;
-    ret = virCgroupGetValueU64(group,
-                               VIR_CGROUP_CONTROLLER_MEMORY,
-                               "memory.memsw.limit_in_bytes", &limit_in_bytes);
+
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
+    ret = virCgroupItemGetValueU64(group,
+                                   "memory.memsw.limit_in_bytes", &limit_in_bytes);
     if (ret == 0)
         *kb = limit_in_bytes >> 10;
     return ret;
@@ -1795,13 +1254,15 @@ int virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
  *
  * Returns: 0 on success
  */
-int virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
+int virCgroupGetMemSwapUsage(virCgroupItemPtr group, unsigned long long *kb)
 {
     long long unsigned int usage_in_bytes;
     int ret;
-    ret = virCgroupGetValueU64(group,
-                               VIR_CGROUP_CONTROLLER_MEMORY,
-                               "memory.memsw.usage_in_bytes", &usage_in_bytes);
+
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_MEMORY);
+
+    ret = virCgroupItemGetValueU64(group,
+                                   "memory.memsw.usage_in_bytes", &usage_in_bytes);
     if (ret == 0)
         *kb = usage_in_bytes >> 10;
     return ret;
@@ -1815,12 +1276,13 @@ int virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
  *
  * Returns: 0 on success
  */
-int virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
+int virCgroupSetCpusetMems(virCgroupItemPtr group, const char *mems)
 {
-    return virCgroupSetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_CPUSET,
-                                "cpuset.mems",
-                                mems);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUSET);
+
+    return virCgroupItemSetValueStr(group,
+                                    "cpuset.mems",
+                                    mems);
 }
 
 /**
@@ -1831,12 +1293,13 @@ int virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
  *
  * Returns: 0 on success
  */
-int virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
+int virCgroupGetCpusetMems(virCgroupItemPtr group, char **mems)
 {
-    return virCgroupGetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_CPUSET,
-                                "cpuset.mems",
-                                mems);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUSET);
+
+    return virCgroupItemGetValueStr(group,
+                                    "cpuset.mems",
+                                    mems);
 }
 
 /**
@@ -1847,12 +1310,13 @@ int virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
  *
  * Retuens: 0 on success
  */
-int virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
+int virCgroupSetCpusetCpus(virCgroupItemPtr group, const char *cpus)
 {
-    return virCgroupSetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_CPUSET,
-                                "cpuset.cpus",
-                                cpus);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUSET);
+
+    return virCgroupItemSetValueStr(group,
+                                    "cpuset.cpus",
+                                    cpus);
 }
 
 /**
@@ -1863,10 +1327,11 @@ int virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
  *
  * Retuens: 0 on success
  */
-int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
+int virCgroupGetCpusetCpus(virCgroupItemPtr group, char **cpus)
 {
-    return virCgroupGetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_CPUSET,
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUSET);
+
+    return virCgroupItemGetValueStr(group,
                                 "cpuset.cpus",
                                 cpus);
 }
@@ -1878,12 +1343,13 @@ int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
  *
  * Returns: 0 on success
  */
-int virCgroupDenyAllDevices(virCgroupPtr group)
+int virCgroupDenyAllDevices(virCgroupItemPtr group)
 {
-    return virCgroupSetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_DEVICES,
-                                "devices.deny",
-                                "a");
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_DEVICES);
+
+    return virCgroupItemSetValueStr(group,
+                                    "devices.deny",
+                                    "a");
 }
 
 /**
@@ -1897,12 +1363,14 @@ int virCgroupDenyAllDevices(virCgroupPtr group)
  *
  * Returns: 0 on success
  */
-int virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
+int virCgroupAllowDevice(virCgroupItemPtr group, char type, int major, int minor,
                          int perms)
 {
     int rc;
     char *devstr = NULL;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_DEVICES);
+
     if (virAsprintf(&devstr, "%c %i:%i %s%s%s", type, major, minor,
                     perms & VIR_CGROUP_DEVICE_READ ? "r" : "",
                     perms & VIR_CGROUP_DEVICE_WRITE ? "w" : "",
@@ -1911,10 +1379,9 @@ int virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
         goto out;
     }
 
-    rc = virCgroupSetValueStr(group,
-                              VIR_CGROUP_CONTROLLER_DEVICES,
-                              "devices.allow",
-                              devstr);
+    rc = virCgroupItemSetValueStr(group,
+                                  "devices.allow",
+                                  devstr);
 out:
     VIR_FREE(devstr);
 
@@ -1931,12 +1398,14 @@ out:
  *
  * Returns: 0 on success
  */
-int virCgroupAllowDeviceMajor(virCgroupPtr group, char type, int major,
+int virCgroupAllowDeviceMajor(virCgroupItemPtr group, char type, int major,
                               int perms)
 {
     int rc;
     char *devstr = NULL;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_DEVICES);
+
     if (virAsprintf(&devstr, "%c %i:* %s%s%s", type, major,
                     perms & VIR_CGROUP_DEVICE_READ ? "r" : "",
                     perms & VIR_CGROUP_DEVICE_WRITE ? "w" : "",
@@ -1945,10 +1414,9 @@ int virCgroupAllowDeviceMajor(virCgroupPtr group, char type, int major,
         goto out;
     }
 
-    rc = virCgroupSetValueStr(group,
-                              VIR_CGROUP_CONTROLLER_DEVICES,
-                              "devices.allow",
-                              devstr);
+    rc = virCgroupItemSetValueStr(group,
+                                  "devices.allow",
+                                  devstr);
  out:
     VIR_FREE(devstr);
 
@@ -1969,7 +1437,7 @@ int virCgroupAllowDeviceMajor(virCgroupPtr group, char type, int major,
  * negative errno value on failure
  */
 #if defined(major) && defined(minor)
-int virCgroupAllowDevicePath(virCgroupPtr group, const char *path, int perms)
+int virCgroupAllowDevicePath(virCgroupItemPtr group, const char *path, int perms)
 {
     struct stat sb;
 
@@ -1986,7 +1454,7 @@ int virCgroupAllowDevicePath(virCgroupPtr group, const char *path, int perms)
                                 perms);
 }
 #else
-int virCgroupAllowDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
+int virCgroupAllowDevicePath(virCgroupItemPtr group ATTRIBUTE_UNUSED,
                              const char *path ATTRIBUTE_UNUSED,
                              int perms ATTRIBUTE_UNUSED)
 {
@@ -2006,12 +1474,14 @@ int virCgroupAllowDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
  *
  * Returns: 0 on success
  */
-int virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
+int virCgroupDenyDevice(virCgroupItemPtr group, char type, int major, int minor,
                         int perms)
 {
     int rc;
     char *devstr = NULL;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_DEVICES);
+
     if (virAsprintf(&devstr, "%c %i:%i %s%s%s", type, major, minor,
                     perms & VIR_CGROUP_DEVICE_READ ? "r" : "",
                     perms & VIR_CGROUP_DEVICE_WRITE ? "w" : "",
@@ -2020,10 +1490,9 @@ int virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
         goto out;
     }
 
-    rc = virCgroupSetValueStr(group,
-                              VIR_CGROUP_CONTROLLER_DEVICES,
-                              "devices.deny",
-                              devstr);
+    rc = virCgroupItemSetValueStr(group,
+                                  "devices.deny",
+                                  devstr);
 out:
     VIR_FREE(devstr);
 
@@ -2040,12 +1509,14 @@ out:
  *
  * Returns: 0 on success
  */
-int virCgroupDenyDeviceMajor(virCgroupPtr group, char type, int major,
+int virCgroupDenyDeviceMajor(virCgroupItemPtr group, char type, int major,
                              int perms)
 {
     int rc;
     char *devstr = NULL;
 
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_DEVICES);
+
     if (virAsprintf(&devstr, "%c %i:* %s%s%s", type, major,
                     perms & VIR_CGROUP_DEVICE_READ ? "r" : "",
                     perms & VIR_CGROUP_DEVICE_WRITE ? "w" : "",
@@ -2054,10 +1525,9 @@ int virCgroupDenyDeviceMajor(virCgroupPtr group, char type, int major,
         goto out;
     }
 
-    rc = virCgroupSetValueStr(group,
-                              VIR_CGROUP_CONTROLLER_DEVICES,
-                              "devices.deny",
-                              devstr);
+    rc = virCgroupItemSetValueStr(group,
+                                  "devices.deny",
+                                  devstr);
  out:
     VIR_FREE(devstr);
 
@@ -2065,7 +1535,7 @@ int virCgroupDenyDeviceMajor(virCgroupPtr group, char type, int major,
 }
 
 #if defined(major) && defined(minor)
-int virCgroupDenyDevicePath(virCgroupPtr group, const char *path, int perms)
+int virCgroupDenyDevicePath(virCgroupItemPtr group, const char *path, int perms)
 {
     struct stat sb;
 
@@ -2082,7 +1552,7 @@ int virCgroupDenyDevicePath(virCgroupPtr group, const char *path, int perms)
                                perms);
 }
 #else
-int virCgroupDenyDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
+int virCgroupDenyDevicePath(virCgroupItemPtr group ATTRIBUTE_UNUSED,
                             const char *path ATTRIBUTE_UNUSED,
                             int perms ATTRIBUTE_UNUSED)
 {
@@ -2090,18 +1560,20 @@ int virCgroupDenyDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
 }
 #endif
 
-int virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares)
+int virCgroupSetCpuShares(virCgroupItemPtr group, unsigned long long shares)
 {
-    return virCgroupSetValueU64(group,
-                                VIR_CGROUP_CONTROLLER_CPU,
-                                "cpu.shares", shares);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPU);
+
+    return virCgroupItemSetValueU64(group,
+                                    "cpu.shares", shares);
 }
 
-int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
+int virCgroupGetCpuShares(virCgroupItemPtr group, unsigned long long *shares)
 {
-    return virCgroupGetValueU64(group,
-                                VIR_CGROUP_CONTROLLER_CPU,
-                                "cpu.shares", shares);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPU);
+
+    return virCgroupItemGetValueU64(group,
+                                    "cpu.shares", shares);
 }
 
 /**
@@ -2112,16 +1584,17 @@ int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
  *
  * Returns: 0 on success
  */
-int virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
+int virCgroupSetCpuCfsPeriod(virCgroupItemPtr group, unsigned long long cfs_period)
 {
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPU);
+
     /* The cfs_period shoule be greater or equal than 1ms, and less or equal
      * than 1s.
      */
     if (cfs_period < 1000 || cfs_period > 1000000)
         return -EINVAL;
 
-    return virCgroupSetValueU64(group,
-                                VIR_CGROUP_CONTROLLER_CPU,
+    return virCgroupItemSetValueU64(group,
                                 "cpu.cfs_period_us", cfs_period);
 }
 
@@ -2133,10 +1606,11 @@ int virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
  *
  * Returns: 0 on success
  */
-int virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
+int virCgroupGetCpuCfsPeriod(virCgroupItemPtr group, unsigned long long *cfs_period)
 {
-    return virCgroupGetValueU64(group,
-                                VIR_CGROUP_CONTROLLER_CPU,
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPU);
+
+    return virCgroupItemGetValueU64(group,
                                 "cpu.cfs_period_us", cfs_period);
 }
 
@@ -2149,8 +1623,10 @@ int virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
  *
  * Returns: 0 on success
  */
-int virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
+int virCgroupSetCpuCfsQuota(virCgroupItemPtr group, long long cfs_quota)
 {
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPU);
+
     if (cfs_quota >= 0) {
         /* The cfs_quota shoule be greater or equal than 1ms */
         if (cfs_quota < 1000)
@@ -2161,9 +1637,8 @@ int virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
             return -EINVAL;
     }
 
-    return virCgroupSetValueI64(group,
-                                VIR_CGROUP_CONTROLLER_CPU,
-                                "cpu.cfs_quota_us", cfs_quota);
+    return virCgroupItemSetValueI64(group,
+                                    "cpu.cfs_quota_us", cfs_quota);
 }
 
 /**
@@ -2175,28 +1650,32 @@ int virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
  *
  * Returns: 0 on success
  */
-int virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota)
+int virCgroupGetCpuCfsQuota(virCgroupItemPtr group, long long *cfs_quota)
 {
-    return virCgroupGetValueI64(group,
-                                VIR_CGROUP_CONTROLLER_CPU,
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPU);
+
+    return virCgroupItemGetValueI64(group,
                                 "cpu.cfs_quota_us", cfs_quota);
 }
 
-int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage)
+int virCgroupGetCpuacctUsage(virCgroupItemPtr group, unsigned long long *usage)
 {
-    return virCgroupGetValueU64(group,
-                                VIR_CGROUP_CONTROLLER_CPUACCT,
-                                "cpuacct.usage", usage);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUACCT);
+
+    return virCgroupItemGetValueU64(group,
+                                    "cpuacct.usage", usage);
 }
 
-int virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage)
+int virCgroupGetCpuacctPercpuUsage(virCgroupItemPtr group, char **usage)
 {
-    return virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
-                                "cpuacct.usage_percpu", usage);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUACCT);
+
+    return virCgroupItemGetValueStr(group,
+                                    "cpuacct.usage_percpu", usage);
 }
 
 #ifdef _SC_CLK_TCK
-int virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+int virCgroupGetCpuacctStat(virCgroupItemPtr group, unsigned long long *user,
                             unsigned long long *sys)
 {
     char *str;
@@ -2204,8 +1683,10 @@ int virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
     int ret;
     static double scale = -1.0;
 
-    if ((ret = virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
-                                    "cpuacct.stat", &str)) < 0)
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_CPUACCT);
+
+    if ((ret = virCgroupItemGetValueStr(group,
+                                        "cpuacct.stat", &str)) < 0)
         return ret;
     if (!(p = STRSKIP(str, "user ")) ||
         virStrToLong_ull(p, &p, 10, user) < 0 ||
@@ -2234,7 +1715,7 @@ cleanup:
     return ret;
 }
 #else
-int virCgroupGetCpuacctStat(virCgroupPtr group ATTRIBUTE_UNUSED,
+int virCgroupGetCpuacctStat(virCgroupItemPtr group ATTRIBUTE_UNUSED,
                             unsigned long long *user ATTRIBUTE_UNUSED,
                             unsigned long long *sys ATTRIBUTE_UNUSED)
 {
@@ -2242,33 +1723,33 @@ int virCgroupGetCpuacctStat(virCgroupPtr group ATTRIBUTE_UNUSED,
 }
 #endif
 
-int virCgroupSetFreezerState(virCgroupPtr group, const char *state)
+int virCgroupSetFreezerState(virCgroupItemPtr group, const char *state)
 {
-    return virCgroupSetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_FREEZER,
-                                "freezer.state", state);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_FREEZER);
+
+    return virCgroupItemSetValueStr(group,
+                                    "freezer.state", state);
 }
 
-int virCgroupGetFreezerState(virCgroupPtr group, char **state)
+int virCgroupGetFreezerState(virCgroupItemPtr group, char **state)
 {
-    return virCgroupGetValueStr(group,
-                                VIR_CGROUP_CONTROLLER_FREEZER,
-                                "freezer.state", state);
+    sa_assert(virCgroupItemType(group) == VIR_CGROUP_CONTROLLER_FREEZER);
+
+    return virCgroupItemGetValueStr(group,
+                                    "freezer.state", state);
 }
 
 
 #if defined HAVE_KILL && defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+static int virCgroupKillInternal(virCgroupItemPtr group, int signum, virHashTablePtr pids)
 {
     int rc;
     int killedAny = 0;
     char *keypath = NULL;
     bool done = false;
     FILE *fp = NULL;
-    VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
-              group, group->path, signum, pids);
 
-    rc = virCgroupPathOfController(group, -1, "tasks", &keypath);
+    rc = virCgroupItemKeyPath(group, "tasks", &keypath);
     if (rc != 0) {
         VIR_DEBUG("No path of %s, tasks", group->path);
         return rc;
@@ -2345,7 +1826,7 @@ static void *virCgroupPidCopy(const void *name)
  *     0 : no PIDs killed
  *     1 : at least one PID killed
  */
-int virCgroupKill(virCgroupPtr group, int signum)
+int virCgroupKill(virCgroupItemPtr group, int signum)
 {
     VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
     int rc;
@@ -2368,17 +1849,17 @@ int virCgroupKill(virCgroupPtr group, int signum)
 }
 
 
-static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHashTablePtr pids, bool dormdir)
+static int virCgroupKillRecursiveInternal(virCgroupItemPtr group,
+                                          int signum,
+                                          virHashTablePtr pids)
 {
     int rc;
-    int killedAny = 0;
     char *keypath = NULL;
-    DIR *dp;
-    virCgroupPtr subgroup = NULL;
-    struct dirent *ent;
-    VIR_DEBUG("group=%p path=%s signum=%d pids=%p", group, group->path, signum, pids);
+    virCgroupItemPtr subgroup = NULL;
+    VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
+              group,group->path, signum, pids);
 
-    rc = virCgroupPathOfController(group, -1, "", &keypath);
+    rc = virCgroupItemKeyPath(group, "", &keypath);
     if (rc != 0) {
         VIR_DEBUG("No path of %s, tasks", group->path);
         return rc;
@@ -2387,52 +1868,18 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas
     if ((rc = virCgroupKillInternal(group, signum, pids)) != 0)
         return rc;
 
-    VIR_DEBUG("Iterate over children of %s", keypath);
-    if (!(dp = opendir(keypath))) {
-        rc = -errno;
-        return rc;
-    }
-
-    while ((ent = readdir(dp))) {
-        char *subpath;
-
-        if (STREQ(ent->d_name, "."))
-            continue;
-        if (STREQ(ent->d_name, ".."))
-            continue;
-        if (ent->d_type != DT_DIR)
-            continue;
-
-        VIR_DEBUG("Process subdir %s", ent->d_name);
-        if (virAsprintf(&subpath, "%s/%s", group->path, ent->d_name) < 0) {
-            rc = -ENOMEM;
-            goto cleanup;
-        }
-
-        if ((rc = virCgroupNew(subpath, &subgroup)) != 0)
-            goto cleanup;
-
-        if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0)
-            goto cleanup;
-        if (rc == 1)
-            killedAny = 1;
-
-        if (dormdir)
-            virCgroupRemove(subgroup);
-
-        virCgroupFree(&subgroup);
+    subgroup = group->children;
+    while (subgroup) {
+        rc = virCgroupKillRecursiveInternal(subgroup, signum, pids);
+        if (rc != 0)
+            return rc;
+        subgroup = subgroup->next;
     }
 
-    rc = killedAny;
-
-cleanup:
-    virCgroupFree(&subgroup);
-    closedir(dp);
-
     return rc;
 }
 
-int virCgroupKillRecursive(virCgroupPtr group, int signum)
+int virCgroupKillRecursive(virCgroupItemPtr group, int signum)
 {
     int rc;
     VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
@@ -2443,7 +1890,7 @@ int virCgroupKillRecursive(virCgroupPtr group, int signum)
                                              virCgroupPidCopy,
                                              NULL);
 
-    rc = virCgroupKillRecursiveInternal(group, signum, pids, false);
+    rc = virCgroupKillRecursiveInternal(group, signum, pids);
 
     virHashFree(pids);
 
@@ -2451,7 +1898,7 @@ int virCgroupKillRecursive(virCgroupPtr group, int signum)
 }
 
 
-int virCgroupKillPainfully(virCgroupPtr group)
+int virCgroupKillPainfully(virCgroupItemPtr group)
 {
     int i;
     int rc;
@@ -2478,18 +1925,18 @@ int virCgroupKillPainfully(virCgroupPtr group)
 }
 
 #else /* !(HAVE_KILL, HAVE_MNTENT_H, HAVE_GETMNTENT_R) */
-int virCgroupKill(virCgroupPtr group ATTRIBUTE_UNUSED,
+int virCgroupKill(virCgroupItemPtr group ATTRIBUTE_UNUSED,
                   int signum ATTRIBUTE_UNUSED)
 {
     return -ENOSYS;
 }
-int virCgroupKillRecursive(virCgroupPtr group ATTRIBUTE_UNUSED,
+int virCgroupKillRecursive(virCgroupItemPtr group ATTRIBUTE_UNUSED,
                            int signum ATTRIBUTE_UNUSED)
 {
     return -ENOSYS;
 }
 
-int virCgroupKillPainfully(virCgroupPtr group ATTRIBUTE_UNUSED)
+int virCgroupKillPainfully(virCgroupItemPtr group ATTRIBUTE_UNUSED)
 {
     return -ENOSYS;
 }
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index 0ba2430..a46b76e 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -27,8 +27,8 @@
 
 #include "virutil.h"
 
-struct virCgroup;
-typedef struct virCgroup *virCgroupPtr;
+typedef struct _virCgroup virCgroup;
+typedef virCgroup *virCgroupPtr;
 
 typedef struct _virCgroupItem virCgroupItem;
 typedef virCgroupItem *virCgroupItemPtr;
@@ -52,7 +52,7 @@ int virCgroupForDriver(const char *name,
                        bool privileged,
                        bool create);
 
-int virCgroupGetAppRoot(virCgroupPtr *group);
+virCgroupItemPtr virCgroupGetAppRoot(int type, bool privileged);
 
 int virCgroupForDomain(virCgroupPtr driver,
                        const char *name,
@@ -73,33 +73,28 @@ int virCgroupPathOfController(virCgroupPtr group,
                               const char *key,
                               char **path);
 
-int virCgroupAddTask(virCgroupPtr group, pid_t pid);
+int virCgroupItemAddTask(virCgroupItemPtr item, pid_t pid);
 
-int virCgroupAddTaskController(virCgroupPtr group,
-                               pid_t pid,
-                               int controller);
+int virCgroupItemMoveTask(virCgroupItemPtr src,
+                          virCgroupItemPtr dest);
 
-int virCgroupMoveTask(virCgroupPtr src_group,
-                      virCgroupPtr dest_group,
-                      int controller);
+int virCgroupSetBlkioWeight(virCgroupItemPtr group, unsigned int weight);
+int virCgroupGetBlkioWeight(virCgroupItemPtr group, unsigned int *weight);
 
-int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
-int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);
-
-int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+int virCgroupSetBlkioDeviceWeight(virCgroupItemPtr group,
                                   const char *path,
                                   unsigned int weight);
 
-int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb);
-int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb);
+int virCgroupSetMemory(virCgroupItemPtr group, unsigned long long kb);
+int virCgroupGetMemoryUsage(virCgroupItemPtr group, unsigned long *kb);
 
-int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb);
-int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb);
-int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb);
-int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb);
-int virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb);
-int virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb);
-int virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb);
+int virCgroupSetMemoryHardLimit(virCgroupItemPtr group, unsigned long long kb);
+int virCgroupGetMemoryHardLimit(virCgroupItemPtr group, unsigned long long *kb);
+int virCgroupSetMemorySoftLimit(virCgroupItemPtr group, unsigned long long kb);
+int virCgroupGetMemorySoftLimit(virCgroupItemPtr group, unsigned long long *kb);
+int virCgroupSetMemSwapHardLimit(virCgroupItemPtr group, unsigned long long kb);
+int virCgroupGetMemSwapHardLimit(virCgroupItemPtr group, unsigned long long *kb);
+int virCgroupGetMemSwapUsage(virCgroupItemPtr group, unsigned long long *kb);
 
 enum {
     VIR_CGROUP_DEVICE_READ  = 1,
@@ -109,65 +104,66 @@ enum {
     VIR_CGROUP_DEVICE_RWM   = VIR_CGROUP_DEVICE_RW | VIR_CGROUP_DEVICE_MKNOD,
 };
 
-int virCgroupDenyAllDevices(virCgroupPtr group);
+int virCgroupDenyAllDevices(virCgroupItemPtr group);
 
-int virCgroupAllowDevice(virCgroupPtr group,
+int virCgroupAllowDevice(virCgroupItemPtr group,
                          char type,
                          int major,
                          int minor,
                          int perms);
-int virCgroupAllowDeviceMajor(virCgroupPtr group,
+int virCgroupAllowDeviceMajor(virCgroupItemPtr group,
                               char type,
                               int major,
                               int perms);
-int virCgroupAllowDevicePath(virCgroupPtr group,
+int virCgroupAllowDevicePath(virCgroupItemPtr group,
                              const char *path,
                              int perms);
 
-int virCgroupDenyDevice(virCgroupPtr group,
+int virCgroupDenyDevice(virCgroupItemPtr group,
                         char type,
                         int major,
                         int minor,
                         int perms);
-int virCgroupDenyDeviceMajor(virCgroupPtr group,
+int virCgroupDenyDeviceMajor(virCgroupItemPtr group,
                              char type,
                              int major,
                              int perms);
-int virCgroupDenyDevicePath(virCgroupPtr group,
+int virCgroupDenyDevicePath(virCgroupItemPtr group,
                             const char *path,
                             int perms);
 
-int virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares);
-int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares);
+int virCgroupSetCpuShares(virCgroupItemPtr group, unsigned long long shares);
+int virCgroupGetCpuShares(virCgroupItemPtr group, unsigned long long *shares);
 
-int virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period);
-int virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period);
+int virCgroupSetCpuCfsPeriod(virCgroupItemPtr group, unsigned long long cfs_period);
+int virCgroupGetCpuCfsPeriod(virCgroupItemPtr group, unsigned long long *cfs_period);
 
-int virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota);
-int virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota);
+int virCgroupSetCpuCfsQuota(virCgroupItemPtr group, long long cfs_quota);
+int virCgroupGetCpuCfsQuota(virCgroupItemPtr group, long long *cfs_quota);
 
-int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage);
-int virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage);
-int virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+int virCgroupGetCpuacctUsage(virCgroupItemPtr group, unsigned long long *usage);
+int virCgroupGetCpuacctPercpuUsage(virCgroupItemPtr group, char **usage);
+int virCgroupGetCpuacctStat(virCgroupItemPtr group, unsigned long long *user,
                             unsigned long long *sys);
 
-int virCgroupSetFreezerState(virCgroupPtr group, const char *state);
-int virCgroupGetFreezerState(virCgroupPtr group, char **state);
+int virCgroupSetFreezerState(virCgroupItemPtr group, const char *state);
+int virCgroupGetFreezerState(virCgroupItemPtr group, char **state);
 
-int virCgroupSetCpusetMems(virCgroupPtr group, const char *mems);
-int virCgroupGetCpusetMems(virCgroupPtr group, char **mems);
+int virCgroupSetCpusetMems(virCgroupItemPtr group, const char *mems);
+int virCgroupGetCpusetMems(virCgroupItemPtr group, char **mems);
 
-int virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus);
-int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus);
+int virCgroupSetCpusetCpus(virCgroupItemPtr group, const char *cpus);
+int virCgroupGetCpusetCpus(virCgroupItemPtr group, char **cpus);
 
 int virCgroupRemove(virCgroupPtr group);
 
+int virCgroupNew(const char *name, virCgroupPtr parent, virCgroupPtr *group);
 void virCgroupFree(virCgroupPtr *group);
-bool virCgroupMounted(virCgroupPtr cgroup, int controller);
+bool virCgroupMounted(int controller);
 
-int virCgroupKill(virCgroupPtr group, int signum);
-int virCgroupKillRecursive(virCgroupPtr group, int signum);
-int virCgroupKillPainfully(virCgroupPtr group);
+int virCgroupKill(virCgroupItemPtr group, int signum);
+int virCgroupKillRecursive(virCgroupItemPtr group, int signum);
+int virCgroupKillPainfully(virCgroupItemPtr group);
 
 virCgroupItemPtr virCgroupItemNew(int type, const char *name, virCgroupItemPtr parent);
 void virCgroupItemFree(virCgroupItemPtr cgroupItem);
-- 
1.8.0.1.240.ge8a1f5a




More information about the libvir-list mailing list