[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v2 4/9] use virBitmap to store cpu affinity info



---
 src/lxc/lxc_controller.c |   23 +++++--------
 src/qemu/qemu_driver.c   |   62 ++++++++++++++++++++-------------
 src/qemu/qemu_process.c  |   86 ++++++++--------------------------------------
 src/util/processinfo.c   |   36 ++++++++++---------
 src/util/processinfo.h   |    9 ++---
 5 files changed, 84 insertions(+), 132 deletions(-)

diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index e5aea11..ac8ce94 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -493,8 +493,7 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr ctrl)
 {
     int i, hostcpus, maxcpu = CPU_SETSIZE;
     virNodeInfo nodeinfo;
-    unsigned char *cpumap;
-    int cpumaplen;
+    virBitmapPtr cpumap;
 
     VIR_DEBUG("Setting CPU affinity");
 
@@ -507,37 +506,33 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr ctrl)
     if (maxcpu > hostcpus)
         maxcpu = hostcpus;
 
-    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
-    if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
-        virReportOOMError();
+    cpumap = virBitmapAlloc(maxcpu);
+    if (!cpumap)
         return -1;
-    }
 
     if (ctrl->def->cpumask) {
         /* XXX why don't we keep 'cpumask' in the libvirt cpumap
          * format to start with ?!?! */
         for (i = 0 ; i < maxcpu && i < ctrl->def->cpumasklen ; i++)
             if (ctrl->def->cpumask[i])
-                VIR_USE_CPU(cpumap, i);
+                ignore_value(virBitmapSetBit(cpumap, i));
     } else {
         /* You may think this is redundant, but we can't assume libvirtd
          * itself is running on all pCPUs, so we need to explicitly set
          * the spawned LXC instance to all pCPUs if no map is given in
          * its config file */
-        for (i = 0 ; i < maxcpu ; i++)
-            VIR_USE_CPU(cpumap, i);
+        virBitmapSetAll(cpumap);
     }
 
-    /* We are pressuming we are running between fork/exec of LXC
+    /* We are presuming we are running between fork/exec of LXC
      * so use '0' to indicate our own process ID. No threads are
      * running at this point
      */
-    if (virProcessInfoSetAffinity(0, /* Self */
-                                  cpumap, cpumaplen, maxcpu) < 0) {
-        VIR_FREE(cpumap);
+    if (virProcessInfoSetAffinity(0 /* Self */, cpumap) < 0) {
+        virBitmapFree(cpumap);
         return -1;
     }
-    VIR_FREE(cpumap);
+    virBitmapFree(cpumap);
 
     return 0;
 }
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bdff4bb..e96c3b8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -92,6 +92,7 @@
 #include "virnodesuspend.h"
 #include "virtime.h"
 #include "virtypedparam.h"
+#include "bitmap.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -3710,10 +3711,10 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
     virNodeInfo nodeinfo;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
-    bool canResetting = true;
+    bool doReset = false;
     int newVcpuPinNum = 0;
     virDomainVcpuPinDefPtr *newVcpuPin = NULL;
-    int pcpu;
+    virBitmapPtr pcpumap = NULL;
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -3749,15 +3750,16 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
     maxcpu = maplen * 8;
     if (maxcpu > hostcpus)
         maxcpu = hostcpus;
+
+    pcpumap = virBitmapAllocFromData(cpumap, maplen);
+    if (!pcpumap)
+        goto cleanup;
+
     /* pinning to all physical cpus means resetting,
      * so check if we can reset setting.
      */
-    for (pcpu = 0; pcpu < hostcpus; pcpu++) {
-        if ((cpumap[pcpu/8] & (1 << (pcpu % 8))) == 0) {
-            canResetting = false;
-            break;
-        }
-    }
+    if (virBitmapIsAllSet(pcpumap))
+        doReset = true;
 
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
 
@@ -3800,8 +3802,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
                 goto cleanup;
             }
         } else {
-            if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
-                                          cpumap, maplen, maxcpu) < 0) {
+            if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], pcpumap) < 0) {
                 virReportError(VIR_ERR_SYSTEM_ERROR,
                                _("failed to set cpu affinity for vcpu %d"),
                                vcpu);
@@ -3809,7 +3810,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
             }
         }
 
-        if (canResetting) {
+        if (doReset) {
             if (virDomainVcpuPinDel(vm->def, vcpu) < 0) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("failed to delete vcpupin xml of "
@@ -3834,7 +3835,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
 
     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
 
-        if (canResetting) {
+        if (doReset) {
             if (virDomainVcpuPinDel(persistentDef, vcpu) < 0) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("failed to delete vcpupin xml of "
@@ -3874,6 +3875,7 @@ cleanup:
         virCgroupFree(&cgroup_dom);
     if (vm)
         virDomainObjUnlock(vm);
+    virBitmapFree(pcpumap);
     return ret;
 }
 
@@ -3992,10 +3994,10 @@ qemudDomainPinEmulator(virDomainPtr dom,
     virNodeInfo nodeinfo;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
-    bool canResetting = true;
-    int pcpu;
+    bool doReset = false;
     int newVcpuPinNum = 0;
     virDomainVcpuPinDefPtr *newVcpuPin = NULL;
+    virBitmapPtr pcpumap = NULL;
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -4024,15 +4026,16 @@ qemudDomainPinEmulator(virDomainPtr dom,
     maxcpu = maplen * 8;
     if (maxcpu > hostcpus)
         maxcpu = hostcpus;
+
+    pcpumap = virBitmapAllocFromData(cpumap, maplen);
+    if (!pcpumap)
+        goto cleanup;
+
     /* pinning to all physical cpus means resetting,
      * so check if we can reset setting.
      */
-    for (pcpu = 0; pcpu < hostcpus; pcpu++) {
-        if ((cpumap[pcpu/8] & (1 << (pcpu % 8))) == 0) {
-            canResetting = false;
-            break;
-        }
-    }
+    if (virBitmapIsAllSet(pcpumap))
+        doReset = true;
 
     pid = vm->pid;
 
@@ -4070,7 +4073,7 @@ qemudDomainPinEmulator(virDomainPtr dom,
                     }
                 }
             } else {
-                if (virProcessInfoSetAffinity(pid, cpumap, maplen, maxcpu) < 0) {
+                if (virProcessInfoSetAffinity(pid, pcpumap) < 0) {
                     virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
                                    _("failed to set cpu affinity for "
                                      "emulator threads"));
@@ -4078,7 +4081,7 @@ qemudDomainPinEmulator(virDomainPtr dom,
                 }
             }
 
-            if (canResetting) {
+            if (doReset) {
                 if (virDomainEmulatorPinDel(vm->def) < 0) {
                     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                    _("failed to delete emulatorpin xml of "
@@ -4105,7 +4108,7 @@ qemudDomainPinEmulator(virDomainPtr dom,
 
     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
 
-        if (canResetting) {
+        if (doReset) {
             if (virDomainEmulatorPinDel(persistentDef) < 0) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("failed to delete emulatorpin xml of "
@@ -4132,6 +4135,7 @@ cleanup:
         virCgroupFree(&cgroup_emulator);
     if (cgroup_dom)
         virCgroupFree(&cgroup_dom);
+    virBitmapFree(pcpumap);
 
     if (vm)
         virDomainObjUnlock(vm);
@@ -4286,10 +4290,20 @@ qemudDomainGetVcpus(virDomainPtr dom,
             if (priv->vcpupids != NULL) {
                 for (v = 0 ; v < maxinfo ; v++) {
                     unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
+                    virBitmapPtr map = NULL;
+                    char *tmpmap = NULL;
+                    int tmpmapLen = 0;
 
                     if (virProcessInfoGetAffinity(priv->vcpupids[v],
-                                                  cpumap, maplen, maxcpu) < 0)
+                                                  &map, maxcpu) < 0)
                         goto cleanup;
+                    virBitmapToData(map, &tmpmap, &tmpmapLen);
+                    if (tmpmapLen > maplen)
+                        tmpmapLen = maplen;
+                    memcpy(cpumap, tmpmap, tmpmapLen);
+
+                    VIR_FREE(tmpmap);
+                    virBitmapFree(map);
                 }
             } else {
                 virReportError(VIR_ERR_OPERATION_INVALID,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4e9aaef..8fe9fa1 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1845,8 +1845,7 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
     int ret = -1;
     int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
     virNodeInfo nodeinfo;
-    unsigned char *cpumap;
-    int cpumaplen;
+    virBitmapPtr cpumap;
 
     VIR_DEBUG("Setting CPU affinity");
 
@@ -1859,8 +1858,8 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
     if (maxcpu > hostcpus)
         maxcpu = hostcpus;
 
-    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
-    if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
+    cpumap = virBitmapAlloc(maxcpu);
+    if (!cpumap) {
         virReportOOMError();
         return -1;
     }
@@ -1873,7 +1872,8 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
             int cur_ncpus = driver->caps->host.numaCell[i]->ncpus;
             if (nodemask[i]) {
                 for (j = 0; j < cur_ncpus; j++)
-                    VIR_USE_CPU(cpumap, driver->caps->host.numaCell[i]->cpus[j]);
+                    ignore_value(virBitmapSetBit(cpumap,
+                                                 driver->caps->host.numaCell[i]->cpus[j]));
             }
         }
     } else {
@@ -1883,14 +1883,13 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
              * format to start with ?!?! */
             for (i = 0 ; i < maxcpu && i < vm->def->cpumasklen ; i++)
                 if (vm->def->cpumask[i])
-                    VIR_USE_CPU(cpumap, i);
+                    ignore_value(virBitmapSetBit(cpumap, i));
         } else {
             /* You may think this is redundant, but we can't assume libvirtd
              * itself is running on all pCPUs, so we need to explicitly set
              * the spawned QEMU instance to all pCPUs if no map is given in
              * its config file */
-            for (i = 0 ; i < maxcpu ; i++)
-                VIR_USE_CPU(cpumap, i);
+            virBitmapSetAll(cpumap);
         }
     }
 
@@ -1898,14 +1897,13 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
      * so use '0' to indicate our own process ID. No threads are
      * running at this point
      */
-    if (virProcessInfoSetAffinity(0, /* Self */
-                                  cpumap, cpumaplen, maxcpu) < 0)
+    if (virProcessInfoSetAffinity(0 /* Self */, cpumap) < 0)
         goto cleanup;
 
     ret = 0;
 
 cleanup:
-    VIR_FREE(cpumap);
+    virBitmapFree(cpumap);
     return ret;
 }
 
@@ -1950,12 +1948,8 @@ qemuProcessSetVcpuAffinites(virConnectPtr conn,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainDefPtr def = vm->def;
     virNodeInfo nodeinfo;
-    pid_t vcpupid;
-    virBitmapPtr cpumask;
-    int vcpu, cpumaplen, hostcpus, maxcpu, n;
-    unsigned char *cpumap = NULL;
+    int vcpu, n;
     int ret = -1;
-    bool result;
 
     if (virNodeGetInfo(conn, &nodeinfo) != 0) {
         return  -1;
@@ -1970,41 +1964,17 @@ qemuProcessSetVcpuAffinites(virConnectPtr conn,
         return -1;
     }
 
-    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
-    cpumaplen = VIR_CPU_MAPLEN(hostcpus);
-    maxcpu = cpumaplen * 8;
-
-    if (maxcpu > hostcpus)
-        maxcpu = hostcpus;
-
-    if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
-        virReportOOMError();
-        return -1;
-    }
-
     for (n = 0; n < def->cputune.nvcpupin; n++) {
-        int i;
         vcpu = def->cputune.vcpupin[n]->vcpuid;
 
-        memset(cpumap, 0, cpumaplen);
-        cpumask = def->cputune.vcpupin[n]->cpumask;
-        vcpupid = priv->vcpupids[vcpu];
-
-        i = -1;
-        while ((i = virBitmapNextSetBit(cpumask, i)) > 0)
-            VIR_USE_CPU(cpumap, i);
-
-        if (virProcessInfoSetAffinity(vcpupid,
-                                      cpumap,
-                                      cpumaplen,
-                                      maxcpu) < 0) {
+        if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
+                                      def->cputune.vcpupin[n]->cpumask) < 0) {
             goto cleanup;
         }
     }
 
     ret = 0;
 cleanup:
-    VIR_FREE(cpumap);
     return ret;
 }
 
@@ -2014,13 +1984,8 @@ qemuProcessSetEmulatorAffinites(virConnectPtr conn,
                                 virDomainObjPtr vm)
 {
     virDomainDefPtr def = vm->def;
-    pid_t pid = vm->pid;
-    virBitmapPtr cpumask = NULL;
-    unsigned char *cpumap = NULL;
     virNodeInfo nodeinfo;
-    int cpumaplen, hostcpus, maxcpu, i;
     int ret = -1;
-    bool result;
 
     if (virNodeGetInfo(conn, &nodeinfo) != 0)
         return -1;
@@ -2028,36 +1993,13 @@ qemuProcessSetEmulatorAffinites(virConnectPtr conn,
     if (!def->cputune.emulatorpin)
         return 0;
 
-    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
-    cpumaplen = VIR_CPU_MAPLEN(hostcpus);
-    maxcpu = cpumaplen * CHAR_BIT;
-
-    if (maxcpu > hostcpus)
-        maxcpu = hostcpus;
-
-    if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
-        virReportOOMError();
-        return -1;
-    }
-
-    cpumask = def->cputune.emulatorpin->cpumask;
-    for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; i++) {
-        if (virBitmapGetBit(cpumask, i, &result) < 0)
-            goto cleanup;
-        if (result)
-            VIR_USE_CPU(cpumap, i);
-    }
-
-    if (virProcessInfoSetAffinity(pid,
-                                  cpumap,
-                                  cpumaplen,
-                                  maxcpu) < 0) {
+    if (virProcessInfoSetAffinity(vm->pid,
+                                  def->cputune.emulatorpin->cpumask) < 0) {
         goto cleanup;
     }
 
     ret = 0;
 cleanup:
-    VIR_FREE(cpumap);
     return ret;
 }
 
diff --git a/src/util/processinfo.c b/src/util/processinfo.c
index 16ab8af..b7d2ed0 100644
--- a/src/util/processinfo.c
+++ b/src/util/processinfo.c
@@ -30,12 +30,10 @@
 
 #if HAVE_SCHED_GETAFFINITY
 
-int virProcessInfoSetAffinity(pid_t pid,
-                              const unsigned char *map,
-                              size_t maplen,
-                              int maxcpu)
+int virProcessInfoSetAffinity(pid_t pid, virBitmapPtr map)
 {
     int i;
+    bool set = false;
 # ifdef CPU_ALLOC
     /* New method dynamically allocates cpu mask, allowing unlimted cpus */
     int numcpus = 1024;
@@ -59,8 +57,10 @@ realloc:
     }
 
     CPU_ZERO_S(masklen, mask);
-    for (i = 0 ; i < maxcpu ; i++) {
-        if (VIR_CPU_USABLE(map, maplen, 0, i))
+    for (i = 0 ; i < virBitmapSize(map); i++) {
+        if (virBitmapGetBit(map, i, &set) < 0)
+            return -1;
+        if (set)
             CPU_SET_S(i, masklen, mask);
     }
 
@@ -81,8 +81,10 @@ realloc:
     cpu_set_t mask;
 
     CPU_ZERO(&mask);
-    for (i = 0 ; i < maxcpu ; i++) {
-        if (VIR_CPU_USABLE(map, maplen, 0, i))
+    for (i = 0 ; i < virBitmapSize(map); i++) {
+        if (virBitmapGetBit(map, i, &set) < 0)
+            return -1;
+        if (set)
             CPU_SET(i, &mask);
     }
 
@@ -97,8 +99,7 @@ realloc:
 }
 
 int virProcessInfoGetAffinity(pid_t pid,
-                              unsigned char *map,
-                              size_t maplen ATTRIBUTE_UNUSED,
+                              virBitmapPtr *map,
                               int maxcpu)
 {
     int i;
@@ -137,9 +138,15 @@ realloc:
         return -1;
     }
 
+    *map = virBitmapAlloc(maxcpu);
+    if (!map) {
+        virReportOOMError();
+        return -1;
+    }
+
     for (i = 0 ; i < maxcpu ; i++)
         if (CPU_ISSET_S(i, masklen, mask))
-            VIR_USE_CPU(map, i);
+            ignore_value(virBitmapSetBit(*map, i));
     CPU_FREE(mask);
 # else
     /* Legacy method uses a fixed size cpu mask, only allows upto 1024 cpus */
@@ -163,9 +170,7 @@ realloc:
 #else /* HAVE_SCHED_GETAFFINITY */
 
 int virProcessInfoSetAffinity(pid_t pid ATTRIBUTE_UNUSED,
-                              const unsigned char *map ATTRIBUTE_UNUSED,
-                              size_t maplen ATTRIBUTE_UNUSED,
-                              int maxcpu ATTRIBUTE_UNUSED)
+                              virBitmapPtr map ATTRIBUTE_UNUSED)
 {
     virReportSystemError(ENOSYS, "%s",
                          _("Process CPU affinity is not supported on this platform"));
@@ -173,8 +178,7 @@ int virProcessInfoSetAffinity(pid_t pid ATTRIBUTE_UNUSED,
 }
 
 int virProcessInfoGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
-                              unsigned char *map ATTRIBUTE_UNUSED,
-                              size_t maplen ATTRIBUTE_UNUSED,
+                              virBitmapPtr *map ATTRIBUTE_UNUSED,
                               int maxcpu ATTRIBUTE_UNUSED)
 {
     virReportSystemError(ENOSYS, "%s",
diff --git a/src/util/processinfo.h b/src/util/processinfo.h
index a648bb8..0424643 100644
--- a/src/util/processinfo.h
+++ b/src/util/processinfo.h
@@ -23,15 +23,12 @@
 # define __VIR_PROCESSINFO_H__
 
 # include "internal.h"
+# include "bitmap.h"
 
-int virProcessInfoSetAffinity(pid_t pid,
-                              const unsigned char *map,
-                              size_t maplen,
-                              int maxcpu);
+int virProcessInfoSetAffinity(pid_t pid, virBitmapPtr map);
 
 int virProcessInfoGetAffinity(pid_t pid,
-                              unsigned char *map,
-                              size_t maplen,
+                              virBitmapPtr *map,
                               int maxcpu);
 
 #endif /* __VIR_PROCESSINFO_H__ */
-- 
1.7.10.2


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]