]> xenbits.xensource.com Git - xen.git/commitdiff
fix listing of vcpus when domains lacking any vcpus exist
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 13 Nov 2014 08:42:03 +0000 (09:42 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 13 Nov 2014 08:42:03 +0000 (09:42 +0100)
On a system which looks like this:

[root@st04 ~]# xl list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0   752     4     r-----   46699.3
(null)                                       1     0     0     --p---       0.0
(null)                                       2     0     0     --p---       0.0
(null)                                       3     0     0     --p---       0.0
badger                                      25     0     1     --p---       0.0

`xl vcpu-list` failes as so:

[root@st04 ~]# xl vcpu-list
Name                                ID  VCPU   CPU State   Time(s) CPU Affinity
Domain-0                             0     0    0   -b-   12171.0  all
Domain-0                             0     1    1   -b-   11779.6  all
Domain-0                             0     2    2   -b-   11599.0  all
Domain-0                             0     3    3   r--   11007.0  all
libxl: critical: libxl__calloc: libxl: FATAL ERROR: memory allocation failure (libxl__calloc, 4294935299 x 40)
: Cannot allocate memory
libxl: FATAL ERROR: memory allocation failure (libxl__calloc, 4294935299 x 40)

The root cause of this is in Xen.  getdomaininfo() has no way of expressing
"this domain has no vcpus".  Previously, info->max_vcpu_id would be returned
uninitialised in such a case.

Unfortunately, setting it to 0 as a default is not appropriate.  A max_vcpu_id
of 0 and nr_online_cpus of 0 is the valid state for a single vcpu domain which
is in the process of being destroyed.

As all components are required to add 1 to max_vcpu_id to get the number of
vcpus, an id of ~0U is not valid to be used.  Explicitly define this as an
invalid max vcpu value, and use it to express "no vcpus" in getdomaininfo()

In libxl, the issue is seen as libxl_list_vcpu() attempts to use the
uninitialised domaininfo.max_vcpu_id for memory allocation.

Check domaininfo.max_vcpu_id against the new sentinel value
XEN_INVALID_MAX_VCPU_ID, and return early.  This means that it is now valid
for libxl_list_vcpu() to return NULL for a domain which lacks any vcpus.

As part of this change, remove the pointless call to libxl_get_max_cpus(),
whose returned value is unconditionally clobbered in the for() loop.

Reported-by: Euan Harris <euan.harris@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Don Slutz <dslutz@verizon.com>
Acked-by: Ian Campbell <Ian.Campbell@citrix.com>
tools/libxl: Fix libxl_list_vcpu() following c/s 93e52d52

My reasoning regarding nr_cpus_out was wrong, as I had confused nr_cpus_out
with nr_vcpus_out.

Dario pointed this out, but the patch (having gained appropriate acks) got
committed before I could post a correction.

Noticed-by: Dario Faggioli <dario.faggioli@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Dario Faggioli <dario.faggioli@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
master commit: 93e52d5242804ff928131553599afa769f85481b
master date: 2014-10-23 10:19:53 +0200
master commit: c90a755f261b8ccb3dac7e1f695122cac95c6053
master date: 2014-10-23 12:29:00 +0100

tools/libxl/libxl.c
tools/libxl/xl_cmdimpl.c
xen/common/domctl.c
xen/include/public/domctl.h

index 2d29ad2ce010a3c69c410b6148d412c59338a5aa..0e41739b9df2918a54d067ffae42be0e38e3f62c 100644 (file)
@@ -4551,6 +4551,12 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
         GC_FREE;
         return NULL;
     }
+
+    if (domaininfo.max_vcpu_id == XEN_INVALID_MAX_VCPU_ID) {
+        GC_FREE;
+        return NULL;
+    }
+
     *nr_cpus_out = libxl_get_max_cpus(ctx);
     ret = ptr = libxl__calloc(NOGC, domaininfo.max_vcpu_id + 1,
                               sizeof(libxl_vcpuinfo));
index 4fc46eb26b7d2fc7224f7f054e7578e0fa974d1e..d1c45e44f8faf4f506d6314c04aa69723c9b47f2 100644 (file)
@@ -4580,10 +4580,8 @@ static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
 
     vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nrcpus);
 
-    if (!vcpuinfo) {
-        fprintf(stderr, "libxl_list_vcpu failed.\n");
+    if (!vcpuinfo)
         return;
-    }
 
     for (i = 0; i < nb_vcpu; i++) {
         print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
index 060af1b8fe934bfe6f287d8b6025516267f1fcad..3a558830d1865da04e7502b1b56419ffb9c0f5ab 100644 (file)
@@ -154,6 +154,7 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
     struct vcpu_runstate_info runstate;
     
     info->domain = d->domain_id;
+    info->max_vcpu_id = XEN_INVALID_MAX_VCPU_ID;
     info->nr_online_vcpus = 0;
     info->ssidref = 0;
     
index f22fe2eaa2dc1ed61f1b5f4a685a634b87c6a3b1..7e0b51776c3713a20862461582569f96eb5ec453 100644 (file)
@@ -107,6 +107,7 @@ struct xen_domctl_getdomaininfo {
     uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
     uint64_aligned_t cpu_time;
     uint32_t nr_online_vcpus;    /* Number of VCPUs currently online. */
+#define XEN_INVALID_MAX_VCPU_ID (~0U) /* Domain has no vcpus? */
     uint32_t max_vcpu_id;        /* Maximum VCPUID in use by this domain. */
     uint32_t ssidref;
     xen_domain_handle_t handle;