All of lore.kernel.org
 help / color / mirror / Atom feed
* [Patch 1/2] support of cpupools in xl: update cpumask handling for cpu pools in libxc and python
@ 2010-09-22  5:42 Juergen Gross
  0 siblings, 0 replies; 5+ messages in thread
From: Juergen Gross @ 2010-09-22  5:42 UTC (permalink / raw)
  To: xen-devel@lists.xensource.com

[-- Attachment #1: Type: text/plain, Size: 496 bytes --]

Hi,

attached patch updates the cpumask handling for cpu pools in libxc and python
to support arbitrary numbers of cpus.

Juergen

-- 
Juergen Gross                 Principal Developer Operating Systems
TSP ES&S SWE OS6                       Telephone: +49 (0) 89 3222 2967
Fujitsu Technology Solutions              e-mail: juergen.gross@ts.fujitsu.com
Domagkstr. 28                           Internet: ts.fujitsu.com
D-80807 Muenchen                 Company details: ts.fujitsu.com/imprint.html

[-- Attachment #2: pools1.patch --]
[-- Type: text/x-patch, Size: 13750 bytes --]

Signed-off-by: juergen.gross@ts.fujitsu.com

To be able to support arbitrary numbers of physical cpus it was necessary to
include the size of cpumaps in the xc-interfaces for cpu pools.
These were:
  definition of xc_cpupoolinfo_t
  xc_cpupool_getinfo()
  xc_cpupool_freeinfo()

diff -r a2b46be9958e tools/libxc/xc_cpupool.c
--- a/tools/libxc/xc_cpupool.c	Tue Sep 21 17:54:43 2010 +0100
+++ b/tools/libxc/xc_cpupool.c	Wed Sep 22 07:20:51 2010 +0200
@@ -34,6 +34,20 @@ static int do_sysctl_save(xc_interface *
     return ret;
 }
 
+static int get_cpumap_size(xc_interface *xch)
+{
+    static int cpumap_size = 0;
+    xc_physinfo_t physinfo;
+
+    if ( cpumap_size )
+        return cpumap_size;
+
+    if ( !xc_physinfo(xch, &physinfo) )
+        cpumap_size = ((physinfo.max_cpu_id + 1) + 7) / 8;  /* round to bytes */
+
+    return cpumap_size;
+}
+
 int xc_cpupool_create(xc_interface *xch,
                       uint32_t *ppoolid,
                       uint32_t sched_id)
@@ -64,50 +78,61 @@ int xc_cpupool_destroy(xc_interface *xch
     return do_sysctl_save(xch, &sysctl);
 }
 
-int xc_cpupool_getinfo(xc_interface *xch, 
-                       uint32_t first_poolid,
-                       uint32_t n_max, 
-                       xc_cpupoolinfo_t *info)
+xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch, 
+                       uint32_t poolid)
 {
     int err = 0;
-    int p;
-    uint32_t poolid = first_poolid;
-    uint8_t local[sizeof (info->cpumap)];
+    xc_cpupoolinfo_t *info;
+    uint8_t *local;
+    int local_size;
+    int cpumap_size;
+    int size;
     DECLARE_SYSCTL;
 
-    memset(info, 0, n_max * sizeof(xc_cpupoolinfo_t));
+    local_size = get_cpumap_size(xch);
+    local = alloca(local_size);
+    if (!local_size)
+    {
+        PERROR("Could not get number of cpus");
+        return NULL;
+    }
+    cpumap_size = (local_size + sizeof(*info->cpumap) - 1) / sizeof(*info->cpumap);
+    size = sizeof(xc_cpupoolinfo_t) + cpumap_size * sizeof(*info->cpumap);
+    info = malloc(size);
+    if ( !info )
+        return NULL;
 
-    for (p = 0; p < n_max; p++)
+    memset(info, 0, size);
+    info->cpumap_size = local_size * 8;
+    info->cpumap = (uint64_t *)(info + 1);
+
+    sysctl.cmd = XEN_SYSCTL_cpupool_op;
+    sysctl.u.cpupool_op.op = XEN_SYSCTL_CPUPOOL_OP_INFO;
+    sysctl.u.cpupool_op.cpupool_id = poolid;
+    set_xen_guest_handle(sysctl.u.cpupool_op.cpumap.bitmap, local);
+    sysctl.u.cpupool_op.cpumap.nr_cpus = local_size * 8;
+
+    if ( (err = lock_pages(local, local_size)) != 0 )
     {
-        sysctl.cmd = XEN_SYSCTL_cpupool_op;
-        sysctl.u.cpupool_op.op = XEN_SYSCTL_CPUPOOL_OP_INFO;
-        sysctl.u.cpupool_op.cpupool_id = poolid;
-        set_xen_guest_handle(sysctl.u.cpupool_op.cpumap.bitmap, local);
-        sysctl.u.cpupool_op.cpumap.nr_cpus = sizeof(info->cpumap) * 8;
+        PERROR("Could not lock memory for Xen hypercall");
+        free(info);
+        return NULL;
+    }
+    err = do_sysctl_save(xch, &sysctl);
+    unlock_pages(local, local_size);
 
-        if ( (err = lock_pages(local, sizeof(local))) != 0 )
-        {
-            PERROR("Could not lock memory for Xen hypercall");
-            break;
-        }
-        err = do_sysctl_save(xch, &sysctl);
-        unlock_pages(local, sizeof (local));
-
-        if ( err < 0 )
-            break;
-
-        info->cpupool_id = sysctl.u.cpupool_op.cpupool_id;
-        info->sched_id = sysctl.u.cpupool_op.sched_id;
-        info->n_dom = sysctl.u.cpupool_op.n_dom;
-        bitmap_byte_to_64(&(info->cpumap), local, sizeof(local) * 8);
-        poolid = sysctl.u.cpupool_op.cpupool_id + 1;
-        info++;
+    if ( err < 0 )
+    {
+        free(info);
+        return NULL;
     }
 
-    if ( p == 0 )
-        return err;
+    info->cpupool_id = sysctl.u.cpupool_op.cpupool_id;
+    info->sched_id = sysctl.u.cpupool_op.sched_id;
+    info->n_dom = sysctl.u.cpupool_op.n_dom;
+    bitmap_byte_to_64(info->cpumap, local, local_size * 8);
 
-    return p;
+    return info;
 }
 
 int xc_cpupool_addcpu(xc_interface *xch,
@@ -150,30 +175,37 @@ int xc_cpupool_movedomain(xc_interface *
 }
 
 int xc_cpupool_freeinfo(xc_interface *xch,
-                        uint64_t *cpumap)
+                        uint64_t *cpumap,
+                        int cpusize)
 {
     int err;
-    uint8_t local[sizeof (*cpumap)];
+    uint8_t *local;
     DECLARE_SYSCTL;
+
+    local = malloc(cpusize);
+    if (local == NULL)
+        return -ENOMEM;
 
     sysctl.cmd = XEN_SYSCTL_cpupool_op;
     sysctl.u.cpupool_op.op = XEN_SYSCTL_CPUPOOL_OP_FREEINFO;
     set_xen_guest_handle(sysctl.u.cpupool_op.cpumap.bitmap, local);
-    sysctl.u.cpupool_op.cpumap.nr_cpus = sizeof(*cpumap) * 8;
+    sysctl.u.cpupool_op.cpumap.nr_cpus = cpusize * 8;
 
-    if ( (err = lock_pages(local, sizeof(local))) != 0 )
+    if ( (err = lock_pages(local, cpusize)) != 0 )
     {
         PERROR("Could not lock memory for Xen hypercall");
+        free(local);
         return err;
     }
 
     err = do_sysctl_save(xch, &sysctl);
-    unlock_pages(local, sizeof (local));
+    unlock_pages(local, cpusize);
+    bitmap_byte_to_64(cpumap, local, cpusize * 8);
+
+    free(local);
 
     if (err < 0)
         return err;
 
-    bitmap_byte_to_64(cpumap, local, sizeof(local) * 8);
-
     return 0;
 }
diff -r a2b46be9958e tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h	Tue Sep 21 17:54:43 2010 +0100
+++ b/tools/libxc/xenctrl.h	Wed Sep 22 07:20:51 2010 +0200
@@ -535,7 +535,8 @@ typedef struct xc_cpupoolinfo {
     uint32_t cpupool_id;
     uint32_t sched_id;
     uint32_t n_dom;
-    uint64_t cpumap;
+    uint32_t cpumap_size;    /* max number of cpus in map */
+    uint64_t *cpumap;
 } xc_cpupoolinfo_t;
 
 /**
@@ -564,15 +565,11 @@ int xc_cpupool_destroy(xc_interface *xch
  * Get cpupool info. Returns info for up to the specified number of cpupools
  * starting at the given id.
  * @parm xc_handle a handle to an open hypervisor interface
- * @parm first_poolid lowest id for which info is returned
- * @parm n_max maximum number of cpupools to return info
- * @parm info pointer to xc_cpupoolinfo_t array
- * return number of cpupool infos
+ * @parm poolid lowest id for which info is returned
+ * return cpupool info ptr (obtained by malloc)
  */
-int xc_cpupool_getinfo(xc_interface *xch,
-                       uint32_t first_poolid,
-                       uint32_t n_max,
-                       xc_cpupoolinfo_t *info);
+xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
+                       uint32_t poolid);
 
 /**
  * Add cpu to a cpupool. cpu may be -1 indicating the first unassigned.
@@ -615,10 +612,12 @@ int xc_cpupool_movedomain(xc_interface *
  *
  * @parm xc_handle a handle to an open hypervisor interface
  * @parm cpumap pointer where to store the cpumap
+ * @parm cpusize size of cpumap array in bytes
  * return 0 on success, -1 on failure
  */
 int xc_cpupool_freeinfo(xc_interface *xch,
-                        uint64_t *cpumap);
+                        uint64_t *cpumap,
+                        int cpusize);
 
 
 /*
diff -r a2b46be9958e tools/libxl/libxl.c
--- a/tools/libxl/libxl.c	Tue Sep 21 17:54:43 2010 +0100
+++ b/tools/libxl/libxl.c	Wed Sep 22 07:20:51 2010 +0200
@@ -609,9 +609,17 @@ libxl_poolinfo * libxl_list_pool(libxl_c
 libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
 {
     libxl_poolinfo *ptr;
-    int i, ret;
-    xc_cpupoolinfo_t info[256];
-    int size = 256;
+    int i;
+    xc_cpupoolinfo_t *info;
+    int size;
+    uint32_t poolid;
+    libxl_physinfo physinfo;
+
+    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting phys info");
+        return NULL;
+    }
+    size = physinfo.max_cpu_id + LIBXL__CPUPOOL_INFO_SPARE;    /* allow some inactive cpu pools */
 
     ptr = calloc(size, sizeof(libxl_poolinfo));
     if (!ptr) {
@@ -619,16 +627,17 @@ libxl_poolinfo * libxl_list_pool(libxl_c
         return NULL;
     }
 
-    ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
-    if (ret<0) {
-        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting cpupool info");
-        return NULL;
+    poolid = 0;
+    for (i = 0; i < size; i++) {
+        info = xc_cpupool_getinfo(ctx->xch, poolid);
+        if (info == NULL)
+            break;
+        ptr[i].poolid = info->cpupool_id;
+        poolid = info->cpupool_id + 1;
+        free(info);
     }
 
-    for (i = 0; i < ret; i++) {
-        ptr[i].poolid = info[i].cpupool_id;
-    }
-    *nb_pool = ret;
+    *nb_pool = i;
     return ptr;
 }
 
diff -r a2b46be9958e tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h	Tue Sep 21 17:54:43 2010 +0100
+++ b/tools/libxl/libxl_internal.h	Wed Sep 22 07:20:51 2010 +0200
@@ -236,6 +236,7 @@ _hidden char *libxl__domid_to_name(libxl
 _hidden char *libxl__domid_to_name(libxl__gc *gc, uint32_t domid);
 _hidden char *libxl__poolid_to_name(libxl__gc *gc, uint32_t poolid);
 
+#define LIBXL__CPUPOOL_INFO_SPARE    32
 
   /* holds the CPUID response for a single CPUID leaf
    * input contains the value of the EAX and ECX register,
diff -r a2b46be9958e tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c	Tue Sep 21 17:54:43 2010 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c	Wed Sep 22 07:20:51 2010 +0200
@@ -241,7 +241,7 @@ static PyObject *pyxc_vcpu_setaffinity(X
     if ( xc_physinfo(self->xc_handle, &info) != 0 )
         return pyxc_error_to_exception(self->xc_handle);
   
-    nr_cpus = info.nr_cpus;
+    nr_cpus = info.max_cpu_id + 1;
 
     size = (nr_cpus + cpumap_size * 8 - 1)/ (cpumap_size * 8);
     cpumap = malloc(cpumap_size * size);
@@ -400,7 +400,7 @@ static PyObject *pyxc_vcpu_getinfo(XcObj
 
     if ( xc_physinfo(self->xc_handle, &pinfo) != 0 ) 
         return pyxc_error_to_exception(self->xc_handle);
-    nr_cpus = pinfo.nr_cpus;
+    nr_cpus = pinfo.max_cpu_id + 1;
 
     rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info);
     if ( rc < 0 )
@@ -1906,22 +1906,23 @@ static PyObject *pyxc_dom_set_memshr(XcO
     return zero;
 }
 
-static PyObject *cpumap_to_cpulist(uint64_t cpumap)
+static PyObject *cpumap_to_cpulist(uint64_t *cpumap, int cpusize)
 {
     PyObject *cpulist = NULL;
-    uint32_t i;
+    int i;
 
     cpulist = PyList_New(0);
-    for ( i = 0; cpumap != 0; i++ )
+    for ( i = 0; i < cpusize; i++ )
     {
-        if ( cpumap & 1 )
+        if ( *cpumap & (1L << (i % 64)) )
         {
             PyObject* pyint = PyInt_FromLong(i);
 
             PyList_Append(cpulist, pyint);
             Py_DECREF(pyint);
         }
-        cpumap >>= 1;
+        if ( (i % 64) == 63 )
+            cpumap++;
     }
     return cpulist;
 }
@@ -1966,7 +1967,7 @@ static PyObject *pyxc_cpupool_getinfo(Xc
     PyObject *list, *info_dict;
 
     uint32_t first_pool = 0;
-    int max_pools = 1024, nr_pools, i;
+    int max_pools = 1024, i;
     xc_cpupoolinfo_t *info;
 
     static char *kwd_list[] = { "first_pool", "max_pools", NULL };
@@ -1975,38 +1976,31 @@ static PyObject *pyxc_cpupool_getinfo(Xc
                                       &first_pool, &max_pools) )
         return NULL;
 
-    info = calloc(max_pools, sizeof(xc_cpupoolinfo_t));
-    if (info == NULL)
-        return PyErr_NoMemory();
-
-    nr_pools = xc_cpupool_getinfo(self->xc_handle, first_pool, max_pools, info);
-
-    if (nr_pools < 0)
+    list = PyList_New(0);
+    for (i = 0; i < max_pools; i++)
     {
-        free(info);
-        return pyxc_error_to_exception(self->xc_handle);
-    }
-
-    list = PyList_New(nr_pools);
-    for ( i = 0 ; i < nr_pools; i++ )
-    {
+        info = xc_cpupool_getinfo(self->xc_handle, first_pool);
+        if (info == NULL)
+            break;
         info_dict = Py_BuildValue(
             "{s:i,s:i,s:i,s:N}",
-            "cpupool",         (int)info[i].cpupool_id,
-            "sched",           info[i].sched_id,
-            "n_dom",           info[i].n_dom,
-            "cpulist",         cpumap_to_cpulist(info[i].cpumap));
+            "cpupool",         (int)info->cpupool_id,
+            "sched",           info->sched_id,
+            "n_dom",           info->n_dom,
+            "cpulist",         cpumap_to_cpulist(info->cpumap,
+                                                 info->cpumap_size));
+        first_pool = info->cpupool_id + 1;
+        free(info);
+
         if ( info_dict == NULL )
         {
             Py_DECREF(list);
-            if ( info_dict != NULL ) { Py_DECREF(info_dict); }
-            free(info);
             return NULL;
         }
-        PyList_SetItem(list, i, info_dict);
+
+        PyList_Append(list, info_dict);
+        Py_DECREF(info_dict);
     }
-
-    free(info);
 
     return list;
 }
@@ -2072,12 +2066,28 @@ static PyObject *pyxc_cpupool_movedomain
 
 static PyObject *pyxc_cpupool_freeinfo(XcObject *self)
 {
-    uint64_t cpumap;
+    uint64_t *cpumap;
+    xc_physinfo_t physinfo;
+    int ret;
+    PyObject *info = NULL;
 
-    if (xc_cpupool_freeinfo(self->xc_handle, &cpumap) != 0)
+    if (xc_physinfo(self->xc_handle, &physinfo))
         return pyxc_error_to_exception(self->xc_handle);
 
-    return cpumap_to_cpulist(cpumap);
+    cpumap = calloc((physinfo.max_cpu_id + 64) / 64, sizeof(uint64_t));
+    if (!cpumap) {
+        errno = -ENOMEM;
+        return PyErr_SetFromErrno(xc_error_obj);
+    }
+
+    ret = xc_cpupool_freeinfo(self->xc_handle, cpumap,
+                              (physinfo.max_cpu_id + 8) / 8);
+    if (!ret)
+        info = cpumap_to_cpulist(cpumap, physinfo.max_cpu_id + 1);
+
+    free(cpumap);
+
+    return ret ? pyxc_error_to_exception(self->xc_handle) : info;
 }
 
 static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args,

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Patch 1/2] support of cpupools in xl: update cpumask handling for cpu pools in libxc and python
@ 2010-10-01  7:20 Juergen Gross
  2010-10-01  9:35 ` Ian Campbell
  0 siblings, 1 reply; 5+ messages in thread
From: Juergen Gross @ 2010-10-01  7:20 UTC (permalink / raw)
  To: xen-devel@lists.xensource.com

[-- Attachment #1: Type: text/plain, Size: 497 bytes --]

Hi,

attached patch updates the cpumask handling for cpu pools in libxc and python
to support arbitrary numbers of cpus.

Juergen

-- 
Juergen Gross                 Principal Developer Operating Systems
TSP ES&S SWE OS6                       Telephone: +49 (0) 89 3222 2967
Fujitsu Technology Solutions              e-mail: juergen.gross@ts.fujitsu.com
Domagkstr. 28                           Internet: ts.fujitsu.com
D-80807 Muenchen                 Company details: ts.fujitsu.com/imprint.html


[-- Attachment #2: pools1.patch --]
[-- Type: text/x-patch, Size: 13849 bytes --]

Signed-off-by: juergen.gross@ts.fujitsu.com

To be able to support arbitrary numbers of physical cpus it was necessary to
include the size of cpumaps in the xc-interfaces for cpu pools.
These were:
  definition of xc_cpupoolinfo_t
  xc_cpupool_getinfo()
  xc_cpupool_freeinfo()

diff -r 71f836615ea2 tools/libxc/xc_cpupool.c
--- a/tools/libxc/xc_cpupool.c	Fri Sep 24 15:54:39 2010 +0100
+++ b/tools/libxc/xc_cpupool.c	Fri Oct 01 09:03:17 2010 +0200
@@ -34,6 +34,20 @@ static int do_sysctl_save(xc_interface *
     return ret;
 }
 
+static int get_cpumap_size(xc_interface *xch)
+{
+    static int cpumap_size = 0;
+    xc_physinfo_t physinfo;
+
+    if ( cpumap_size )
+        return cpumap_size;
+
+    if ( !xc_physinfo(xch, &physinfo) )
+        cpumap_size = ((physinfo.max_cpu_id + 1) + 7) / 8;  /* round to bytes */
+
+    return cpumap_size;
+}
+
 int xc_cpupool_create(xc_interface *xch,
                       uint32_t *ppoolid,
                       uint32_t sched_id)
@@ -64,50 +78,61 @@ int xc_cpupool_destroy(xc_interface *xch
     return do_sysctl_save(xch, &sysctl);
 }
 
-int xc_cpupool_getinfo(xc_interface *xch, 
-                       uint32_t first_poolid,
-                       uint32_t n_max, 
-                       xc_cpupoolinfo_t *info)
+xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch, 
+                       uint32_t poolid)
 {
     int err = 0;
-    int p;
-    uint32_t poolid = first_poolid;
-    uint8_t local[sizeof (info->cpumap)];
+    xc_cpupoolinfo_t *info;
+    uint8_t *local;
+    int local_size;
+    int cpumap_size;
+    int size;
     DECLARE_SYSCTL;
 
-    memset(info, 0, n_max * sizeof(xc_cpupoolinfo_t));
+    local_size = get_cpumap_size(xch);
+    local = alloca(local_size);
+    if (!local_size)
+    {
+        PERROR("Could not get number of cpus");
+        return NULL;
+    }
+    cpumap_size = (local_size + sizeof(*info->cpumap) - 1) / sizeof(*info->cpumap);
+    size = sizeof(xc_cpupoolinfo_t) + cpumap_size * sizeof(*info->cpumap);
+    info = malloc(size);
+    if ( !info )
+        return NULL;
 
-    for (p = 0; p < n_max; p++)
+    memset(info, 0, size);
+    info->cpumap_size = local_size * 8;
+    info->cpumap = (uint64_t *)(info + 1);
+
+    sysctl.cmd = XEN_SYSCTL_cpupool_op;
+    sysctl.u.cpupool_op.op = XEN_SYSCTL_CPUPOOL_OP_INFO;
+    sysctl.u.cpupool_op.cpupool_id = poolid;
+    set_xen_guest_handle(sysctl.u.cpupool_op.cpumap.bitmap, local);
+    sysctl.u.cpupool_op.cpumap.nr_cpus = local_size * 8;
+
+    if ( (err = lock_pages(local, local_size)) != 0 )
     {
-        sysctl.cmd = XEN_SYSCTL_cpupool_op;
-        sysctl.u.cpupool_op.op = XEN_SYSCTL_CPUPOOL_OP_INFO;
-        sysctl.u.cpupool_op.cpupool_id = poolid;
-        set_xen_guest_handle(sysctl.u.cpupool_op.cpumap.bitmap, local);
-        sysctl.u.cpupool_op.cpumap.nr_cpus = sizeof(info->cpumap) * 8;
+        PERROR("Could not lock memory for Xen hypercall");
+        free(info);
+        return NULL;
+    }
+    err = do_sysctl_save(xch, &sysctl);
+    unlock_pages(local, local_size);
 
-        if ( (err = lock_pages(local, sizeof(local))) != 0 )
-        {
-            PERROR("Could not lock memory for Xen hypercall");
-            break;
-        }
-        err = do_sysctl_save(xch, &sysctl);
-        unlock_pages(local, sizeof (local));
-
-        if ( err < 0 )
-            break;
-
-        info->cpupool_id = sysctl.u.cpupool_op.cpupool_id;
-        info->sched_id = sysctl.u.cpupool_op.sched_id;
-        info->n_dom = sysctl.u.cpupool_op.n_dom;
-        bitmap_byte_to_64(&(info->cpumap), local, sizeof(local) * 8);
-        poolid = sysctl.u.cpupool_op.cpupool_id + 1;
-        info++;
+    if ( err < 0 )
+    {
+        free(info);
+        return NULL;
     }
 
-    if ( p == 0 )
-        return err;
+    info->cpupool_id = sysctl.u.cpupool_op.cpupool_id;
+    info->sched_id = sysctl.u.cpupool_op.sched_id;
+    info->n_dom = sysctl.u.cpupool_op.n_dom;
+    bitmap_byte_to_64(info->cpumap, local, local_size * 8);
 
-    return p;
+    return info;
 }
 
 int xc_cpupool_addcpu(xc_interface *xch,
@@ -150,30 +175,37 @@ int xc_cpupool_movedomain(xc_interface *
 }
 
 int xc_cpupool_freeinfo(xc_interface *xch,
-                        uint64_t *cpumap)
+                        uint64_t *cpumap,
+                        int cpusize)
 {
     int err;
-    uint8_t local[sizeof (*cpumap)];
+    uint8_t *local;
     DECLARE_SYSCTL;
+
+    local = malloc(cpusize);
+    if (local == NULL)
+        return -ENOMEM;
 
     sysctl.cmd = XEN_SYSCTL_cpupool_op;
     sysctl.u.cpupool_op.op = XEN_SYSCTL_CPUPOOL_OP_FREEINFO;
     set_xen_guest_handle(sysctl.u.cpupool_op.cpumap.bitmap, local);
-    sysctl.u.cpupool_op.cpumap.nr_cpus = sizeof(*cpumap) * 8;
+    sysctl.u.cpupool_op.cpumap.nr_cpus = cpusize * 8;
 
-    if ( (err = lock_pages(local, sizeof(local))) != 0 )
+    if ( (err = lock_pages(local, cpusize)) != 0 )
     {
         PERROR("Could not lock memory for Xen hypercall");
+        free(local);
         return err;
     }
 
     err = do_sysctl_save(xch, &sysctl);
-    unlock_pages(local, sizeof (local));
+    unlock_pages(local, cpusize);
+    bitmap_byte_to_64(cpumap, local, cpusize * 8);
+
+    free(local);
 
     if (err < 0)
         return err;
 
-    bitmap_byte_to_64(cpumap, local, sizeof(local) * 8);
-
     return 0;
 }
diff -r 71f836615ea2 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h	Fri Sep 24 15:54:39 2010 +0100
+++ b/tools/libxc/xenctrl.h	Fri Oct 01 09:03:17 2010 +0200
@@ -535,7 +535,8 @@ typedef struct xc_cpupoolinfo {
     uint32_t cpupool_id;
     uint32_t sched_id;
     uint32_t n_dom;
-    uint64_t cpumap;
+    uint32_t cpumap_size;    /* max number of cpus in map */
+    uint64_t *cpumap;
 } xc_cpupoolinfo_t;
 
 /**
@@ -564,15 +565,11 @@ int xc_cpupool_destroy(xc_interface *xch
  * Get cpupool info. Returns info for up to the specified number of cpupools
  * starting at the given id.
  * @parm xc_handle a handle to an open hypervisor interface
- * @parm first_poolid lowest id for which info is returned
- * @parm n_max maximum number of cpupools to return info
- * @parm info pointer to xc_cpupoolinfo_t array
- * return number of cpupool infos
+ * @parm poolid lowest id for which info is returned
+ * return cpupool info ptr (obtained by malloc)
  */
-int xc_cpupool_getinfo(xc_interface *xch,
-                       uint32_t first_poolid,
-                       uint32_t n_max,
-                       xc_cpupoolinfo_t *info);
+xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
+                       uint32_t poolid);
 
 /**
  * Add cpu to a cpupool. cpu may be -1 indicating the first unassigned.
@@ -615,10 +612,12 @@ int xc_cpupool_movedomain(xc_interface *
  *
  * @parm xc_handle a handle to an open hypervisor interface
  * @parm cpumap pointer where to store the cpumap
+ * @parm cpusize size of cpumap array in bytes
  * return 0 on success, -1 on failure
  */
 int xc_cpupool_freeinfo(xc_interface *xch,
-                        uint64_t *cpumap);
+                        uint64_t *cpumap,
+                        int cpusize);
 
 
 /*
diff -r 71f836615ea2 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c	Fri Sep 24 15:54:39 2010 +0100
+++ b/tools/libxl/libxl.c	Fri Oct 01 09:03:17 2010 +0200
@@ -610,26 +610,34 @@ libxl_poolinfo * libxl_list_pool(libxl_c
 libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
 {
     libxl_poolinfo *ptr;
-    int i, ret;
-    xc_cpupoolinfo_t info[256];
-    int size = 256;
+    int i;
+    xc_cpupoolinfo_t *info;
+    uint32_t poolid;
+    libxl_physinfo physinfo;
 
-    ptr = calloc(size, sizeof(libxl_poolinfo));
-    if (!ptr) {
-        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
+    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting phys info");
         return NULL;
     }
 
-    ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
-    if (ret<0) {
-        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting cpupool info");
-        return NULL;
+    ptr = NULL;
+
+    poolid = 0;
+    for (i = 0;; i++) {
+        info = xc_cpupool_getinfo(ctx->xch, poolid);
+        if (info == NULL)
+            break;
+        ptr = realloc(ptr, (i + 1) * sizeof(libxl_poolinfo));
+        if (!ptr) {
+            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
+            return NULL;
+        }
+        ptr[i].poolid = info->cpupool_id;
+        poolid = info->cpupool_id + 1;
+        free(info);
     }
 
-    for (i = 0; i < ret; i++) {
-        ptr[i].poolid = info[i].cpupool_id;
-    }
-    *nb_pool = ret;
+    *nb_pool = i;
     return ptr;
 }
 
diff -r 71f836615ea2 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h	Fri Sep 24 15:54:39 2010 +0100
+++ b/tools/libxl/libxl_internal.h	Fri Oct 01 09:03:17 2010 +0200
@@ -239,7 +239,6 @@ _hidden char *libxl__domid_to_name(libxl
 _hidden char *libxl__domid_to_name(libxl__gc *gc, uint32_t domid);
 _hidden char *libxl__poolid_to_name(libxl__gc *gc, uint32_t poolid);
 
-
   /* holds the CPUID response for a single CPUID leaf
    * input contains the value of the EAX and ECX register,
    * and each policy string contains a filter to apply to
diff -r 71f836615ea2 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c	Fri Sep 24 15:54:39 2010 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c	Fri Oct 01 09:03:17 2010 +0200
@@ -241,7 +241,7 @@ static PyObject *pyxc_vcpu_setaffinity(X
     if ( xc_physinfo(self->xc_handle, &info) != 0 )
         return pyxc_error_to_exception(self->xc_handle);
   
-    nr_cpus = info.nr_cpus;
+    nr_cpus = info.max_cpu_id + 1;
 
     size = (nr_cpus + cpumap_size * 8 - 1)/ (cpumap_size * 8);
     cpumap = malloc(cpumap_size * size);
@@ -400,7 +400,7 @@ static PyObject *pyxc_vcpu_getinfo(XcObj
 
     if ( xc_physinfo(self->xc_handle, &pinfo) != 0 ) 
         return pyxc_error_to_exception(self->xc_handle);
-    nr_cpus = pinfo.nr_cpus;
+    nr_cpus = pinfo.max_cpu_id + 1;
 
     rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info);
     if ( rc < 0 )
@@ -1906,22 +1906,23 @@ static PyObject *pyxc_dom_set_memshr(XcO
     return zero;
 }
 
-static PyObject *cpumap_to_cpulist(uint64_t cpumap)
+static PyObject *cpumap_to_cpulist(uint64_t *cpumap, int cpusize)
 {
     PyObject *cpulist = NULL;
-    uint32_t i;
+    int i;
 
     cpulist = PyList_New(0);
-    for ( i = 0; cpumap != 0; i++ )
+    for ( i = 0; i < cpusize; i++ )
     {
-        if ( cpumap & 1 )
+        if ( *cpumap & (1L << (i % 64)) )
         {
             PyObject* pyint = PyInt_FromLong(i);
 
             PyList_Append(cpulist, pyint);
             Py_DECREF(pyint);
         }
-        cpumap >>= 1;
+        if ( (i % 64) == 63 )
+            cpumap++;
     }
     return cpulist;
 }
@@ -1966,7 +1967,7 @@ static PyObject *pyxc_cpupool_getinfo(Xc
     PyObject *list, *info_dict;
 
     uint32_t first_pool = 0;
-    int max_pools = 1024, nr_pools, i;
+    int max_pools = 1024, i;
     xc_cpupoolinfo_t *info;
 
     static char *kwd_list[] = { "first_pool", "max_pools", NULL };
@@ -1975,38 +1976,31 @@ static PyObject *pyxc_cpupool_getinfo(Xc
                                       &first_pool, &max_pools) )
         return NULL;
 
-    info = calloc(max_pools, sizeof(xc_cpupoolinfo_t));
-    if (info == NULL)
-        return PyErr_NoMemory();
-
-    nr_pools = xc_cpupool_getinfo(self->xc_handle, first_pool, max_pools, info);
-
-    if (nr_pools < 0)
+    list = PyList_New(0);
+    for (i = 0; i < max_pools; i++)
     {
-        free(info);
-        return pyxc_error_to_exception(self->xc_handle);
-    }
-
-    list = PyList_New(nr_pools);
-    for ( i = 0 ; i < nr_pools; i++ )
-    {
+        info = xc_cpupool_getinfo(self->xc_handle, first_pool);
+        if (info == NULL)
+            break;
         info_dict = Py_BuildValue(
             "{s:i,s:i,s:i,s:N}",
-            "cpupool",         (int)info[i].cpupool_id,
-            "sched",           info[i].sched_id,
-            "n_dom",           info[i].n_dom,
-            "cpulist",         cpumap_to_cpulist(info[i].cpumap));
+            "cpupool",         (int)info->cpupool_id,
+            "sched",           info->sched_id,
+            "n_dom",           info->n_dom,
+            "cpulist",         cpumap_to_cpulist(info->cpumap,
+                                                 info->cpumap_size));
+        first_pool = info->cpupool_id + 1;
+        free(info);
+
         if ( info_dict == NULL )
         {
             Py_DECREF(list);
-            if ( info_dict != NULL ) { Py_DECREF(info_dict); }
-            free(info);
             return NULL;
         }
-        PyList_SetItem(list, i, info_dict);
+
+        PyList_Append(list, info_dict);
+        Py_DECREF(info_dict);
     }
-
-    free(info);
 
     return list;
 }
@@ -2072,12 +2066,28 @@ static PyObject *pyxc_cpupool_movedomain
 
 static PyObject *pyxc_cpupool_freeinfo(XcObject *self)
 {
-    uint64_t cpumap;
+    uint64_t *cpumap;
+    xc_physinfo_t physinfo;
+    int ret;
+    PyObject *info = NULL;
 
-    if (xc_cpupool_freeinfo(self->xc_handle, &cpumap) != 0)
+    if (xc_physinfo(self->xc_handle, &physinfo))
         return pyxc_error_to_exception(self->xc_handle);
 
-    return cpumap_to_cpulist(cpumap);
+    cpumap = calloc((physinfo.max_cpu_id + 64) / 64, sizeof(uint64_t));
+    if (!cpumap) {
+        errno = -ENOMEM;
+        return PyErr_SetFromErrno(xc_error_obj);
+    }
+
+    ret = xc_cpupool_freeinfo(self->xc_handle, cpumap,
+                              (physinfo.max_cpu_id + 8) / 8);
+    if (!ret)
+        info = cpumap_to_cpulist(cpumap, physinfo.max_cpu_id + 1);
+
+    free(cpumap);
+
+    return ret ? pyxc_error_to_exception(self->xc_handle) : info;
 }
 
 static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args,

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch 1/2] support of cpupools in xl: update cpumask handling for cpu pools in libxc and python
  2010-10-01  7:20 Juergen Gross
@ 2010-10-01  9:35 ` Ian Campbell
  2010-10-05 13:50   ` Juergen Gross
  0 siblings, 1 reply; 5+ messages in thread
From: Ian Campbell @ 2010-10-01  9:35 UTC (permalink / raw)
  To: Juergen Gross; +Cc: xen-devel@lists.xensource.com

(I highly recommend the patchbomb extension ("hg email"), it makes
sending series much simpler and threads the mails together in a
convenient way)

On Fri, 2010-10-01 at 08:20 +0100, Juergen Gross wrote:
> Signed-off-by: juergen.gross@ts.fujitsu.com

This should come after the description.

> To be able to support arbitrary numbers of physical cpus it was necessary to
> include the size of cpumaps in the xc-interfaces for cpu pools.
> These were:
>   definition of xc_cpupoolinfo_t
>   xc_cpupool_getinfo()
>   xc_cpupool_freeinfo()

Please also mention the change in xc_cpupool_getinfo semantics from
caller allocated buffer to callee allocated+returned.

> @@ -64,50 +78,61 @@ int xc_cpupool_destroy(xc_interface *xch
>      return do_sysctl_save(xch, &sysctl);
>  }
>  
> -int xc_cpupool_getinfo(xc_interface *xch, 
> -                       uint32_t first_poolid,
> -                       uint32_t n_max, 
> -                       xc_cpupoolinfo_t *info)
> +xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch, 
> +                       uint32_t poolid)
[...]
> -    memset(info, 0, n_max * sizeof(xc_cpupoolinfo_t));
> +    local_size = get_cpumap_size(xch);
> +    local = alloca(local_size);
> +    if (!local_size)
> +    {
> +        PERROR("Could not get number of cpus");
> +        return NULL;
> +    }

I imagine alloca(0) is most likely safe so long as you don't actually
use the result, but the man page doesn't specifically say. Probably the
check of !local_size should be before the alloca(local_size) to be on
the safe side.

> +    cpumap_size = (local_size + sizeof(*info->cpumap) - 1) / sizeof(*info->cpumap);

xg_private.h defines a macro ROUNDUP, I wonder if that should be moved
somewhere more generic and used to clarify code like this?

> diff -r 8b7d253f0e17 tools/libxc/xenctrl.h
> --- a/tools/libxc/xenctrl.h     Fri Oct 01 08:39:49 2010 +0100
> +++ b/tools/libxc/xenctrl.h     Fri Oct 01 09:13:36 2010 +0100
> @@ -564,15 +565,11 @@ int xc_cpupool_destroy(xc_interface *xch
> [...]
> + * @parm poolid lowest id for which info is returned
> + * return cpupool info ptr (obtained by malloc)
>   */
> -int xc_cpupool_getinfo(xc_interface *xch,
> -                       uint32_t first_poolid,
> -                       uint32_t n_max,
> -                       xc_cpupoolinfo_t *info);
> +xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
> +                       uint32_t poolid);
>  
>  /**
>   * Add cpu to a cpupool. cpu may be -1 indicating the first unassigned.
> @@ -615,10 +612,12 @@ int xc_cpupool_movedomain(xc_interface *
>   *
>   * @parm xc_handle a handle to an open hypervisor interface
>   * @parm cpumap pointer where to store the cpumap
> + * @parm cpusize size of cpumap array in bytes
>   * return 0 on success, -1 on failure
>   */
>  int xc_cpupool_freeinfo(xc_interface *xch,
> -                        uint64_t *cpumap);
> +                        uint64_t *cpumap,
> +                        int cpusize);

xc_cpupool_getinfo returns a callee allocated buffer and
xc_cpupool_freeinfo expects to be given a caller allocated buffer? I
think we should make this consistent one way of the other.

> diff -r 71f836615ea2 tools/libxl/libxl.c
> --- a/tools/libxl/libxl.c       Fri Sep 24 15:54:39 2010 +0100
> +++ b/tools/libxl/libxl.c       Fri Oct 01 09:03:17 2010 +0200
> @@ -610,26 +610,34 @@ libxl_poolinfo * libxl_list_pool(libxl_c
>  libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
>  {
>      libxl_poolinfo *ptr;
> -    int i, ret;
> -    xc_cpupoolinfo_t info[256];
> -    int size = 256;
> +    int i;
> +    xc_cpupoolinfo_t *info;
> +    uint32_t poolid;
> +    libxl_physinfo physinfo;
>  
> -    ptr = calloc(size, sizeof(libxl_poolinfo));
> -    if (!ptr) {
> -        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
> +    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
> +        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting phys info");
>          return NULL;
>      }

Am I missing where the contents of physinfo is subsequently used in this
function?

>  
> -    ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
> -    if (ret<0) {
> -        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting cpupool info");
> -        return NULL;
> +    ptr = NULL;
> +
> +    poolid = 0;
> +    for (i = 0;; i++) {
> +        info = xc_cpupool_getinfo(ctx->xch, poolid);
> +        if (info == NULL)
> +            break;
> +        ptr = realloc(ptr, (i + 1) * sizeof(libxl_poolinfo));
> +        if (!ptr) {
> +            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
> +            return NULL;
> +        }

This will leak the previous value of ptr if realloc() fails. You need to
do:
	tmp = realloc(ptr, ....)
	if (!tmp) {
		free(ptr);
		LIBXL__LOG_ERRNO(...);
		return NULL;
	}
	ptr = tmp;


> diff -r 71f836615ea2 tools/python/xen/lowlevel/xc/xc.c
> --- a/tools/python/xen/lowlevel/xc/xc.c Fri Sep 24 15:54:39 2010 +0100
> +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 01 09:03:17 2010 +0200
> @@ -241,7 +241,7 @@ static PyObject *pyxc_vcpu_setaffinity(X
>      if ( xc_physinfo(self->xc_handle, &info) != 0 )
>          return pyxc_error_to_exception(self->xc_handle);
>    
> -    nr_cpus = info.nr_cpus;
> +    nr_cpus = info.max_cpu_id + 1;
>  
>      size = (nr_cpus + cpumap_size * 8 - 1)/ (cpumap_size * 8);
>      cpumap = malloc(cpumap_size * size);

Is this (and the equivalent in getinfo) an independent bug fix for a
pre-existing issue or does it somehow relate to the rest of the changes?
I don't see any corresponding change to xc_vcpu_setaffinity is all.

Given the repeated uses of physinfo.max_cpu_id (here, in get_cpumap_size
etc) might a xc_get_nr_cpus() function be worthwhile?

Presumably when you change these interfaces to use uint8_t instead of
uint64_t this code becomes the same as the private get_cpumap_size you
defined earlier so it might be worth exporting that functionality from
libxc?

> @@ -1966,7 +1967,7 @@ static PyObject *pyxc_cpupool_getinfo(Xc
>      PyObject *list, *info_dict;
>  
>      uint32_t first_pool = 0;
> -    int max_pools = 1024, nr_pools, i;
> +    int max_pools = 1024, i;
[...]
> +    for (i = 0; i < max_pools; i++)

I don't think there is any 1024 pool limit inherent in the new libxc
code, is there? You've removed the limit from libxl and I think the
right thing to do is remove it here as well.

>      {
> -        free(info);
> -        return pyxc_error_to_exception(self->xc_handle);
> -    }
> -
> -    list = PyList_New(nr_pools);
> -    for ( i = 0 ; i < nr_pools; i++ )
> -    {
> +        info = xc_cpupool_getinfo(self->xc_handle, first_pool);
> +        if (info == NULL)
> +            break;
>          info_dict = Py_BuildValue(
>              "{s:i,s:i,s:i,s:N}",
> -            "cpupool",         (int)info[i].cpupool_id,
> -            "sched",           info[i].sched_id,
> -            "n_dom",           info[i].n_dom,
> -            "cpulist",         cpumap_to_cpulist(info[i].cpumap));
> +            "cpupool",         (int)info->cpupool_id,
> +            "sched",           info->sched_id,
> +            "n_dom",           info->n_dom,
> +            "cpulist",         cpumap_to_cpulist(info->cpumap,
> +                                                 info->cpumap_size));
> +        first_pool = info->cpupool_id + 1;
> +        free(info);
> +
>          if ( info_dict == NULL )
>          {
>              Py_DECREF(list);
> -            if ( info_dict != NULL ) { Py_DECREF(info_dict); }
> -            free(info);
>              return NULL;
>          }
> -        PyList_SetItem(list, i, info_dict);
> +
> +        PyList_Append(list, info_dict);
> +        Py_DECREF(info_dict);
>      }
> -
> -    free(info);
>  
>      return list;
>  }
> @@ -2072,12 +2066,28 @@ static PyObject *pyxc_cpupool_movedomain
>  
>  static PyObject *pyxc_cpupool_freeinfo(XcObject *self)
>  {
> -    uint64_t cpumap;
> +    uint64_t *cpumap;
> +    xc_physinfo_t physinfo;
> +    int ret;
> +    PyObject *info = NULL;
>  
> -    if (xc_cpupool_freeinfo(self->xc_handle, &cpumap) != 0)
> +    if (xc_physinfo(self->xc_handle, &physinfo))
>          return pyxc_error_to_exception(self->xc_handle);
>  
> -    return cpumap_to_cpulist(cpumap);
> +    cpumap = calloc((physinfo.max_cpu_id + 64) / 64, sizeof(uint64_t));

Making xc_cpupool_freeinfo allocate the buffer, like xc_cpupool_getinfo
does would remove the need for this sort of arithmetic in the users of
libxc.

Ian.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch 1/2] support of cpupools in xl: update cpumask handling for cpu pools in libxc and python
  2010-10-01  9:35 ` Ian Campbell
@ 2010-10-05 13:50   ` Juergen Gross
  2010-10-06 13:17     ` Ian Campbell
  0 siblings, 1 reply; 5+ messages in thread
From: Juergen Gross @ 2010-10-05 13:50 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel@lists.xensource.com

On 10/01/10 11:35, Ian Campbell wrote:
> (I highly recommend the patchbomb extension ("hg email"), it makes
> sending series much simpler and threads the mails together in a
> convenient way)

Okay, I'll try hg email for the next round...

>
> On Fri, 2010-10-01 at 08:20 +0100, Juergen Gross wrote:
>> Signed-off-by: juergen.gross@ts.fujitsu.com
>
> This should come after the description.

Okay.

>
>> To be able to support arbitrary numbers of physical cpus it was necessary to
>> include the size of cpumaps in the xc-interfaces for cpu pools.
>> These were:
>>    definition of xc_cpupoolinfo_t
>>    xc_cpupool_getinfo()
>>    xc_cpupool_freeinfo()
>
> Please also mention the change in xc_cpupool_getinfo semantics from
> caller allocated buffer to callee allocated+returned.

Okay.

>
>> @@ -64,50 +78,61 @@ int xc_cpupool_destroy(xc_interface *xch
>>       return do_sysctl_save(xch,&sysctl);
>>   }
>>
>> -int xc_cpupool_getinfo(xc_interface *xch,
>> -                       uint32_t first_poolid,
>> -                       uint32_t n_max,
>> -                       xc_cpupoolinfo_t *info)
>> +xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
>> +                       uint32_t poolid)
> [...]
>> -    memset(info, 0, n_max * sizeof(xc_cpupoolinfo_t));
>> +    local_size = get_cpumap_size(xch);
>> +    local = alloca(local_size);
>> +    if (!local_size)
>> +    {
>> +        PERROR("Could not get number of cpus");
>> +        return NULL;
>> +    }
>
> I imagine alloca(0) is most likely safe so long as you don't actually
> use the result, but the man page doesn't specifically say. Probably the
> check of !local_size should be before the alloca(local_size) to be on
> the safe side.

Yeah, you are right.

>
>> +    cpumap_size = (local_size + sizeof(*info->cpumap) - 1) / sizeof(*info->cpumap);
>
> xg_private.h defines a macro ROUNDUP, I wonder if that should be moved
> somewhere more generic and used to clarify code like this?

Doesn't fit really here (needs the number of bits, e.g. 6 in this case).
As this code will vanish with cpumask rework to be byte-based, I don't
change this now.

>
>> diff -r 8b7d253f0e17 tools/libxc/xenctrl.h
>> --- a/tools/libxc/xenctrl.h     Fri Oct 01 08:39:49 2010 +0100
>> +++ b/tools/libxc/xenctrl.h     Fri Oct 01 09:13:36 2010 +0100
>> @@ -564,15 +565,11 @@ int xc_cpupool_destroy(xc_interface *xch
>> [...]
>> + * @parm poolid lowest id for which info is returned
>> + * return cpupool info ptr (obtained by malloc)
>>    */
>> -int xc_cpupool_getinfo(xc_interface *xch,
>> -                       uint32_t first_poolid,
>> -                       uint32_t n_max,
>> -                       xc_cpupoolinfo_t *info);
>> +xc_cpupoolinfo_t *xc_cpupool_getinfo(xc_interface *xch,
>> +                       uint32_t poolid);
>>
>>   /**
>>    * Add cpu to a cpupool. cpu may be -1 indicating the first unassigned.
>> @@ -615,10 +612,12 @@ int xc_cpupool_movedomain(xc_interface *
>>    *
>>    * @parm xc_handle a handle to an open hypervisor interface
>>    * @parm cpumap pointer where to store the cpumap
>> + * @parm cpusize size of cpumap array in bytes
>>    * return 0 on success, -1 on failure
>>    */
>>   int xc_cpupool_freeinfo(xc_interface *xch,
>> -                        uint64_t *cpumap);
>> +                        uint64_t *cpumap,
>> +                        int cpusize);
>
> xc_cpupool_getinfo returns a callee allocated buffer and
> xc_cpupool_freeinfo expects to be given a caller allocated buffer? I
> think we should make this consistent one way of the other.

Agreed.

>
>> diff -r 71f836615ea2 tools/libxl/libxl.c
>> --- a/tools/libxl/libxl.c       Fri Sep 24 15:54:39 2010 +0100
>> +++ b/tools/libxl/libxl.c       Fri Oct 01 09:03:17 2010 +0200
>> @@ -610,26 +610,34 @@ libxl_poolinfo * libxl_list_pool(libxl_c
>>   libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
>>   {
>>       libxl_poolinfo *ptr;
>> -    int i, ret;
>> -    xc_cpupoolinfo_t info[256];
>> -    int size = 256;
>> +    int i;
>> +    xc_cpupoolinfo_t *info;
>> +    uint32_t poolid;
>> +    libxl_physinfo physinfo;
>>
>> -    ptr = calloc(size, sizeof(libxl_poolinfo));
>> -    if (!ptr) {
>> -        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
>> +    if (libxl_get_physinfo(ctx,&physinfo) != 0) {
>> +        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting phys info");
>>           return NULL;
>>       }
>
> Am I missing where the contents of physinfo is subsequently used in this
> function?

Me too :-)
Should be in the second patch.

>
>>
>> -    ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
>> -    if (ret<0) {
>> -        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting cpupool info");
>> -        return NULL;
>> +    ptr = NULL;
>> +
>> +    poolid = 0;
>> +    for (i = 0;; i++) {
>> +        info = xc_cpupool_getinfo(ctx->xch, poolid);
>> +        if (info == NULL)
>> +            break;
>> +        ptr = realloc(ptr, (i + 1) * sizeof(libxl_poolinfo));
>> +        if (!ptr) {
>> +            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
>> +            return NULL;
>> +        }
>
> This will leak the previous value of ptr if realloc() fails. You need to
> do:
> 	tmp = realloc(ptr, ....)
> 	if (!tmp) {
> 		free(ptr);
> 		LIBXL__LOG_ERRNO(...);
> 		return NULL;
> 	}
> 	ptr = tmp;
>
>

Should be changed in other places, too:
libxc/xc_tmem.c
libxl/libxl.c (sometimes not even checked for error)

>> diff -r 71f836615ea2 tools/python/xen/lowlevel/xc/xc.c
>> --- a/tools/python/xen/lowlevel/xc/xc.c Fri Sep 24 15:54:39 2010 +0100
>> +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 01 09:03:17 2010 +0200
>> @@ -241,7 +241,7 @@ static PyObject *pyxc_vcpu_setaffinity(X
>>       if ( xc_physinfo(self->xc_handle,&info) != 0 )
>>           return pyxc_error_to_exception(self->xc_handle);
>>
>> -    nr_cpus = info.nr_cpus;
>> +    nr_cpus = info.max_cpu_id + 1;
>>
>>       size = (nr_cpus + cpumap_size * 8 - 1)/ (cpumap_size * 8);
>>       cpumap = malloc(cpumap_size * size);
>
> Is this (and the equivalent in getinfo) an independent bug fix for a
> pre-existing issue or does it somehow relate to the rest of the changes?
> I don't see any corresponding change to xc_vcpu_setaffinity is all.

It's an independent fix. OTOH it's cpumask related, so I put it in...
xc_vcpu_setaffinity is not touched as it takes the cpumask size as
parameter.

>
> Given the repeated uses of physinfo.max_cpu_id (here, in get_cpumap_size
> etc) might a xc_get_nr_cpus() function be worthwhile?

Okay. I'll call it xc_get_max_cpus().

>
> Presumably when you change these interfaces to use uint8_t instead of
> uint64_t this code becomes the same as the private get_cpumap_size you
> defined earlier so it might be worth exporting that functionality from
> libxc?

I'll merge these functions later.

>
>> @@ -1966,7 +1967,7 @@ static PyObject *pyxc_cpupool_getinfo(Xc
>>       PyObject *list, *info_dict;
>>
>>       uint32_t first_pool = 0;
>> -    int max_pools = 1024, nr_pools, i;
>> +    int max_pools = 1024, i;
> [...]
>> +    for (i = 0; i<  max_pools; i++)
>
> I don't think there is any 1024 pool limit inherent in the new libxc
> code, is there? You've removed the limit from libxl and I think the
> right thing to do is remove it here as well.

Correct.

>
>>       {
>> -        free(info);
>> -        return pyxc_error_to_exception(self->xc_handle);
>> -    }
>> -
>> -    list = PyList_New(nr_pools);
>> -    for ( i = 0 ; i<  nr_pools; i++ )
>> -    {
>> +        info = xc_cpupool_getinfo(self->xc_handle, first_pool);
>> +        if (info == NULL)
>> +            break;
>>           info_dict = Py_BuildValue(
>>               "{s:i,s:i,s:i,s:N}",
>> -            "cpupool",         (int)info[i].cpupool_id,
>> -            "sched",           info[i].sched_id,
>> -            "n_dom",           info[i].n_dom,
>> -            "cpulist",         cpumap_to_cpulist(info[i].cpumap));
>> +            "cpupool",         (int)info->cpupool_id,
>> +            "sched",           info->sched_id,
>> +            "n_dom",           info->n_dom,
>> +            "cpulist",         cpumap_to_cpulist(info->cpumap,
>> +                                                 info->cpumap_size));
>> +        first_pool = info->cpupool_id + 1;
>> +        free(info);
>> +
>>           if ( info_dict == NULL )
>>           {
>>               Py_DECREF(list);
>> -            if ( info_dict != NULL ) { Py_DECREF(info_dict); }
>> -            free(info);
>>               return NULL;
>>           }
>> -        PyList_SetItem(list, i, info_dict);
>> +
>> +        PyList_Append(list, info_dict);
>> +        Py_DECREF(info_dict);
>>       }
>> -
>> -    free(info);
>>
>>       return list;
>>   }
>> @@ -2072,12 +2066,28 @@ static PyObject *pyxc_cpupool_movedomain
>>
>>   static PyObject *pyxc_cpupool_freeinfo(XcObject *self)
>>   {
>> -    uint64_t cpumap;
>> +    uint64_t *cpumap;
>> +    xc_physinfo_t physinfo;
>> +    int ret;
>> +    PyObject *info = NULL;
>>
>> -    if (xc_cpupool_freeinfo(self->xc_handle,&cpumap) != 0)
>> +    if (xc_physinfo(self->xc_handle,&physinfo))
>>           return pyxc_error_to_exception(self->xc_handle);
>>
>> -    return cpumap_to_cpulist(cpumap);
>> +    cpumap = calloc((physinfo.max_cpu_id + 64) / 64, sizeof(uint64_t));
>
> Making xc_cpupool_freeinfo allocate the buffer, like xc_cpupool_getinfo
> does would remove the need for this sort of arithmetic in the users of
> libxc.

Yes.


Juergen

-- 
Juergen Gross                 Principal Developer Operating Systems
TSP ES&S SWE OS6                       Telephone: +49 (0) 89 3222 2967
Fujitsu Technology Solutions              e-mail: juergen.gross@ts.fujitsu.com
Domagkstr. 28                           Internet: ts.fujitsu.com
D-80807 Muenchen                 Company details: ts.fujitsu.com/imprint.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch 1/2] support of cpupools in xl: update cpumask handling for cpu pools in libxc and python
  2010-10-05 13:50   ` Juergen Gross
@ 2010-10-06 13:17     ` Ian Campbell
  0 siblings, 0 replies; 5+ messages in thread
From: Ian Campbell @ 2010-10-06 13:17 UTC (permalink / raw)
  To: Juergen Gross; +Cc: xen-devel@lists.xensource.com

On Tue, 2010-10-05 at 14:50 +0100, Juergen Gross wrote:
> >
> > This will leak the previous value of ptr if realloc() fails. You need to
> > do:
> >       tmp = realloc(ptr, ....)
> >       if (!tmp) {
> >               free(ptr);
> >               LIBXL__LOG_ERRNO(...);
> >               return NULL;
> >       }
> >       ptr = tmp;
> >
> >
> 
> Should be changed in other places, too:
> libxc/xc_tmem.c
> libxl/libxl.c (sometimes not even checked for error)

Undoubtedly, but lets not make things worse ;-)

I've added this to my todo list...

> >> diff -r 71f836615ea2 tools/python/xen/lowlevel/xc/xc.c
> >> --- a/tools/python/xen/lowlevel/xc/xc.c Fri Sep 24 15:54:39 2010 +0100
> >> +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 01 09:03:17 2010 +0200
> >> @@ -241,7 +241,7 @@ static PyObject *pyxc_vcpu_setaffinity(X
> >>       if ( xc_physinfo(self->xc_handle,&info) != 0 )
> >>           return pyxc_error_to_exception(self->xc_handle);
> >>
> >> -    nr_cpus = info.nr_cpus;
> >> +    nr_cpus = info.max_cpu_id + 1;
> >>
> >>       size = (nr_cpus + cpumap_size * 8 - 1)/ (cpumap_size * 8);
> >>       cpumap = malloc(cpumap_size * size);
> >
> > Is this (and the equivalent in getinfo) an independent bug fix for a
> > pre-existing issue or does it somehow relate to the rest of the changes?
> > I don't see any corresponding change to xc_vcpu_setaffinity is all.
> 
> It's an independent fix. OTOH it's cpumask related, so I put it in...
> xc_vcpu_setaffinity is not touched as it takes the cpumask size as
> parameter.

Please separate unrelated fixes into their own patches. Not least
because it allows you to accurately changelog them.

Thanks,
Ian.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-10-06 13:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-22  5:42 [Patch 1/2] support of cpupools in xl: update cpumask handling for cpu pools in libxc and python Juergen Gross
  -- strict thread matches above, loose matches on Subject: below --
2010-10-01  7:20 Juergen Gross
2010-10-01  9:35 ` Ian Campbell
2010-10-05 13:50   ` Juergen Gross
2010-10-06 13:17     ` Ian Campbell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.