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

[Xen-API] [PATCH] Fix bug with maxmem handling



# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1264521078 0
# Node ID b001a306fbc2128979e1b7471bc34d14e6a03a02
# Parent  22cd3f304b9e0818b80ac5a40e6d4c6438c5e58a
CA-36316: fix a bug where the domain's maxmem gets out of sync in the case when 
no ballooning is required e.g. if dynamic_min = dynamic_max. This causes 
subsequent suspend/resume or migrate operations to demand more memory than they 
strictly need.

The problem is caused by:
1. xapi creates the domain and sets maxmem = static_max
2. squeezed modifies maxmem only if it is doing some squeezing; if dynamic_min 
= dynamic_max then no squeezing is necessary
3. xapi uses max(memory_actual, maxmem) as the amount "needed" by 
suspend/resume/migrate

Since squeezed is managing maxmem, this patch makes it always reset maxmems to 
low values in its polling loop. Note that there is a cache so we don't issue 
more hypercalls than we actually need.

Also fix a logging glitch where if dynamic_min = dynamic_max, large negative 
numbers were written to the log (but not used for anything)

Signed-off-by: David Scott <dave.scott@xxxxxxxxxxxxx>

diff -r 22cd3f304b9e -r b001a306fbc2 ocaml/xenops/squeeze.ml
--- a/ocaml/xenops/squeeze.ml   Thu Jan 21 15:45:09 2010 +0000
+++ b/ocaml/xenops/squeeze.ml   Tue Jan 26 15:51:18 2010 +0000
@@ -292,11 +292,13 @@
          (* We allocate surplus memory in proportion to each domain's 
dynamic_range: *)
          let allocate gamma domain = Int64.of_float (gamma *. (Int64.to_float 
(range domain))) in
          (* gamma = the proportion where 0 <= gamma <= 1 *)
-         let total_range = Int64.to_float (sum (List.map range domains)) in
-         let gamma' = Int64.to_float surplus_memory_kib /. total_range in
+         let total_range = sum (List.map range domains) in
+         let gamma' = Int64.to_float surplus_memory_kib /. (Int64.to_float 
total_range) in
          let gamma = constrain 0. 1. gamma' in
+         debug "total_range = %Ld gamma = %f gamma' = %f" total_range gamma 
gamma';
          if verbose
-         then debug "Total additional memory over dynamic_min = %Ld KiB; will 
set gamma = %.2f (leaving unallocated %Ld KiB)" surplus_memory_kib gamma 
(Int64.of_float (total_range *. (gamma' -. gamma)));
+         then debug "Total additional memory over dynamic_min = %Ld KiB; will 
set gamma = %.2f (leaving unallocated %Ld KiB)" surplus_memory_kib gamma 
+               (if total_range = 0L then 0L else Int64.of_float 
(Int64.to_float total_range *. (gamma' -. gamma)));
 
          List.map (fun domain -> domain, domain.dynamic_min_kib +* (allocate 
gamma domain)) domains
 
@@ -521,30 +523,18 @@
     let debug_string = String.concat "; " (host_debug_string :: (List.map (fun 
domain -> short_string_of_domain domain ^ (new_target_direction domain)) 
host.domains)) in
     debug "%s" debug_string;
     
-    (* Deal with inactive and 'never been run' domains *)
-    List.iter (fun domid -> 
-                try
-                  let domain = IntMap.find domid host.domid_to_domain in
-                  let mem_max_kib = min domain.target_kib 
domain.memory_actual_kib in
-                  debug "Setting inactive domain %d mem_max = %Ld" domid 
mem_max_kib;
-                  io.domain_setmaxmem domid mem_max_kib
-                with Not_found ->
-                  debug "WARNING: inactive domain %d not in map" domid
-             ) declared_inactive_domids;
-    (* Next deal with the active domains (which may have new targets) *)
-    List.iter (fun domid ->
-                try
-                  let domain = IntMap.find domid host.domid_to_domain in
-                  let mem_max_kib = 
-                    if List.mem_assoc domid new_targets 
-                    then List.assoc domid new_targets 
-                    else domain.target_kib in
-                  debug "Setting active domain %d mem_max = %Ld" domid 
mem_max_kib;
-                  io.domain_setmaxmem domid mem_max_kib
-                with Not_found ->
-                  debug "WARNING: active domain %d not in map" domid
-             ) declared_active_domids;
-    
+       (* For each domid, decide what maxmem should be *)
+       let maxmems = IntMap.mapi
+         (fun domid domain ->
+                  if List.mem domid declared_inactive_domids 
+                  then min domain.target_kib domain.memory_actual_kib
+                  else 
+                        if List.mem_assoc domid new_targets
+                        then List.assoc domid new_targets
+                        else domain.target_kib) host.domid_to_domain in
+
+       IntMap.iter io.domain_setmaxmem maxmems;
+
     begin match result with
     | Success ->
                  if io.verbose
diff -r 22cd3f304b9e -r b001a306fbc2 ocaml/xenops/squeeze_xen.ml
--- a/ocaml/xenops/squeeze_xen.ml       Thu Jan 21 15:45:09 2010 +0000
+++ b/ocaml/xenops/squeeze_xen.ml       Tue Jan 26 15:51:18 2010 +0000
@@ -359,11 +359,20 @@
        reserved_kib := Int64.add !reserved_kib non_domain_reservations;
 
        let host = Squeeze.make_host ~domains ~free_mem_kib:(Int64.sub 
free_mem_kib !reserved_kib) in
+       Domain.gc (List.map (fun di -> di.Xc.domid) domain_infolist);
 
+       (* Externally-visible side-effects. It's a bit ugly to include these 
here: *)
        update_cooperative_table host;
        update_cooperative_flags cnx;
 
-       Domain.gc (List.map (fun di -> di.Xc.domid) domain_infolist);
+       (* It's always safe to _decrease_ a domain's maxmem towards target. 
This catches the case
+          where a toolstack creates a domain with maxmem = static_max and 
target < static_max (eg
+          CA-36316) *)
+       let updates = Squeeze.IntMap.fold (fun domid domain updates ->
+                                                                               
   if domain.Squeeze.target_kib < (Domain.get_maxmem (xc, xs) domid)
+                                                                               
   then Squeeze.IntMap.add domid domain.Squeeze.target_kib updates
+                                                                               
   else updates) host.Squeeze.domid_to_domain Squeeze.IntMap.empty in
+       Squeeze.IntMap.iter (Domain.set_maxmem_noexn (xc, xs)) updates;
 
        Printf.sprintf "F%Ld S%Ld R%Ld T%Ld" free_pages_kib scrub_pages_kib 
!reserved_kib total_pages_kib, host
 
2 files changed, 27 insertions(+), 28 deletions(-)
ocaml/xenops/squeeze.ml     |   44 ++++++++++++++++---------------------------
ocaml/xenops/squeeze_xen.ml |   11 +++++++++-


Attachment: xen-api.hg.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api

 


Rackspace

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