WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-api

[Xen-API] [PATCH] move essential suspend/resume code into Vmops so that

To: xen-api@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-API] [PATCH] move essential suspend/resume code into Vmops so that it can be shared with checkpoint
From: David Scott <dave.scott@xxxxxxxxxxxxx>
Date: Tue, 16 Mar 2010 11:32:59 +0000
Delivery-date: Tue, 16 Mar 2010 04:24:16 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-api-request@lists.xensource.com?subject=help>
List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>
List-post: <mailto:xen-api@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-api-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1268739133 0
# Node ID bd84ea5e1a08e0d8019f8ab64a67b96a3a543548
# Parent  012936d9d680683cd83cdcd2cd772985de142c50
CA-37332: move essential suspend/resume-related code (specifically memory and 
PCI device handling) into Vmops so that it can be shared with checkpoint.

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

diff -r 012936d9d680 -r bd84ea5e1a08 ocaml/xapi/vmops.ml
--- a/ocaml/xapi/vmops.ml       Tue Mar 16 11:30:25 2010 +0000
+++ b/ocaml/xapi/vmops.ml       Tue Mar 16 11:32:13 2010 +0000
@@ -748,13 +748,19 @@
 (** Get the suspend VDI, mount the disk, open the file and call _restore*. 
Guarantees to
     always unmount the VDI and, only if the restore succeeds, deletes the VDI 
(otherwise
     an exception from lower-level code propagates out *)
-let restore ~__context ~xc ~xs ~self domid =
+let restore ~__context ~xc ~xs ~self start_paused =
+  let memory_required_kib = Memory.kib_of_bytes_used 
(Memory_check.vm_compute_resume_memory ~__context self) in
+  let snapshot = Helpers.get_boot_record ~__context ~self in
+  (* CA-31759: we always use the live memory_target *)
+  let snapshot = { snapshot with API.vM_memory_target = 
Db.VM.get_memory_target ~__context ~self } in
+
+  let reservation_id = Memory_control.reserve_memory ~__context ~xc ~xs 
~kib:memory_required_kib in
+  let domid = create ~__context ~xc ~xs ~self ~reservation_id snapshot () in
+
   Xapi_xenops_errors.handle_xenops_error
     (fun () ->
        let suspend_vdi = Db.VM.get_suspend_VDI ~__context ~self in
-       let snapshot = Helpers.get_boot_record ~__context ~self in
-       (* CA-31759: we always use the live memory_target *)
-       let snapshot = { snapshot with API.vM_memory_target = 
Db.VM.get_memory_target ~__context ~self } in
+
 
        Sm_fs_ops.with_fs_vdi __context suspend_vdi
         (fun mount_point ->
@@ -806,7 +812,13 @@
        Helpers.call_api_functions ~__context
           (fun rpc session_id ->
              Client.VDI.destroy rpc session_id suspend_vdi);
-       Db.VM.set_suspend_VDI ~__context ~self ~value:Ref.null
+       Db.VM.set_suspend_VDI ~__context ~self ~value:Ref.null;
+
+          Db.VM.set_domid ~__context ~self ~value:(Int64.of_int domid);
+
+          debug "Vmops.restore: %s unpausing domain" (if start_paused then 
"not" else "");
+          if not start_paused then Domain.unpause ~xc domid;
+          plug_pcidevs_noexn ~__context ~vm:self domid (pcidevs_of_vm 
~__context ~vm:self);
     )
 
 
@@ -879,10 +891,33 @@
 exception Domain_architecture_not_supported_in_suspend
 
 let suspend ~live ~progress_cb ~__context ~xc ~xs ~vm =
-       Xapi_xenops_errors.handle_xenops_error
-               (fun () ->
-                       let uuid = Db.VM.get_uuid ~__context ~self:vm in
-                       let hvm = Helpers.has_booted_hvm ~__context ~self:vm in
+  let uuid = Db.VM.get_uuid ~__context ~self:vm in
+  let hvm = Helpers.has_booted_hvm ~__context ~self:vm in
+  let domid = Helpers.domid_of_vm ~__context ~self:vm in
+
+  Xapi_xenops_errors.handle_xenops_error
+         (fun () ->
+                  with_xc_and_xs
+                          (fun xc xs ->
+                                       let is_paused = Db.VM.get_power_state
+                                         ~__context ~self:vm = `Paused in
+                                       if is_paused then Domain.unpause ~xc 
domid;
+                                       let min = Db.VM.get_memory_dynamic_min 
~__context ~self:vm in
+                                       let max = Db.VM.get_memory_dynamic_max 
~__context ~self:vm in
+                                       let min = Int64.to_int (Int64.div min 
1024L) in
+                                       let max = Int64.to_int (Int64.div max 
1024L) in
+                                       try
+                                         (* Balloon down the guest as far as 
we can to force it to clear
+                                                unnecessary caches etc. *)
+                                               debug "suspend phase 0/4: 
asking guest to balloon down";
+                                               Domain.set_memory_dynamic_range 
~xs ~min ~max:min domid;
+                                               Memory_control.balance_memory 
~__context ~xc ~xs;
+                                               
+                                               debug "suspend phase 1/4: 
hot-unplugging any PCI devices";
+                                               let hvm = (Xc.domain_getinfo xc 
domid).Xc.hvm_guest in
+                                               if hvm then 
unplug_pcidevs_noexn ~__context ~vm domid (Device.PCI.list xc xs domid);
+
+
                        let suspend_SR = Helpers.choose_suspend_sr ~__context 
~vm in
                        let required_space = get_suspend_space __context vm in
                        Sm_fs_ops.with_new_fs_vdi __context
@@ -891,7 +926,7 @@
                                ~sm_config:[Xapi_globs._sm_vm_hint, uuid]
                                (fun vdi_ref mount_point ->
                                        let filename = sprintf 
"%s/suspend-image" mount_point in
-                                       debug "suspend: phase 1/2: opening 
suspend image file (%s)"
+                                       debug "suspend: phase 2/4: opening 
suspend image file (%s)"
                                                filename;
                                        (* NB if the suspend file already 
exists it will be *)
                                        (* overwritten. *)
@@ -900,7 +935,7 @@
                                        finally
                                                (fun () ->
                                                        let domid = 
Helpers.domid_of_vm ~__context ~self:vm in
-                                                       debug "suspend: phase 
2/2: suspending to disk";
+                                                       debug "suspend: phase 
3/4: suspending to disk";
                                                        with_xal
                                                                (fun xal ->
                                                                        
Domain.suspend ~xc ~xs ~hvm domid fd []
@@ -926,8 +961,25 @@
                                                                ~value:vdi_ref;
                                                )
                                                (fun () -> Unix.close fd);
-                       debug "suspend: complete")
-               )
+                       debug "suspend: complete");
+
+                       debug "suspend phase 4/4: recording memory usage";
+                       (* Record the final memory usage of the VM, so *)
+                       (* that we know how much memory to free before *)
+                       (* attempting to resume this VM in future.     *)
+                       let di = with_xc (fun xc -> Xc.domain_getinfo xc domid) 
in
+                       let final_memory_bytes = Memory.bytes_of_pages 
(Int64.of_nativeint di.Xc.total_memory_pages) in
+                       debug "total_memory_pages=%Ld; storing target=%Ld" 
(Int64.of_nativeint di.Xc.total_memory_pages) final_memory_bytes;
+                       (* CA-31759: avoid using the LBR to simplify upgrade *)
+                       Db.VM.set_memory_target ~__context ~self:vm 
~value:final_memory_bytes;
+
+          with e ->
+                  Domain.set_memory_dynamic_range ~xs ~min ~max domid;
+                  Memory_control.balance_memory ~__context ~xc ~xs;
+                  if is_paused then
+                        (try Domain.pause ~xc domid with _ -> ());
+                  raise e
+         ))
 
 let resume ~__context ~xc ~xs ~vm =
        let domid = Helpers.domid_of_vm ~__context ~self:vm in
diff -r 012936d9d680 -r bd84ea5e1a08 ocaml/xapi/xapi_vm.ml
--- a/ocaml/xapi/xapi_vm.ml     Tue Mar 16 11:30:25 2010 +0000
+++ b/ocaml/xapi/xapi_vm.ml     Tue Mar 16 11:32:13 2010 +0000
@@ -724,24 +724,6 @@
                                        ~reason:Xapi_hooks.reason__suspend ~vm;
                                with_xc_and_xs
                                (fun xc xs ->
-                                       let is_paused = Db.VM.get_power_state
-                                               ~__context ~self:vm = `Paused in
-                                       if is_paused then Domain.unpause ~xc 
domid;
-                                       let min = Db.VM.get_memory_dynamic_min 
~__context ~self:vm in
-                                       let max = Db.VM.get_memory_dynamic_max 
~__context ~self:vm in
-                                       let min = Int64.to_int (Int64.div min 
1024L) in
-                                       let max = Int64.to_int (Int64.div max 
1024L) in
-                                       try
-                                               (* Balloon down the guest as 
far as we can to force it to clear
-                                                  unnecessary caches etc. *)
-                                               debug "suspend phase 0/4: 
asking guest to balloon down";
-                                               Domain.set_memory_dynamic_range 
~xs ~min ~max:min domid;
-                                               Memory_control.balance_memory 
~__context ~xc ~xs;
-
-                                               debug "suspend phase 1/4: 
hot-unplugging any PCI devices";
-                                               let hvm = (Xc.domain_getinfo xc 
domid).Xc.hvm_guest in
-                                               if hvm then 
Vmops.unplug_pcidevs_noexn ~__context ~vm domid (Device.PCI.list xc xs domid);
-
                                                debug "suspend phase 2/4: 
calling Vmops.suspend";
                                                (* Call the memory image 
creating 90%, *)
                                                (* the device un-hotplug the 
final 10% *)
@@ -750,24 +732,10 @@
                                                                
TaskHelper.set_progress
                                                                ~__context (x 
*. 0.9)
                                                        );
-                                               debug "suspend phase 3/4: 
recording memory usage";
-                                               (* Record the final memory 
usage of the VM, so *)
-                                               (* that we know how much memory 
to free before *)
-                                               (* attempting to resume this VM 
in future.     *)
-                                               let di = with_xc (fun xc -> 
Xc.domain_getinfo xc domid) in
-                                               let final_memory_bytes = 
Memory.bytes_of_pages (Int64.of_nativeint di.Xc.total_memory_pages) in
-                                               debug "total_memory_pages=%Ld; 
storing target=%Ld" (Int64.of_nativeint di.Xc.total_memory_pages) 
final_memory_bytes;
-                                               (* CA-31759: avoid using the 
LBR to simplify upgrade *)
-                                               Db.VM.set_memory_target 
~__context ~self:vm ~value:final_memory_bytes;
                                                debug "suspend phase 4/4: 
destroying the domain";
                                                Vmops.destroy 
~clear_currently_attached:false
                                                        ~__context ~xc ~xs 
~self:vm domid `Suspended;
-                                       with e ->
-                                               Domain.set_memory_dynamic_range 
~xs ~min ~max domid;
-                                               Memory_control.balance_memory 
~__context ~xc ~xs;
-                                               if is_paused then
-                                                       (try Domain.pause ~xc 
domid with _ -> ());
-                                                       raise e
+
                                )
                        )
                ) ()
@@ -789,37 +757,13 @@
                                                debug "resume: making sure the 
VM really is suspended";
                                                assert_power_state_is 
~__context ~vm ~expected:`Suspended;
                                                assert_ha_always_run_is_true 
~__context ~vm;
-                                               let snapshot = 
Helpers.get_boot_record ~__context ~self:vm in
-                                               let memory_required_kib =
-                                                       
Memory.kib_of_bytes_used (
-                                                               
Memory_check.vm_compute_resume_memory
-                                                               ~__context vm) 
in
-(*
-                                               Vmops.with_enough_memory 
~__context ~xc ~xs ~memory_required_kib
-  (fun () ->
-*)
-                                               debug "resume phase 0/3: 
allocating memory";
-                                               let reservation_id = 
Memory_control.reserve_memory ~__context ~xc ~xs ~kib:memory_required_kib in
-                                                       debug "resume phase 
1/3: creating an empty domain";
-                                                       let domid = 
Vmops.create ~__context ~xc ~xs ~self:vm ~reservation_id
-                                                               snapshot () in
 
-                                                       debug "resume phase 
2/3: executing Vmops.restore";
+
                                                        (* vmops.restore 
guarantees that, if an exn occurs *)
                                                        (* during execution, 
any disks that were attached/ *)
                                                        (* activated have been 
detached/de-activated and   *)
                                                        (* the domain is 
destroyed.                        *)
-                                                       Vmops.restore 
~__context ~xc ~xs ~self:vm domid;
-                                                       Db.VM.set_domid 
~__context ~self:vm
-                                                               
~value:(Int64.of_int domid);
-
-                                                       debug "resume phase 
3/3: %s unpausing domain"
-                                                               (if 
start_paused then "not" else "");
-                                                       if not start_paused 
then begin
-                                                               Domain.unpause 
~xc domid;
-                                                       end;
-
-                                                       
Vmops.plug_pcidevs_noexn ~__context ~vm domid (Vmops.pcidevs_of_vm ~__context 
~vm);
+                                                       Vmops.restore 
~__context ~xc ~xs ~self:vm start_paused;
 
                                                        (* VM is now resident 
here *)
                                                        let localhost = 
Helpers.get_localhost ~__context in
2 files changed, 68 insertions(+), 72 deletions(-)
ocaml/xapi/vmops.ml   |   78 ++++++++++++++++++++++++++++++++++++++++---------
ocaml/xapi/xapi_vm.ml |   62 +-------------------------------------


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

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-API] [PATCH] move essential suspend/resume code into Vmops so that it can be shared with checkpoint, David Scott <=