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

Re: [Xen-devel] [PATCH] libxl: fix "xl mem-set" regression from 0c029c4da2



On Wed, 22 Apr 2015, Jan Beulich wrote:
> Said commit ("libxl_set_memory_target: retain the same maxmem offset on
> top of the current target") caused a regression for "xl mem-set"
> against Dom0: While prior to creation of the first domain this works,
> the first domain creation involving ballooning breaks. Due to "enforce"
> not being set in the domain creation case, and due to Dom0's initial
> ->max_pages (in the hypervisor) being UINT_MAX, the calculation of
> "memorykb" in the first "xl mem-set" adusting the target upwards
> subsequent to domain creation and termination may cause an overflow,
> resulting in Dom0's maximum getting to a very small value. This small
> maximum will the make the subsequent setting of the PoD target fail.
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> Note that this only fixes the immediate problem - there appear to be
> further issues lurking here:
> - libxl_set_memory_target()'s *_memkb variables all being 32-bit,
> - libxl_domain_setmaxmem()'s max_memkb parameter being 32-bit,
> - other similar code living elsewhere?
> Note also that this requires
> http://lists.xenproject.org/archives/html/xen-devel/2015-04/msg02485.html 
> (or some other change avoiding truncation) to also be in place in order
> to address the observed problem.
> Note further that xc_domain_setmaxmem() is being used by upstream qemu
> and hence the libxc interface change here may represent a compatibility
> issue.
> Finally the setting of a PoD target for non-HVM domains seems bogus too
> (even if it's expected to just be a no-op in that case).
> 
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -1256,7 +1256,7 @@ int xc_getcpuinfo(xc_interface *xch, int
>  
>  int xc_domain_setmaxmem(xc_interface *xch,
>                          uint32_t domid,
> -                        unsigned int max_memkb);
> +                        uint64_t max_memkb);
>  
>  int xc_domain_set_memmap_limit(xc_interface *xch,
>                                 uint32_t domid,
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -634,7 +634,7 @@ int xc_shadow_control(xc_interface *xch,
>  
>  int xc_domain_setmaxmem(xc_interface *xch,
>                          uint32_t domid,
> -                        unsigned int max_memkb)
> +                        uint64_t max_memkb)
>  {
>      DECLARE_DOMCTL;
>      domctl.cmd = XEN_DOMCTL_max_mem;
>
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -4726,7 +4726,8 @@ int libxl_set_memory_target(libxl_ctx *c
>  {
>      GC_INIT(ctx);
>      int rc = 1, abort_transaction = 0;
> -    uint32_t memorykb = 0, videoram = 0;
> +    uint64_t memorykb;
> +    uint32_t videoram = 0;
>      uint32_t current_target_memkb = 0, new_target_memkb = 0;
>      uint32_t current_max_memkb = 0;
>      char *memmax, *endptr, *videoram_s = NULL, *target = NULL;

From the description of the problem above, we have two issues:

1) we don't detect that maxmem is already UINT_MAX*4, so we shouldn't try
   to increase it

2) unsigned int / uint64_t mismatch


1) is pretty easy and might just come down to one more if statement in
libxl_set_memory_target. Something like:


#define MAXMEM_MAX_KB ((uint64_t)UINT32_MAX * 4)
if ((new_target_memkb - current_target_memkb) > 0 && 
    (ptr.max_memkb - new_target_memkb + current_target_memkb) < ptr.max_memkb)
{
    /* avoid overflow */
   rc = xc_domain_setmaxmem(ctx->xch, domid, MAXMEM_MAX_KB);
} else {
   rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb);
}


2) is difficult as we have unsigned int in many many places.  Not only
we need to fix the libxc interface, but as far as I can tell we also
need to fix at least libxl_set_memory_target,
libxl__fill_dom0_memory_info, libxl__get_memory_target, all the callers.
This is the minimum set of changes I think are required:


diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 511eef1..3e91203 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -4641,8 +4641,8 @@ out:
     return rc;
 }
 
-static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint32_t *target_memkb,
-                                        uint32_t *max_memkb)
+static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint64_t *target_memkb,
+                                        uint64_t *max_memkb)
 {
     int rc;
     libxl_dominfo info;
@@ -4666,7 +4666,7 @@ retry_transaction:
     }
 
     if (target) {
-        *target_memkb = strtoul(target, &endptr, 10);
+        *target_memkb = strtoull(target, &endptr, 10);
         if (*endptr != '\0') {
             LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                     "invalid memory target %s from %s\n", target, target_path);
@@ -4676,7 +4676,7 @@ retry_transaction:
     }
 
     if (staticmax) {
-        *max_memkb = strtoul(staticmax, &endptr, 10);
+        *max_memkb = strtoull(staticmax, &endptr, 10);
         if (*endptr != '\0') {
             LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                              "invalid memory static-max %s from %s\n",
@@ -4697,14 +4697,14 @@ retry_transaction:
         goto out;
 
     if (target == NULL) {
-        libxl__xs_write(gc, t, target_path, "%"PRIu32,
-                (uint32_t) info.current_memkb);
-        *target_memkb = (uint32_t) info.current_memkb;
+        libxl__xs_write(gc, t, target_path, "%"PRIu64,
+                info.current_memkb);
+        *target_memkb = info.current_memkb;
     }
     if (staticmax == NULL) {
-        libxl__xs_write(gc, t, max_path, "%"PRIu32,
-                        (uint32_t) info.max_memkb);
-        *max_memkb = (uint32_t) info.max_memkb;
+        libxl__xs_write(gc, t, max_path, "%"PRIu64,
+                        info.max_memkb);
+        *max_memkb = info.max_memkb;
     }
 
     rc = 0;
@@ -4726,9 +4726,9 @@ int libxl_set_memory_target(libxl_ctx *ctx, uint32_t 
domid,
 {
     GC_INIT(ctx);
     int rc = 1, abort_transaction = 0;
-    uint32_t memorykb = 0, videoram = 0;
-    uint32_t current_target_memkb = 0, new_target_memkb = 0;
-    uint32_t current_max_memkb = 0;
+    uint64_t memorykb = 0, videoram = 0;
+    uint64_t current_target_memkb = 0, new_target_memkb = 0;
+    uint64_t current_max_memkb = 0;
     char *memmax, *endptr, *videoram_s = NULL, *target = NULL;
     char *dompath = libxl__xs_get_dompath(gc, domid);
     libxl_dominfo ptr;
@@ -4761,7 +4761,7 @@ retry_transaction:
         abort_transaction = 1;
         goto out;
     } else {
-        current_target_memkb = strtoul(target, &endptr, 10);
+        current_target_memkb = strtoull(target, &endptr, 10);
         if (*endptr != '\0') {
             LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                     "invalid memory target %s from %s/memory/target\n",
@@ -4779,7 +4779,7 @@ retry_transaction:
         abort_transaction = 1;
         goto out;
     }
-    memorykb = strtoul(memmax, &endptr, 10);
+    memorykb = strtoull(memmax, &endptr, 10);
     if (*endptr != '\0') {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                 "invalid max memory %s from %s/memory/static-max\n",
@@ -4790,7 +4790,17 @@ retry_transaction:
 
     videoram_s = libxl__xs_read(gc, t, libxl__sprintf(gc,
                 "%s/memory/videoram", dompath));
-    videoram = videoram_s ? atoi(videoram_s) : 0;
+    if (!videoram_s) {
+        videoram = 0;
+    } else {
+        videoram = strtoull(videoram_s, &endptr, 10);
+        if (*endptr != '\0') {
+            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
+                    "invalid videoram %s\n", videoram_s);
+            abort_transaction = 1;
+            goto out;
+        }
+    }
 
     if (relative) {
         if (target_memkb < 0 && abs(target_memkb) > current_target_memkb)
@@ -4809,7 +4819,7 @@ retry_transaction:
 
     if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) {
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
-                "new target %d for dom0 is below the minimum threshold\n",
+                "new target %"PRIu64" for dom0 is below the minimum 
threshold\n",
                  new_target_memkb);
         abort_transaction = 1;
         goto out;
@@ -4820,7 +4830,7 @@ retry_transaction:
         rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb);
         if (rc != 0) {
             LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
-                    "xc_domain_setmaxmem domid=%d memkb=%d failed "
+                    "xc_domain_setmaxmem domid=%d memkb=%"PRIu64" failed "
                     "rc=%d\n", domid, memorykb, rc);
             abort_transaction = 1;
             goto out;
@@ -4831,7 +4841,7 @@ retry_transaction:
             new_target_memkb / 4, NULL, NULL, NULL);
     if (rc != 0) {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
-                "xc_domain_set_pod_target domid=%d, memkb=%d "
+                "xc_domain_set_pod_target domid=%d, memkb=%"PRIu64" "
                 "failed rc=%d\n", domid, new_target_memkb / 4,
                 rc);
         abort_transaction = 1;
@@ -4839,10 +4849,10 @@ retry_transaction:
     }
 
     libxl__xs_write(gc, t, libxl__sprintf(gc, "%s/memory/target",
-                dompath), "%"PRIu32, new_target_memkb);
+                dompath), "%"PRIu64, new_target_memkb);
 
     libxl__xs_write(gc, t, libxl__sprintf(gc, "/vm/%s/memory", uuid),
-            "%"PRIu32, new_target_memkb / 1024);
+            "%"PRIu64, new_target_memkb / 1024);
 
 out:
     if (!xs_transaction_end(ctx->xsh, t, abort_transaction)
@@ -4858,13 +4868,13 @@ out_no_transaction:
 
 /* out_target_memkb and out_max_memkb can be NULL */
 static int libxl__get_memory_target(libxl__gc *gc, uint32_t domid,
-                                    uint32_t *out_target_memkb,
-                                    uint32_t *out_max_memkb)
+                                    uint64_t *out_target_memkb,
+                                    uint64_t *out_max_memkb)
 {
     int rc;
     char *target = NULL, *static_max = NULL, *endptr = NULL;
     char *dompath = libxl__xs_get_dompath(gc, domid);
-    uint32_t target_memkb, max_memkb;
+    uint64_t target_memkb, max_memkb;
 
     target = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc,
                     "%s/memory/target", dompath));
@@ -4888,14 +4898,14 @@ static int libxl__get_memory_target(libxl__gc *gc, 
uint32_t domid,
                 dompath);
         goto out;
     } else {
-        target_memkb = strtoul(target, &endptr, 10);
+        target_memkb = strtoull(target, &endptr, 10);
         if (*endptr != '\0') {
             LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
                     "invalid memory target %s from %s/memory/target\n",
                     target, dompath);
             goto out;
         }
-        max_memkb = strtoul(static_max, &endptr, 10);
+        max_memkb = strtoull(static_max, &endptr, 10);
         if (*endptr != '\0') {
             LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR,
                     "invalid memory target %s from %s/memory/static-max\n",
@@ -4918,7 +4928,7 @@ out:
 }
 
 int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid,
-                            uint32_t *out_target)
+                            uint64_t *out_target)
 {
     GC_INIT(ctx);
     int rc;
@@ -5006,7 +5016,7 @@ out:
 int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs)
 {
     int rc = 0;
-    uint32_t target_memkb = 0;
+    uint64_t target_memkb = 0;
     uint64_t current_memkb, prev_memkb;
     libxl_dominfo info;
 
@@ -6652,7 +6662,7 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, 
uint32_t domid,
      * "target" and "static-max".
      */
     {
-        uint32_t target_memkb = 0, max_memkb = 0;
+        uint64_t target_memkb = 0, max_memkb = 0;
 
         /* "target" */
         rc = libxl__get_memory_target(gc, domid, &target_memkb, &max_memkb);
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 6bc75c5..3b2daa8 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1047,7 +1047,7 @@ int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid,
 
 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t 
target_memkb);
 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, int32_t 
target_memkb, int relative, int enforce);
-int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t 
*out_target);
+int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid, uint64_t 
*out_target);
 
 
 /*

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.