[libvirt] [PATCH 1/3] Report full errors from virCgroupNew*

Daniel P. Berrange berrange at redhat.com
Thu Jul 18 15:00:01 UTC 2013


From: "Daniel P. Berrange" <berrange at redhat.com>

Instead of returning raw errno values, report full libvirt
errors in virCgroupNew* functions.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/libvirt_private.syms |   1 +
 src/lxc/lxc_cgroup.c     |  83 +++-----
 src/lxc/lxc_container.c  |   6 +-
 src/lxc/lxc_fuse.c       |   6 +-
 src/qemu/qemu_cgroup.c   |  87 +++-----
 src/qemu/qemu_driver.c   |  76 ++-----
 src/util/vircgroup.c     | 515 ++++++++++++++++++++++++-----------------------
 src/util/virerror.c      |  46 +++++
 src/util/virerror.h      |   4 +
 tests/vircgrouptest.c    |  44 +++-
 10 files changed, 431 insertions(+), 437 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 542424d..a31512f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1302,6 +1302,7 @@ ebtablesRemoveForwardAllowIn;
 # util/virerror.h
 virDispatchError;
 virErrorInitialize;
+virLastErrorIsSystemErrno;
 virRaiseErrorFull;
 virReportErrorHelper;
 virReportOOMErrorFull;
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index fd27601..3cec8e2 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -306,33 +306,29 @@ cleanup:
 
 int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo)
 {
-    int ret;
+    int ret = -1, rc;
     virCgroupPtr cgroup;
 
-    ret = virCgroupNewSelf(&cgroup);
-    if (ret < 0) {
-        virReportSystemError(-ret, "%s",
-                             _("Unable to get cgroup for container"));
-        return ret;
-    }
+    if (virCgroupNewSelf(&cgroup) < 0)
+        return -1;
 
-    ret = virLXCCgroupGetMemStat(cgroup, meminfo);
-    if (ret < 0) {
-        virReportSystemError(-ret, "%s",
+    rc = virLXCCgroupGetMemStat(cgroup, meminfo);
+    if (rc < 0) {
+        virReportSystemError(-rc, "%s",
                              _("Unable to get memory cgroup stat info"));
         goto cleanup;
     }
 
-    ret = virLXCCgroupGetMemTotal(cgroup, meminfo);
-    if (ret < 0) {
-        virReportSystemError(-ret, "%s",
+    rc = virLXCCgroupGetMemTotal(cgroup, meminfo);
+    if (rc < 0) {
+        virReportSystemError(-rc, "%s",
                              _("Unable to get memory cgroup total"));
         goto cleanup;
     }
 
-    ret = virLXCCgroupGetMemUsage(cgroup, meminfo);
-    if (ret < 0) {
-        virReportSystemError(-ret, "%s",
+    rc = virLXCCgroupGetMemUsage(cgroup, meminfo);
+    if (rc < 0) {
+        virReportSystemError(-rc, "%s",
                              _("Unable to get memory cgroup stat usage"));
         goto cleanup;
     }
@@ -541,7 +537,6 @@ cleanup:
 
 virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def, bool startup)
 {
-    int rc;
     virCgroupPtr parent = NULL;
     virCgroupPtr cgroup = NULL;
 
@@ -569,50 +564,30 @@ virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def, bool startup)
         }
         /* We only auto-create the default partition. In other
          * cases we expec the sysadmin/app to have done so */
-        rc = virCgroupNewPartition(def->resource->partition,
-                                   STREQ(def->resource->partition, "/machine"),
-                                   -1,
-                                   &parent);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to initialize %s cgroup"),
-                                 def->resource->partition);
+        if (virCgroupNewPartition(def->resource->partition,
+                                  STREQ(def->resource->partition, "/machine"),
+                                  -1,
+                                  &parent) < 0)
             goto cleanup;
-        }
 
-        rc = virCgroupNewDomainPartition(parent,
-                                         "lxc",
-                                         def->name,
-                                         true,
-                                         &cgroup);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create cgroup for %s"),
-                                 def->name);
+        if (virCgroupNewDomainPartition(parent,
+                                        "lxc",
+                                        def->name,
+                                        true,
+                                        &cgroup) < 0)
             goto cleanup;
-        }
     } else {
-        rc = virCgroupNewDriver("lxc",
-                                true,
-                                -1,
-                                &parent);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create cgroup for %s"),
-                                 def->name);
+        if (virCgroupNewDriver("lxc",
+                               true,
+                               -1,
+                               &parent) < 0)
             goto cleanup;
-        }
 
-        rc = virCgroupNewDomainDriver(parent,
-                                      def->name,
-                                      true,
-                                      &cgroup);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create cgroup for %s"),
-                                 def->name);
+        if (virCgroupNewDomainDriver(parent,
+                                     def->name,
+                                     true,
+                                     &cgroup) < 0)
             goto cleanup;
-        }
     }
 
 cleanup:
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 004a6ff..c033c7a 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1463,7 +1463,6 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
                                       virSecurityManagerPtr securityDriver)
 {
     virCgroupPtr cgroup = NULL;
-    int rc;
     int ret = -1;
     char *sec_mount_options;
     char *stateDir = NULL;
@@ -1475,11 +1474,8 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
 
     /* Before pivoting we need to identify any
      * cgroups controllers that are mounted */
-    if ((rc = virCgroupNewSelf(&cgroup)) != 0) {
-        virReportSystemError(-rc, "%s",
-                             _("Cannot identify cgroup placement"));
+    if (virCgroupNewSelf(&cgroup) < 0)
         goto cleanup;
-    }
 
     if (virFileResolveAllLinks(LXC_STATE_DIR, &stateDir) < 0)
         goto cleanup;
diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c
index ea4ab7a..e672b0f 100644
--- a/src/lxc/lxc_fuse.c
+++ b/src/lxc/lxc_fuse.c
@@ -139,8 +139,10 @@ static int lxcProcReadMeminfo(char *hostpath, virDomainDefPtr def,
     virBuffer buffer = VIR_BUFFER_INITIALIZER;
     virBufferPtr new_meminfo = &buffer;
 
-    if ((res = virLXCCgroupGetMeminfo(&meminfo)) < 0)
-        return res;
+    if (virLXCCgroupGetMeminfo(&meminfo) < 0) {
+        virErrorSetErrnoFromLastError();
+        return -errno;
+    }
 
     fd = fopen(hostpath, "r");
     if (fd == NULL) {
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index fbe7e6f..f40131a 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -727,64 +727,52 @@ int qemuInitCgroup(virQEMUDriverPtr driver,
         }
         /* We only auto-create the default partition. In other
          * cases we expec the sysadmin/app to have done so */
-        rc = virCgroupNewPartition(vm->def->resource->partition,
-                                   STREQ(vm->def->resource->partition, "/machine"),
-                                   cfg->cgroupControllers,
-                                   &parent);
-        if (rc != 0) {
-            if (rc == -ENXIO ||
-                rc == -EPERM ||
-                rc == -EACCES) { /* No cgroups mounts == success */
+        if (virCgroupNewPartition(vm->def->resource->partition,
+                                  STREQ(vm->def->resource->partition, "/machine"),
+                                  cfg->cgroupControllers,
+                                  &parent) < 0) {
+            virErrorPtr err = virGetLastError();
+            if (err && err->code == VIR_ERR_SYSTEM_ERROR &&
+                (err->int1 == ENXIO ||
+                 err->int1 == EPERM ||
+                 err->int1 == EACCES)) { /* No cgroups mounts == success */
                 VIR_DEBUG("No cgroups present/configured/accessible, ignoring error");
+                virResetLastError();
                 goto done;
             }
 
-            virReportSystemError(-rc,
-                                 _("Unable to initialize %s cgroup"),
-                                 vm->def->resource->partition);
             goto cleanup;
         }
 
-        rc = virCgroupNewDomainPartition(parent,
-                                         "qemu",
-                                         vm->def->name,
-                                         true,
-                                         &priv->cgroup);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create cgroup for %s"),
-                                 vm->def->name);
+        if (virCgroupNewDomainPartition(parent,
+                                        "qemu",
+                                        vm->def->name,
+                                        true,
+                                        &priv->cgroup) < 0)
             goto cleanup;
-        }
     } else {
-        rc = virCgroupNewDriver("qemu",
-                                true,
-                                cfg->cgroupControllers,
-                                &parent);
-        if (rc != 0) {
-            if (rc == -ENXIO ||
-                rc == -EPERM ||
-                rc == -EACCES) { /* No cgroups mounts == success */
+        if (virCgroupNewDriver("qemu",
+                               true,
+                               cfg->cgroupControllers,
+                               &parent) < 0) {
+            virErrorPtr err = virGetLastError();
+            if (err && err->code == VIR_ERR_SYSTEM_ERROR &&
+                (err->int1 == ENXIO ||
+                 err->int1 == EPERM ||
+                 err->int1 == EACCES)) { /* No cgroups mounts == success */
                 VIR_DEBUG("No cgroups present/configured/accessible, ignoring error");
+                virResetLastError();
                 goto done;
             }
 
-            virReportSystemError(-rc,
-                                 _("Unable to create cgroup for %s"),
-                                 vm->def->name);
             goto cleanup;
         }
 
-        rc = virCgroupNewDomainDriver(parent,
-                                      vm->def->name,
-                                      true,
-                                      &priv->cgroup);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create cgroup for %s"),
-                                 vm->def->name);
+        if (virCgroupNewDomainDriver(parent,
+                                     vm->def->name,
+                                     true,
+                                     &priv->cgroup) < 0)
             goto cleanup;
-        }
     }
 
 done:
@@ -953,14 +941,8 @@ int qemuSetupCgroupForVcpu(virDomainObjPtr vm)
     }
 
     for (i = 0; i < priv->nvcpupids; i++) {
-        rc = virCgroupNewVcpu(priv->cgroup, i, true, &cgroup_vcpu);
-        if (rc < 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to create vcpu cgroup for %s(vcpu:"
-                                   " %zu)"),
-                                 vm->def->name, i);
+        if (virCgroupNewVcpu(priv->cgroup, i, true, &cgroup_vcpu) < 0)
             goto cleanup;
-        }
 
         /* move the thread for vcpu to sub dir */
         rc = virCgroupAddTask(cgroup_vcpu, priv->vcpupids[i]);
@@ -1019,7 +1001,7 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     unsigned long long period = vm->def->cputune.emulator_period;
     long long quota = vm->def->cputune.emulator_quota;
-    int rc;
+    int rc = -1;
 
     if ((period || quota) &&
         !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
@@ -1031,13 +1013,8 @@ int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
     if (priv->cgroup == NULL)
         return 0; /* Not supported, so claim success */
 
-    rc = virCgroupNewEmulator(priv->cgroup, true, &cgroup_emulator);
-    if (rc < 0) {
-        virReportSystemError(-rc,
-                             _("Unable to create emulator cgroup for %s"),
-                             vm->def->name);
+    if (virCgroupNewEmulator(priv->cgroup, true, &cgroup_emulator) < 0)
         goto cleanup;
-    }
 
     rc = virCgroupMoveTask(priv->cgroup, cgroup_emulator);
     if (rc < 0) {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b7b066d..5c84ce4 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3940,14 +3940,8 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
             if (priv->cgroup) {
                 int rv = -1;
                 /* Create cgroup for the onlined vcpu */
-                rv = virCgroupNewVcpu(priv->cgroup, i, true, &cgroup_vcpu);
-                if (rv < 0) {
-                    virReportSystemError(-rv,
-                                         _("Unable to create vcpu cgroup for %s(vcpu:"
-                                           " %zu)"),
-                                         vm->def->name, i);
+                if (virCgroupNewVcpu(priv->cgroup, i, true, &cgroup_vcpu) < 0)
                     goto cleanup;
-                }
 
                 /* Add vcpu thread to the cgroup */
                 rv = virCgroupAddTask(cgroup_vcpu, cpupids[i]);
@@ -4008,16 +4002,8 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
             virDomainVcpuPinDefPtr vcpupin = NULL;
 
             if (priv->cgroup) {
-                int rv = -1;
-
-                rv = virCgroupNewVcpu(priv->cgroup, i, false, &cgroup_vcpu);
-                if (rv < 0) {
-                    virReportSystemError(-rv,
-                                         _("Unable to access vcpu cgroup for %s(vcpu:"
-                                           " %zu)"),
-                                         vm->def->name, i);
+                if (virCgroupNewVcpu(priv->cgroup, i, false, &cgroup_vcpu) < 0)
                     goto cleanup;
-                }
 
                 /* Remove cgroup for the offlined vcpu */
                 virCgroupRemove(cgroup_vcpu);
@@ -4358,8 +4344,9 @@ qemuDomainPinVcpuFlags(virDomainPtr dom,
 
         /* Configure the corresponding cpuset cgroup before set affinity. */
         if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
-            if (virCgroupNewVcpu(priv->cgroup, vcpu, false, &cgroup_vcpu) == 0 &&
-                qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) < 0) {
+            if (virCgroupNewVcpu(priv->cgroup, vcpu, false, &cgroup_vcpu) < 0)
+                goto cleanup;
+            if (qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) < 0) {
                 virReportError(VIR_ERR_OPERATION_INVALID,
                                _("failed to set cpuset.cpus in cgroup"
                                  " for vcpu %d"), vcpu);
@@ -4620,16 +4607,15 @@ qemuDomainPinEmulator(virDomainPtr dom,
                                        VIR_CGROUP_CONTROLLER_CPUSET)) {
                 /*
                  * Configure the corresponding cpuset cgroup.
-                 * If no cgroup for domain or hypervisor exists, do nothing.
                  */
-                if (virCgroupNewEmulator(priv->cgroup, false, &cgroup_emulator) == 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 (virCgroupNewEmulator(priv->cgroup, false, &cgroup_emulator) < 0)
+                    goto cleanup;
+                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;
                 }
             } else {
                 if (virProcessSetAffinity(pid, pcpumap) < 0) {
@@ -8590,7 +8576,6 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
     size_t i;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virCgroupPtr cgroup_vcpu = NULL;
-    int rc;
 
     if (period == 0 && quota == 0)
         return 0;
@@ -8601,14 +8586,8 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
      */
     if (priv->nvcpupids != 0 && priv->vcpupids[0] != vm->pid) {
         for (i = 0; i < priv->nvcpupids; i++) {
-            rc = virCgroupNewVcpu(cgroup, i, false, &cgroup_vcpu);
-            if (rc < 0) {
-                virReportSystemError(-rc,
-                                     _("Unable to find vcpu cgroup for %s(vcpu:"
-                                       " %zu)"),
-                                     vm->def->name, i);
+            if (virCgroupNewVcpu(cgroup, i, false, &cgroup_vcpu) < 0)
                 goto cleanup;
-            }
 
             if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
                 goto cleanup;
@@ -8630,7 +8609,6 @@ qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virCgroupPtr cgroup_emulator = NULL;
-    int rc;
 
     if (period == 0 && quota == 0)
         return 0;
@@ -8639,13 +8617,8 @@ qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
         return 0;
     }
 
-    rc = virCgroupNewEmulator(cgroup, false, &cgroup_emulator);
-    if (rc < 0) {
-        virReportSystemError(-rc,
-                             _("Unable to find emulator cgroup for %s"),
-                             vm->def->name);
+    if (virCgroupNewEmulator(cgroup, false, &cgroup_emulator) < 0)
         goto cleanup;
-    }
 
     if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
         goto cleanup;
@@ -8891,13 +8864,8 @@ qemuGetVcpusBWLive(virDomainObjPtr vm,
     }
 
     /* get period and quota for vcpu0 */
-    rc = virCgroupNewVcpu(priv->cgroup, 0, false, &cgroup_vcpu);
-    if (!cgroup_vcpu) {
-        virReportSystemError(-rc,
-                             _("Unable to find vcpu cgroup for %s(vcpu: 0)"),
-                             vm->def->name);
+    if (virCgroupNewVcpu(priv->cgroup, 0, false, &cgroup_vcpu) < 0)
         goto cleanup;
-    }
 
     rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
     if (rc < 0)
@@ -8929,13 +8897,8 @@ qemuGetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
     }
 
     /* get period and quota for emulator */
-    rc = virCgroupNewEmulator(cgroup, false, &cgroup_emulator);
-    if (!cgroup_emulator) {
-        virReportSystemError(-rc,
-                             _("Unable to find emulator cgroup for %s"),
-                             vm->def->name);
+    if (virCgroupNewEmulator(cgroup, false, &cgroup_emulator) < 0)
         goto cleanup;
-    }
 
     rc = qemuGetVcpuBWLive(cgroup_emulator, period, quota);
     if (rc < 0)
@@ -15531,11 +15494,8 @@ getSumVcpuPercpuStats(virDomainObjPtr vm,
         unsigned long long tmp;
         size_t j;
 
-        if (virCgroupNewVcpu(priv->cgroup, i, false, &group_vcpu) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("error accessing cgroup cpuacct for vcpu"));
+        if (virCgroupNewVcpu(priv->cgroup, i, false, &group_vcpu) < 0)
             goto cleanup;
-        }
 
         if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
             goto cleanup;
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 9dfe98d..12ace2e 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -116,13 +116,13 @@ static int virCgroupCopyMounts(virCgroupPtr group,
         if (!parent->controllers[i].mountPoint)
             continue;
 
-        if (VIR_STRDUP_QUIET(group->controllers[i].mountPoint,
-                             parent->controllers[i].mountPoint) < 0)
-            return -ENOMEM;
+        if (VIR_STRDUP(group->controllers[i].mountPoint,
+                       parent->controllers[i].mountPoint) < 0)
+            return -1;
 
-        if (VIR_STRDUP_QUIET(group->controllers[i].linkPoint,
-                             parent->controllers[i].linkPoint) < 0)
-            return -ENOMEM;
+        if (VIR_STRDUP(group->controllers[i].linkPoint,
+                       parent->controllers[i].linkPoint) < 0)
+            return -1;
     }
     return 0;
 }
@@ -140,8 +140,9 @@ static int virCgroupDetectMounts(virCgroupPtr group)
 
     mounts = fopen("/proc/mounts", "r");
     if (mounts == NULL) {
-        VIR_ERROR(_("Unable to open /proc/mounts"));
-        return -ENOENT;
+        virReportSystemError(errno, "%s",
+                             _("Unable to open /proc/mounts"));
+        return -1;
     }
 
     while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
@@ -171,13 +172,15 @@ static int virCgroupDetectMounts(virCgroupPtr group)
                     struct stat sb;
                     char *tmp2;
 
-                    if (VIR_STRDUP_QUIET(group->controllers[i].mountPoint,
-                                         entry.mnt_dir) < 0)
+                    if (VIR_STRDUP(group->controllers[i].mountPoint,
+                                   entry.mnt_dir) < 0)
                         goto error;
 
                     tmp2 = strrchr(entry.mnt_dir, '/');
                     if (!tmp2) {
-                        errno = EINVAL;
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("Missing '/' separator in cgroup mount '%s'"),
+                                       entry.mnt_dir);
                         goto error;
                     }
                     *tmp2 = '\0';
@@ -195,6 +198,8 @@ static int virCgroupDetectMounts(virCgroupPtr group)
                                          typestr, entry.mnt_dir, linksrc);
                                 VIR_FREE(linksrc);
                             } else {
+                                virReportSystemError(errno,
+                                                     _("Cannot stat %s"), linksrc);
                                 goto error;
                             }
                         } else {
@@ -218,7 +223,7 @@ static int virCgroupDetectMounts(virCgroupPtr group)
 
 error:
     VIR_FORCE_FCLOSE(mounts);
-    return -errno;
+    return -1;
 }
 
 
@@ -232,8 +237,8 @@ static int virCgroupCopyPlacement(virCgroupPtr group,
             continue;
 
         if (path[0] == '/') {
-            if (VIR_STRDUP_QUIET(group->controllers[i].placement, path) < 0)
-                return -ENOMEM;
+            if (VIR_STRDUP(group->controllers[i].placement, path) < 0)
+                return -1;
         } else {
             /*
              * parent=="/" + path="" => "/"
@@ -246,7 +251,7 @@ static int virCgroupCopyPlacement(virCgroupPtr group,
                             (STREQ(parent->controllers[i].placement, "/") ||
                              STREQ(path, "") ? "" : "/"),
                             path) < 0)
-                return -ENOMEM;
+                return -1;
         }
     }
 
@@ -282,11 +287,13 @@ static int virCgroupDetectPlacement(virCgroupPtr group,
     size_t i;
     FILE *mapping  = NULL;
     char line[1024];
+    int ret = -1;
 
     mapping = fopen("/proc/self/cgroup", "r");
     if (mapping == NULL) {
-        VIR_ERROR(_("Unable to open /proc/self/cgroup"));
-        return -ENOENT;
+        virReportSystemError(errno, "%s",
+                             _("Unable to open /proc/self/cgroup"));
+        return -1;
     }
 
     while (fgets(line, sizeof(line), mapping) != NULL) {
@@ -329,7 +336,7 @@ static int virCgroupDetectPlacement(virCgroupPtr group,
                                     (STREQ(selfpath, "/") ||
                                      STREQ(path, "") ? "" : "/"),
                                     path) < 0)
-                        goto no_memory;
+                        goto cleanup;
                 }
 
                 tmp = next;
@@ -337,14 +344,12 @@ static int virCgroupDetectPlacement(virCgroupPtr group,
         }
     }
 
-    VIR_FORCE_FCLOSE(mapping);
-
-    return 0;
+    ret = 0;
 
-no_memory:
+cleanup:
     VIR_FORCE_FCLOSE(mapping);
-    return -ENOMEM;
 
+    return ret;
 }
 
 static int virCgroupDetect(virCgroupPtr group,
@@ -352,19 +357,17 @@ static int virCgroupDetect(virCgroupPtr group,
                            const char *path,
                            virCgroupPtr parent)
 {
-    int rc;
     size_t i;
     size_t j;
     VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
               group, controllers, path, parent);
 
-    if (parent)
-        rc = virCgroupCopyMounts(group, parent);
-    else
-        rc = virCgroupDetectMounts(group);
-    if (rc < 0) {
-        VIR_ERROR(_("Failed to detect mounts for %s"), group->path);
-        return rc;
+    if (parent) {
+        if (virCgroupCopyMounts(group, parent) < 0)
+            return -1;
+    } else {
+        if (virCgroupDetectMounts(group) < 0)
+            return -1;
     }
 
     if (controllers >= 0) {
@@ -392,10 +395,11 @@ static int virCgroupDetect(virCgroupPtr group,
 
                     if (STREQ_NULLABLE(group->controllers[i].mountPoint,
                                        group->controllers[j].mountPoint)) {
-                        VIR_DEBUG("Controller '%s' is not wanted, but '%s' is co-mounted",
-                                  virCgroupControllerTypeToString(i),
-                                  virCgroupControllerTypeToString(j));
-                        return -EINVAL;
+                        virReportSystemError(EINVAL,
+                                             "Controller '%s' is not wanted, but '%s' is co-mounted",
+                                             virCgroupControllerTypeToString(i),
+                                             virCgroupControllerTypeToString(j));
+                        return -1;
                     }
                 }
                 VIR_FREE(group->controllers[i].mountPoint);
@@ -416,39 +420,39 @@ static int virCgroupDetect(virCgroupPtr group,
 
     /* Check that at least 1 controller is available */
     if (!controllers) {
-        VIR_DEBUG("No controllers set");
-        return -ENXIO;
+        virReportSystemError(ENXIO, "%s",
+                             _("At least one cgroup controller is required"));
+        return -1;
     }
 
-    if (parent || path[0] == '/')
-        rc = virCgroupCopyPlacement(group, path, parent);
-    else
-        rc = virCgroupDetectPlacement(group, path);
-
-    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 (parent || path[0] == '/') {
+        if (virCgroupCopyPlacement(group, path, parent) < 0)
+            return -1;
+    } else {
+        if (virCgroupDetectPlacement(group, path) < 0)
+            return -1;
+    }
 
-            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;
-            }
+    /* 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;
 
-            VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s", i,
-                      virCgroupControllerTypeToString(i),
-                      group->controllers[i].mountPoint,
-                      group->controllers[i].placement);
+        if (!group->controllers[i].placement) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Could not find placement for controller %s at %s"),
+                           virCgroupControllerTypeToString(i),
+                           group->controllers[i].placement);
+            return -1;
         }
-    } else {
-        VIR_ERROR(_("Failed to detect mapping for %s"), group->path);
+
+        VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s", i,
+                  virCgroupControllerTypeToString(i),
+                  group->controllers[i].mountPoint,
+                  group->controllers[i].placement);
     }
 
-    return rc;
+    return 0;
 }
 #endif
 
@@ -646,8 +650,9 @@ static int virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
                                   inherit_values[i],
                                   &value);
         if (rc != 0) {
-            VIR_ERROR(_("Failed to get %s %d"), inherit_values[i], rc);
-            break;
+            virReportSystemError(-rc,
+                                 _("Failed to get '%s'"), inherit_values[i]);
+            return -1;
         }
 
         VIR_DEBUG("Inherit %s = %s", inherit_values[i], value);
@@ -659,12 +664,13 @@ static int virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
         VIR_FREE(value);
 
         if (rc != 0) {
-            VIR_ERROR(_("Failed to set %s %d"), inherit_values[i], rc);
-            break;
+            virReportSystemError(-rc,
+                                 _("Failed to set '%s'"), inherit_values[i]);
+            return -1;
         }
     }
 
-    return rc;
+    return 0;
 }
 
 static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
@@ -677,8 +683,9 @@ static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
                               VIR_CGROUP_CONTROLLER_MEMORY,
                               filename, &value);
     if (rc != 0) {
-        VIR_ERROR(_("Failed to read %s/%s (%d)"), group->path, filename, rc);
-        return rc;
+        virReportSystemError(-rc,
+                             _("Failed to get '%s'"), filename);
+        return -1;
     }
 
     /* Setting twice causes error, so if already enabled, skip setting */
@@ -691,10 +698,12 @@ static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
                               filename, 1);
 
     if (rc != 0) {
-        VIR_ERROR(_("Failed to set %s/%s (%d)"), group->path, filename, rc);
+        virReportSystemError(-rc,
+                             _("Failed to set '%s'"), filename);
+        return -1;
     }
 
-    return rc;
+    return 0;
 }
 
 static int virCgroupMakeGroup(virCgroupPtr parent,
@@ -703,7 +712,7 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
                               unsigned int flags)
 {
     size_t i;
-    int rc = 0;
+    int ret = -1;
 
     VIR_DEBUG("Make group %s", group->path);
     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
@@ -716,11 +725,11 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
             continue;
         }
 
-        rc = virCgroupPathOfController(group, i, "", &path);
-        if (rc < 0) {
-            VIR_DEBUG("Failed to find path of controller %s",
-                      virCgroupControllerTypeToString(i));
-            return rc;
+        if (virCgroupPathOfController(group, i, "", &path) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Failed to find path of controller %s"),
+                           virCgroupControllerTypeToString(i));
+            return -1;
         }
         /* As of Feb 2011, clang can't see that the above function
          * call did not modify group. */
@@ -736,25 +745,23 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
                  * treat blkio as unmounted if mkdir fails. */
                 if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
                     VIR_DEBUG("Ignoring mkdir failure with blkio controller. Kernel probably too old");
-                    rc = 0;
                     VIR_FREE(group->controllers[i].mountPoint);
                     VIR_FREE(path);
                     continue;
                 } else {
-                    VIR_DEBUG("Failed to create controller %s for group",
-                              virCgroupControllerTypeToString(i));
-                    rc = -errno;
+                    virReportSystemError(errno,
+                                         _("Failed to create controller %s for group"),
+                                         virCgroupControllerTypeToString(i));
                     VIR_FREE(path);
-                    break;
+                    goto cleanup;
                 }
             }
             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) {
+                if (virCgroupCpuSetInherit(parent, group) < 0) {
                     VIR_FREE(path);
-                    break;
+                    goto cleanup;
                 }
             }
             /*
@@ -765,10 +772,9 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
                 (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) {
+                if (virCgroupSetMemoryUseHierarchy(group) < 0) {
                     VIR_FREE(path);
-                    break;
+                    goto cleanup;
                 }
             }
         }
@@ -777,7 +783,10 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
     }
 
     VIR_DEBUG("Done making controllers for group");
-    return rc;
+    ret = 0;
+
+cleanup:
+    return ret;
 }
 
 
@@ -795,51 +804,41 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
  * @parent is NULL, then the placement of the current
  * process is used.
  *
+ * Returns 0 on success, -1 on error
  */
 static int virCgroupNew(const char *path,
                         virCgroupPtr parent,
                         int controllers,
                         virCgroupPtr *group)
 {
-    int rc = 0;
-    char *typpath = NULL;
-
     VIR_DEBUG("parent=%p path=%s controllers=%d",
               parent, path, controllers);
     *group = NULL;
 
-    if (VIR_ALLOC((*group)) != 0) {
-        rc = -ENOMEM;
-        goto err;
-    }
+    if (VIR_ALLOC((*group)) < 0)
+        goto error;
 
     if (path[0] == '/' || !parent) {
-        if (VIR_STRDUP_QUIET((*group)->path, path) < 0) {
-            rc = -ENOMEM;
-            goto err;
-        }
+        if (VIR_STRDUP((*group)->path, path) < 0)
+            goto error;
     } else {
         if (virAsprintf(&(*group)->path, "%s%s%s",
                         parent->path,
                         STREQ(parent->path, "") ? "" : "/",
-                        path) < 0) {
-            rc = -ENOMEM;
-            goto err;
-        }
+                        path) < 0)
+            goto error;
     }
 
-    rc = virCgroupDetect(*group, controllers, path, parent);
-    if (rc < 0)
-        goto err;
+    if (virCgroupDetect(*group, controllers, path, parent) < 0)
+        goto error;
 
-    return rc;
-err:
+    return 0;
+
+error:
     virCgroupFree(group);
     *group = NULL;
 
-    VIR_FREE(typpath);
-
-    return rc;
+    return -1;
 }
 
 static int virCgroupAppRoot(virCgroupPtr *group,
@@ -847,22 +846,21 @@ static int virCgroupAppRoot(virCgroupPtr *group,
                             int controllers)
 {
     virCgroupPtr selfgrp = NULL;
-    int rc;
-
-    rc = virCgroupNewSelf(&selfgrp);
+    int ret = -1;
 
-    if (rc != 0)
-        return rc;
+    if (virCgroupNewSelf(&selfgrp) < 0)
+        return -1;
 
-    rc = virCgroupNew("libvirt", selfgrp, controllers, group);
-    if (rc != 0)
+    if (virCgroupNew("libvirt", selfgrp, controllers, group) < 0)
         goto cleanup;
 
-    rc = virCgroupMakeGroup(selfgrp, *group, create, VIR_CGROUP_NONE);
+    if (virCgroupMakeGroup(selfgrp, *group, create, VIR_CGROUP_NONE) < 0)
+        goto cleanup;
 
+    ret = 0;
 cleanup:
     virCgroupFree(&selfgrp);
-    return rc;
+    return ret;
 }
 #endif
 
@@ -918,8 +916,9 @@ int virCgroupRemoveRecursively(char *grppath)
 #else
 int virCgroupRemoveRecursively(char *grppath ATTRIBUTE_UNUSED)
 {
-    /* Claim no support */
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1119,7 +1118,9 @@ static int virCgroupPartitionNeedsEscaping(const char *path)
          * if cgroups are not available on a host */
         if (errno == ENOENT)
             errno = ENXIO;
-        return -errno;
+        virReportSystemError(errno, "%s",
+                             _("Cannot open /proc/cgroups"));
+        return -1;
     }
 
     /*
@@ -1152,7 +1153,8 @@ static int virCgroupPartitionNeedsEscaping(const char *path)
     }
 
     if (ferror(fp)) {
-        ret = -EIO;
+        virReportSystemError(errno, "%s",
+                             _("Error while reading /proc/cgroups"));
         goto cleanup;
     }
 
@@ -1172,18 +1174,18 @@ static int virCgroupPartitionEscape(char **path)
         return rc;
 
     if (VIR_INSERT_ELEMENT(*path, 0, len, escape) < 0)
-        return -ENOMEM;
+        return -1;
 
     return 0;
 }
 
 static int virCgroupSetPartitionSuffix(const char *path, char **res)
 {
-    char **tokens = virStringSplit(path, "/", 0);
+    char **tokens;
     size_t i;
     int ret = -1;
 
-    if (!tokens)
+    if (!(tokens = virStringSplit(path, "/", 0)))
         return ret;
 
     for (i = 0; tokens[i] != NULL; i++) {
@@ -1202,23 +1204,17 @@ static int virCgroupSetPartitionSuffix(const char *path, char **res)
         if (STRNEQ(tokens[i], "") &&
             !strchr(tokens[i], '.')) {
             if (VIR_REALLOC_N(tokens[i],
-                              strlen(tokens[i]) + strlen(".partition") + 1) < 0) {
-                ret = -ENOMEM;
+                              strlen(tokens[i]) + strlen(".partition") + 1) < 0)
                 goto cleanup;
-            }
             strcat(tokens[i], ".partition");
         }
 
-        ret = virCgroupPartitionEscape(&(tokens[i]));
-        if (ret < 0) {
+        if (virCgroupPartitionEscape(&(tokens[i])) < 0)
             goto cleanup;
-        }
     }
 
-    if (!(*res = virStringJoin((const char **)tokens, "/"))) {
-        ret = -ENOMEM;
+    if (!(*res = virStringJoin((const char **)tokens, "/")))
         goto cleanup;
-    }
 
     ret = 0;
 
@@ -1236,64 +1232,59 @@ cleanup:
  * Creates a new cgroup to represent the resource
  * partition path identified by @name.
  *
- * Returns 0 on success, -errno on failure
+ * Returns 0 on success, -1 on failure
  */
 int virCgroupNewPartition(const char *path,
                           bool create,
                           int controllers,
                           virCgroupPtr *group)
 {
-    int rc;
+    int ret = -1;
     char *parentPath = NULL;
     virCgroupPtr parent = NULL;
     char *newpath = NULL;
     VIR_DEBUG("path=%s create=%d controllers=%x",
               path, create, controllers);
 
-    if (path[0] != '/')
-        return -EINVAL;
+    if (path[0] != '/') {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Partition path '%s' must start with '/'"),
+                       path);
+        return -1;
+    }
 
-    /* XXX convert all cgroups APIs to use error report
-     * APIs instead of returning errno */
-    rc = virCgroupSetPartitionSuffix(path, &newpath);
-    if (rc < 0) {
-        virResetLastError();
+    if (virCgroupSetPartitionSuffix(path, &newpath) < 0)
         goto cleanup;
-    }
 
-    rc = virCgroupNew(newpath, NULL, controllers, group);
-    if (rc != 0)
+    if (virCgroupNew(newpath, NULL, controllers, group) < 0)
         goto cleanup;
 
     if (STRNEQ(newpath, "/")) {
         char *tmp;
-        if (VIR_STRDUP_QUIET(parentPath, newpath) < 0) {
-            rc = -ENOMEM;
+        if (VIR_STRDUP(parentPath, newpath) < 0)
             goto cleanup;
-        }
 
         tmp = strrchr(parentPath, '/');
         tmp++;
         *tmp = '\0';
 
-        rc = virCgroupNew(parentPath, NULL, controllers, &parent);
-        if (rc != 0)
+        if (virCgroupNew(parentPath, NULL, controllers, &parent) < 0)
             goto cleanup;
 
-        rc = virCgroupMakeGroup(parent, *group, create, VIR_CGROUP_NONE);
-        if (rc != 0) {
+        if (virCgroupMakeGroup(parent, *group, create, VIR_CGROUP_NONE) < 0) {
             virCgroupRemove(*group);
             goto cleanup;
         }
     }
 
+    ret = 0;
 cleanup:
-    if (rc != 0)
+    if (ret != 0)
         virCgroupFree(group);
     virCgroupFree(&parent);
     VIR_FREE(parentPath);
     VIR_FREE(newpath);
-    return rc;
+    return ret;
 }
 #else
 int virCgroupNewPartition(const char *path ATTRIBUTE_UNUSED,
@@ -1301,8 +1292,9 @@ int virCgroupNewPartition(const char *path ATTRIBUTE_UNUSED,
                           int controllers ATTRIBUTE_UNUSED,
                           virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    /* Claim no support */
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1312,7 +1304,7 @@ int virCgroupNewPartition(const char *path ATTRIBUTE_UNUSED,
  * @name: name of this driver (e.g., xen, qemu, lxc)
  * @group: Pointer to returned virCgroupPtr
  *
- * Returns 0 on success
+ * Returns 0 on success, or -1 on error
  */
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
 int virCgroupNewDriver(const char *name,
@@ -1320,26 +1312,27 @@ int virCgroupNewDriver(const char *name,
                        int controllers,
                        virCgroupPtr *group)
 {
-    int rc;
+    int ret = -1;
     virCgroupPtr rootgrp = NULL;
 
-    rc = virCgroupAppRoot(&rootgrp,
-                          create, controllers);
-    if (rc != 0)
-        goto out;
+    if (virCgroupAppRoot(&rootgrp,
+                         create, controllers) < 0)
+        goto cleanup;
 
-    rc = virCgroupNew(name, rootgrp, -1, group);
-    if (rc == 0) {
-        rc = virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE);
-        if (rc != 0) {
-            virCgroupRemove(*group);
-            virCgroupFree(group);
-        }
+    if (virCgroupNew(name, rootgrp, -1, group) < 0)
+        goto cleanup;
+
+    if (virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE) < 0) {
+        virCgroupRemove(*group);
+        virCgroupFree(group);
+        goto cleanup;
     }
-out:
-    virCgroupFree(&rootgrp);
 
-    return rc;
+    ret = 0;
+
+cleanup:
+    virCgroupFree(&rootgrp);
+    return ret;
 }
 #else
 int virCgroupNewDriver(const char *name ATTRIBUTE_UNUSED,
@@ -1347,8 +1340,9 @@ int virCgroupNewDriver(const char *name ATTRIBUTE_UNUSED,
                        int controllers ATTRIBUTE_UNUSED,
                        virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    /* Claim no support */
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1360,7 +1354,7 @@ int virCgroupNewDriver(const char *name ATTRIBUTE_UNUSED,
 * Obtain a cgroup representing the config of the
 * current process
 *
-* Returns 0 on success
+* Returns 0 on success, or -1 on error
 */
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
 int virCgroupNewSelf(virCgroupPtr *group)
@@ -1370,7 +1364,9 @@ int virCgroupNewSelf(virCgroupPtr *group)
 #else
 int virCgroupNewSelf(virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1381,7 +1377,7 @@ int virCgroupNewSelf(virCgroupPtr *group ATTRIBUTE_UNUSED)
  * @name: name of the domain
  * @group: Pointer to returned virCgroupPtr
  *
- * Returns 0 on success
+ * Returns 0 on success, or -1 on error
  */
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
 int virCgroupNewDomainDriver(virCgroupPtr driver,
@@ -1389,29 +1385,30 @@ int virCgroupNewDomainDriver(virCgroupPtr driver,
                              bool create,
                              virCgroupPtr *group)
 {
-    int rc;
+    int ret = -1;
 
-    rc = virCgroupNew(name, driver, -1, group);
-
-    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) {
-            virCgroupRemove(*group);
-            virCgroupFree(group);
-        }
+    if (virCgroupNew(name, driver, -1, group) < 0)
+        goto cleanup;
+
+    /*
+     * 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.
+     */
+    if (virCgroupMakeGroup(driver, *group, create, VIR_CGROUP_MEM_HIERACHY) < 0) {
+        virCgroupRemove(*group);
+        virCgroupFree(group);
+        goto cleanup;
     }
 
-    return rc;
+    ret = 0;
+cleanup:
+    return ret;
 }
 #else
 int virCgroupNewDomainDriver(virCgroupPtr driver ATTRIBUTE_UNUSED,
@@ -1419,7 +1416,9 @@ int virCgroupNewDomainDriver(virCgroupPtr driver ATTRIBUTE_UNUSED,
                              bool create ATTRIBUTE_UNUSED,
                              virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1431,7 +1430,7 @@ int virCgroupNewDomainDriver(virCgroupPtr driver ATTRIBUTE_UNUSED,
  * @name: name of the domain
  * @group: Pointer to returned virCgroupPtr
  *
- * Returns 0 on success
+ * Returns 0 on success, or -1 on error
  */
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
 int virCgroupNewDomainPartition(virCgroupPtr partition,
@@ -1440,38 +1439,40 @@ int virCgroupNewDomainPartition(virCgroupPtr partition,
                                 bool create,
                                 virCgroupPtr *group)
 {
-    int rc;
+    int ret = -1;
     char *grpname = NULL;
 
     if (virAsprintf(&grpname, "%s.libvirt-%s",
                     name, driver) < 0)
-        return -ENOMEM;
+        goto cleanup;
 
-    if ((rc = virCgroupPartitionEscape(&grpname)) < 0)
-        return rc;
+    if (virCgroupPartitionEscape(&grpname) < 0)
+        goto cleanup;
 
-    rc = virCgroupNew(grpname, partition, -1, group);
-
-    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(partition, *group, create, VIR_CGROUP_MEM_HIERACHY);
-        if (rc != 0) {
-            virCgroupRemove(*group);
-            virCgroupFree(group);
-        }
+    if (virCgroupNew(grpname, partition, -1, group) < 0)
+        goto cleanup;
+
+    /*
+     * 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.
+     */
+    if (virCgroupMakeGroup(partition, *group, create, VIR_CGROUP_MEM_HIERACHY) < 0) {
+        virCgroupRemove(*group);
+        virCgroupFree(group);
+        goto cleanup;
     }
 
+    ret = 0;
+
+cleanup:
     VIR_FREE(grpname);
-    return rc;
+    return ret;
 }
 #else
 int virCgroupNewDomainPartition(virCgroupPtr partition ATTRIBUTE_UNUSED,
@@ -1480,7 +1481,9 @@ int virCgroupNewDomainPartition(virCgroupPtr partition ATTRIBUTE_UNUSED,
                                 bool create ATTRIBUTE_UNUSED,
                                 virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1492,7 +1495,7 @@ int virCgroupNewDomainPartition(virCgroupPtr partition ATTRIBUTE_UNUSED,
  * @create: true to create if not already existing
  * @group: Pointer to returned virCgroupPtr
  *
- * Returns 0 on success
+ * Returns 0 on success, or -1 on error
  */
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
 int virCgroupNewVcpu(virCgroupPtr domain,
@@ -1500,29 +1503,30 @@ int virCgroupNewVcpu(virCgroupPtr domain,
                      bool create,
                      virCgroupPtr *group)
 {
-    int rc;
-    char *name;
+    int ret = -1;
+    char *name = NULL;
     int controllers;
 
     if (virAsprintf(&name, "vcpu%d", vcpuid) < 0)
-        return -ENOMEM;
+        goto cleanup;
 
     controllers = ((1 << VIR_CGROUP_CONTROLLER_CPU) |
                    (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
                    (1 << VIR_CGROUP_CONTROLLER_CPUSET));
 
-    rc = virCgroupNew(name, domain, controllers, group);
-    VIR_FREE(name);
+    if (virCgroupNew(name, domain, controllers, group) < 0)
+        goto cleanup;
 
-    if (rc == 0) {
-        rc = virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE);
-        if (rc != 0) {
-            virCgroupRemove(*group);
-            virCgroupFree(group);
-        }
+    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
+        virCgroupRemove(*group);
+        virCgroupFree(group);
+        goto cleanup;
     }
 
-    return rc;
+    ret = 0;
+cleanup:
+    VIR_FREE(name);
+    return ret;
 }
 #else
 int virCgroupNewVcpu(virCgroupPtr domain ATTRIBUTE_UNUSED,
@@ -1530,7 +1534,9 @@ int virCgroupNewVcpu(virCgroupPtr domain ATTRIBUTE_UNUSED,
                      bool create ATTRIBUTE_UNUSED,
                      virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 #endif
 
@@ -1541,38 +1547,41 @@ int virCgroupNewVcpu(virCgroupPtr domain ATTRIBUTE_UNUSED,
  * @create: true to create if not already existing
  * @group: Pointer to returned virCgroupPtr
  *
- * Returns: 0 on success or -errno on failure
+ * Returns: 0 on success or -1 on error
  */
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
 int virCgroupNewEmulator(virCgroupPtr domain,
                          bool create,
                          virCgroupPtr *group)
 {
-    int rc;
+    int ret = -1;
     int controllers;
 
     controllers = ((1 << VIR_CGROUP_CONTROLLER_CPU) |
                    (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
                    (1 << VIR_CGROUP_CONTROLLER_CPUSET));
 
-    rc = virCgroupNew("emulator", domain, controllers, group);
+    if (virCgroupNew("emulator", domain, controllers, group) < 0)
+        goto cleanup;
 
-    if (rc == 0) {
-        rc = virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE);
-        if (rc != 0) {
-            virCgroupRemove(*group);
-            virCgroupFree(group);
-        }
+    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
+        virCgroupRemove(*group);
+        virCgroupFree(group);
+        goto cleanup;
     }
 
-    return rc;
+    ret = 0;
+cleanup:
+    return ret;
 }
 #else
 int virCgroupNewEmulator(virCgroupPtr domain ATTRIBUTE_UNUSED,
                          bool create ATTRIBUTE_UNUSED,
                          virCgroupPtr *group ATTRIBUTE_UNUSED)
 {
-    return -ENXIO;
+    virReportSystemError(ENXIO, "%s",
+                         _("Control groups not supported on this platform"));
+    return -1;
 }
 
 #endif
@@ -2454,8 +2463,10 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas
 
         VIR_DEBUG("Process subdir %s", ent->d_name);
 
-        if ((rc = virCgroupNew(ent->d_name, group, -1, &subgroup)) != 0)
+        if (virCgroupNew(ent->d_name, group, -1, &subgroup) < 0) {
+            rc = -EIO;
             goto cleanup;
+        }
 
         if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0)
             goto cleanup;
diff --git a/src/util/virerror.c b/src/util/virerror.c
index ce3ab85..de4479e 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -1397,3 +1397,49 @@ void virSetErrorLogPriorityFunc(virErrorLogPriorityFunc func)
 {
     virErrorLogPriorityFilter = func;
 }
+
+
+/**
+ * virErrorSetErrnoFromLastError:
+ *
+ * If the last error had a code of VIR_ERR_SYSTEM_ERROR
+ * then set errno to the value saved in the error object.
+ *
+ * If the last error had a code of VIR_ERR_NO_MEMORY
+ * then set errno to ENOMEM
+ *
+ * Otherwise set errno to EIO.
+ */
+void virErrorSetErrnoFromLastError(void)
+{
+    virErrorPtr err = virGetLastError();
+    if (err && err->code == VIR_ERR_SYSTEM_ERROR) {
+        errno = err->int1;
+    } else if (err && err->code == VIR_ERR_NO_MEMORY) {
+        errno = ENOMEM;
+    } else {
+        errno = EIO;
+    }
+}
+
+
+/**
+ * virLastErrorIsSystemErrno:
+ * @errnum: the errno value
+ *
+ * Check if the last error reported is a system
+ * error with the specific errno value
+ *
+ * Returns true if the last errr was a system error with errno == @errnum
+ */
+bool virLastErrorIsSystemErrno(int errnum)
+{
+    virErrorPtr err = virGetLastError();
+    if (!err)
+        return false;
+    if (err->code != VIR_ERR_SYSTEM_ERROR)
+        return false;
+    if (err->int1 != errnum)
+        return false;
+    return true;
+}
diff --git a/src/util/virerror.h b/src/util/virerror.h
index 332a5eb..b4f2f04 100644
--- a/src/util/virerror.h
+++ b/src/util/virerror.h
@@ -164,4 +164,8 @@ const char *virStrerror(int theerrno, char *errBuf, size_t errBufLen);
 typedef int (*virErrorLogPriorityFunc)(virErrorPtr, int);
 void virSetErrorLogPriorityFunc(virErrorLogPriorityFunc func);
 
+void virErrorSetErrnoFromLastError(void);
+
+bool virLastErrorIsSystemErrno(int errnum);
+
 #endif
diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
index 22b40b4..21529a0 100644
--- a/tests/vircgrouptest.c
+++ b/tests/vircgrouptest.c
@@ -136,6 +136,18 @@ cleanup:
 }
 
 
+#define ENSURE_ERRNO(en)                                            \
+    do {                                                            \
+    if (!virLastErrorIsSystemErrno(en)) {                           \
+        virErrorPtr err = virGetLastError();                        \
+        fprintf(stderr, "Did not get " #en " error code: %d\n",     \
+                err ? err->code : 0);                               \
+        goto cleanup;                                               \
+    } } while (0)
+
+    /* Asking for impossible combination since CPU is co-mounted */
+
+
 static int testCgroupNewForDriver(const void *args ATTRIBUTE_UNUSED)
 {
     virCgroupPtr cgroup = NULL;
@@ -160,27 +172,30 @@ static int testCgroupNewForDriver(const void *args ATTRIBUTE_UNUSED)
         [VIR_CGROUP_CONTROLLER_BLKIO] = "/libvirt/lxc",
     };
 
-    if ((rv = virCgroupNewDriver("lxc", false, -1, &cgroup)) != -ENOENT) {
+    if ((rv = virCgroupNewDriver("lxc", false, -1, &cgroup)) != -1) {
         fprintf(stderr, "Unexpected found LXC cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENOENT);
 
-    /* Asking for impossible combination since CPU is co-mounted */
     if ((rv = virCgroupNewDriver("lxc", true,
                                  (1 << VIR_CGROUP_CONTROLLER_CPU),
-                                 &cgroup)) != -EINVAL) {
+                                 &cgroup)) != -1) {
         fprintf(stderr, "Should not have created LXC cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(EINVAL);
 
     /* Asking for impossible combination since devices is not mounted */
     if ((rv = virCgroupNewDriver("lxc", true,
                                  (1 << VIR_CGROUP_CONTROLLER_DEVICES),
-                                 &cgroup)) != -ENXIO) {
+                                 &cgroup)) != -1) {
         fprintf(stderr, "Should not have created LXC cgroup: %d\n", -rv);
         goto cleanup;
     }
 
+    ENSURE_ERRNO(ENXIO);
+
     /* Asking for small combination since devices is not mounted */
     if ((rv = virCgroupNewDriver("lxc", true,
                                  (1 << VIR_CGROUP_CONTROLLER_CPU) |
@@ -264,26 +279,29 @@ static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED)
         [VIR_CGROUP_CONTROLLER_BLKIO] = "/virtualmachines.partition",
     };
 
-    if ((rv = virCgroupNewPartition("/virtualmachines", false, -1, &cgroup)) != -ENOENT) {
+    if ((rv = virCgroupNewPartition("/virtualmachines", false, -1, &cgroup)) != -1) {
         fprintf(stderr, "Unexpected found /virtualmachines cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENOENT);
 
     /* Asking for impossible combination since CPU is co-mounted */
     if ((rv = virCgroupNewPartition("/virtualmachines", true,
                                     (1 << VIR_CGROUP_CONTROLLER_CPU),
-                                    &cgroup)) != -EINVAL) {
+                                    &cgroup)) != -1) {
         fprintf(stderr, "Should not have created /virtualmachines cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(EINVAL);
 
     /* Asking for impossible combination since devices is not mounted */
     if ((rv = virCgroupNewPartition("/virtualmachines", true,
                                     (1 << VIR_CGROUP_CONTROLLER_DEVICES),
-                                    &cgroup)) != -ENXIO) {
+                                    &cgroup)) != -1) {
         fprintf(stderr, "Should not have created /virtualmachines cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENXIO);
 
     /* Asking for small combination since devices is not mounted */
     if ((rv = virCgroupNewPartition("/virtualmachines", true,
@@ -324,16 +342,18 @@ static int testCgroupNewForPartitionNested(const void *args ATTRIBUTE_UNUSED)
         [VIR_CGROUP_CONTROLLER_BLKIO] = "/deployment.partition/production.partition",
     };
 
-    if ((rv = virCgroupNewPartition("/deployment/production", false, -1, &cgroup)) != -ENOENT) {
+    if ((rv = virCgroupNewPartition("/deployment/production", false, -1, &cgroup)) != -1) {
         fprintf(stderr, "Unexpected found /deployment/production cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENOENT);
 
     /* Should not work, since we require /deployment to be pre-created */
-    if ((rv = virCgroupNewPartition("/deployment/production", true, -1, &cgroup)) != -ENOENT) {
+    if ((rv = virCgroupNewPartition("/deployment/production", true, -1, &cgroup)) != -1) {
         fprintf(stderr, "Unexpected created /deployment/production cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENOENT);
 
     if ((rv = virCgroupNewPartition("/deployment", true, -1, &cgroup)) != 0) {
         fprintf(stderr, "Failed to create /deployment cgroup: %d\n", -rv);
@@ -370,16 +390,18 @@ static int testCgroupNewForPartitionNestedDeep(const void *args ATTRIBUTE_UNUSED
         [VIR_CGROUP_CONTROLLER_BLKIO] = "/user/berrange.user/production.partition",
     };
 
-    if ((rv = virCgroupNewPartition("/user/berrange.user/production", false, -1, &cgroup)) != -ENOENT) {
+    if ((rv = virCgroupNewPartition("/user/berrange.user/production", false, -1, &cgroup)) != -1) {
         fprintf(stderr, "Unexpected found /user/berrange.user/production cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENOENT);
 
     /* Should not work, since we require /user/berrange.user to be pre-created */
-    if ((rv = virCgroupNewPartition("/user/berrange.user/production", true, -1, &cgroup)) != -ENOENT) {
+    if ((rv = virCgroupNewPartition("/user/berrange.user/production", true, -1, &cgroup)) != -1) {
         fprintf(stderr, "Unexpected created /user/berrange.user/production cgroup: %d\n", -rv);
         goto cleanup;
     }
+    ENSURE_ERRNO(ENOENT);
 
     if ((rv = virCgroupNewPartition("/user", true, -1, &cgroup)) != 0) {
         fprintf(stderr, "Failed to create /user/berrange.user cgroup: %d\n", -rv);
-- 
1.8.1.4




More information about the libvir-list mailing list