# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1260486289 0
# Node ID ca92f46da128588874c6c660aef6409adae119dd
# Parent 90cd62326033db94c84c9c8f607f27335e3c76c4
CA-33707: Refactor the xenops shutdown functions to (i) make them robust to
being called in parallel with (eg) domain destroy; and (ii) to make it possible
to call 'shutdown' more than once.
One side-effect is that if a guest misses the initial signal to shutdown then
we can try a few more times before giving up.
Signed-off-by: David Scott <dave.scott@xxxxxxxxxxxxx>
diff -r 90cd62326033 -r ca92f46da128 ocaml/xenops/domain.ml
--- a/ocaml/xenops/domain.ml Thu Dec 10 23:04:48 2009 +0000
+++ b/ocaml/xenops/domain.ml Thu Dec 10 23:04:49 2009 +0000
@@ -201,41 +201,47 @@
(** Return the path in xenstore watched by the PV shutdown driver *)
let control_shutdown ~xs domid = xs.Xs.getdomainpath domid ^
"/control/shutdown"
+(** Raised if a domain has vanished *)
+exception Domain_does_not_exist
+
(** Request a shutdown, return without waiting for acknowledgement *)
let shutdown ~xs domid req =
debug "Requesting shutdown of domain %d" domid;
let reason = string_of_shutdown_reason req in
- xs.Xs.write (control_shutdown ~xs domid) reason
+ let path = control_shutdown ~xs domid in
+ let domainpath = xs.Xs.getdomainpath domid in
+ Xs.transaction xs
+ (fun t ->
+ (* Fail if the directory has been deleted *)
+ let domain_exists = try ignore (t.Xst.read
domainpath); true with Xb.Noent -> false in
+ if not domain_exists then raise Domain_does_not_exist;
+ (* Delete the node if it already exists. NB: the guest
may well still shutdown for the
+ previous reason... we only want to give it a
kick again just in case. *)
+ (try t.Xst.rm path with _ -> ());
+ t.Xst.write path reason
+ )
-(** PV domains will acknowledge the request by deleting the node from the
- store, block until this happens. *)
-let shutdown_wait_for_ack ?timeout ~xs domid req =
+(** If domain is PV, signal it to shutdown. If the PV domain fails to respond
then throw a Watch.Timeout exception.
+ All other exceptions imply the domain has disappeared. *)
+let shutdown_wait_for_ack ?(timeout=60.) ~xc ~xs domid req =
+ let di = Xc.domain_getinfo xc domid in
+
+ if di.Xc.hvm_guest then begin
+ if Xc.hvm_check_pvdriver xc domid
+ then debug "HVM guest with PV drivers: not expecting any
acknowledgement"
+ else Xc.domain_shutdown xc domid (shutdown_to_xc_shutdown req)
+ end else begin
debug "Waiting for PV domain %d to acknowledge shutdown request" domid;
let path = control_shutdown ~xs domid in
- try
- Watch.wait_for ~xs ?timeout (Watch.value_to_become path "");
- debug "Domain acknowledged shutdown request";
- true
- with Watch.Timeout _ ->
- debug "Timed-out waiting for domain to acknowledge shutdown request";
- false
-
-
-let shutdown_ack ?(timeout=60.) ~xc ~xs domid req =
- (* For both PV and HVM, write the control/shutdown node *)
- shutdown ~xs domid req;
- (* PV domains will acknowledge the request (if not then something
- very bad is wrong) *)
- if not((Xc.domain_getinfo xc domid).Xc.hvm_guest)
- then shutdown_wait_for_ack ~timeout ~xs domid req
- else begin
- (* If HVM domain has no PV drivers, we shut it down here *)
- if not(Xc.hvm_check_pvdriver xc domid)
- then Xc.domain_shutdown xc domid (shutdown_to_xc_shutdown req);
- (* If HVM domain has PV drivers, it shuts itself down but it
- doesn't remove the control/shutdown node. *)
- true
- end
+ (* If already shutdown then we continue *)
+ if not di.Xc.shutdown
+ then match Watch.wait_for ~xs ~timeout (Watch.any_of [ `Ack,
Watch.value_to_become path "";
+
`Gone, Watch.key_to_disappear path ]) with
+ | `Ack, _ ->
+ debug "Domain acknowledged shutdown request"
+ | `Gone, _ ->
+ debug "Domain disappeared"
+ end
let sysrq ~xs domid key =
let path = xs.Xs.getdomainpath domid ^ "/control/sysrq" in
diff -r 90cd62326033 -r ca92f46da128 ocaml/xenops/domain.mli
--- a/ocaml/xenops/domain.mli Thu Dec 10 23:04:48 2009 +0000
+++ b/ocaml/xenops/domain.mli Thu Dec 10 23:04:49 2009 +0000
@@ -77,6 +77,9 @@
(** Immediately force shutdown the domain with reason 'shutdown_reason' *)
val hard_shutdown: xc:Xc.handle -> domid -> shutdown_reason -> unit
+
+(** Thrown if the domain has disappeared *)
+exception Domain_does_not_exist
(** Tell the domain to shutdown with reason 'shutdown_reason'. Don't wait for
an ack *)
val shutdown: xs:Xs.xsh -> domid -> shutdown_reason -> unit
2 files changed, 37 insertions(+), 28 deletions(-)
ocaml/xenops/domain.ml | 62 +++++++++++++++++++++++++----------------------
ocaml/xenops/domain.mli | 3 ++
xen-api.hg-4.patch
Description: Text Data
_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
|