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

[Xen-changelog] [xen stable-4.5] oxenstored: support commit history tracking



commit a28b99d05c2f9e759091a315d65e818c68440d1d
Author:     Jonathan Davies <jonathan.davies@xxxxxxxxxx>
AuthorDate: Tue Mar 14 13:20:07 2017 +0000
Commit:     Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
CommitDate: Wed Apr 5 15:22:33 2017 +0100

    oxenstored: support commit history tracking
    
    Add ability to track xenstore tree operations -- either non-transactional
    operations or committed transactions.
    
    For now, the call to actually retain commits is commented out because 
history
    can grow without bound.
    
    For now, we call record_commit for all non-transactional operations. A
    subsequent patch will make it retain only the ones with side-effects.
    
    Reported-by: Juergen Gross <jgross@xxxxxxxx>
    Signed-off-by: Jonathan Davies <jonathan.davies@xxxxxxxxxx>
    Signed-off-by: Thomas Sanders <thomas.sanders@xxxxxxxxxx>
    Reviewed-by: Christian Lindig <christian.lindig@xxxxxxxxxx>
---
 tools/ocaml/xenstored/Makefile     |  1 +
 tools/ocaml/xenstored/history.ml   | 43 ++++++++++++++++++++++++++++++++++++++
 tools/ocaml/xenstored/process.ml   | 24 +++++++++++++++++++--
 tools/ocaml/xenstored/xenstored.ml |  1 +
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/tools/ocaml/xenstored/Makefile b/tools/ocaml/xenstored/Makefile
index 3d045bb..c92fcc1 100644
--- a/tools/ocaml/xenstored/Makefile
+++ b/tools/ocaml/xenstored/Makefile
@@ -47,6 +47,7 @@ OBJS = define \
        domains \
        connection \
        connections \
+       history \
        parse_arg \
        process \
        xenstored
diff --git a/tools/ocaml/xenstored/history.ml b/tools/ocaml/xenstored/history.ml
new file mode 100644
index 0000000..e4b4d70
--- /dev/null
+++ b/tools/ocaml/xenstored/history.ml
@@ -0,0 +1,43 @@
+(*
+ * Copyright (c) 2017 Citrix Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+type history_record = {
+       con: Connection.t;   (* connection that made a change *)
+       tid: int;            (* transaction id of the change (may be 
Transaction.none) *)
+       before: Store.t;     (* the store before the change *)
+       after: Store.t;      (* the store after the change *)
+       finish_count: int64; (* the commit-count at which the transaction 
finished *)
+}
+
+let history : history_record list ref = ref []
+
+(* Called from periodic_ops to ensure we don't discard symbols that are still 
needed. *)
+(* There is scope for optimisation here, since in consecutive commits one 
commit's `after`
+ * is the same thing as the next commit's `before`, but not all commits in 
history are
+ * consecutive. *)
+let mark_symbols () =
+       (* There are gaps where dom0's commits are missing. Otherwise we could 
assume that
+        * each element's `before` is the same thing as the next element's 
`after`
+        * since the next element is the previous commit *)
+       List.iter (fun hist_rec ->
+                       Store.mark_symbols hist_rec.before;
+                       Store.mark_symbols hist_rec.after;
+               )
+               !history
+
+let push (x: history_record) =
+       let dom = x.con.Connection.dom in
+       match dom with
+       | None -> () (* treat socket connections as always free to conflict *)
+       | Some d -> if not (Domain.is_free_to_conflict d) then history := x :: 
!history
diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
index 0596be2..c38e3ad 100644
--- a/tools/ocaml/xenstored/process.ml
+++ b/tools/ocaml/xenstored/process.ml
@@ -287,6 +287,16 @@ let write_response_log ~ty ~tid ~con ~response =
        | Packet.Reply x -> write_answer_log ~ty ~tid ~con ~data:x
        | Packet.Error e -> write_answer_log ~ty:(Xenbus.Xb.Op.Error) ~tid ~con 
~data:e
 
+let record_commit ~con ~tid ~before ~after =
+       let inc r = r := Int64.add 1L !r in
+       let finish_count = inc Transaction.counter; !Transaction.counter in
+       (* This call would leak memory if historic activity is retained forever
+          so can only be uncommented if history is guaranteed not to grow
+          unboundedly.
+       History.push {History.con=con; tid=tid; before=before; after=after; 
finish_count=finish_count}
+       *)
+       ()
+
 (* Replay a stored transaction against a fresh store, check the responses are
    all equivalent: if so, commit the transaction. Otherwise send the abort to
    the client. *)
@@ -357,8 +367,14 @@ let do_transaction_end con t domains cons data =
                Connection.end_transaction con (Transaction.get_id t) commit in
        if not success then
                raise Transaction_again;
-       if commit then
-               process_watch (List.rev (Transaction.get_paths t)) cons
+       if commit then begin
+               process_watch (List.rev (Transaction.get_paths t)) cons;
+               match t.Transaction.ty with
+               | Transaction.No ->
+                       () (* no need to record anything *)
+               | Transaction.Full(id, oldstore, cstore) ->
+                       record_commit ~con ~tid:id ~before:oldstore 
~after:cstore
+       end
 
 let do_introduce con t domains cons data =
        if not (Connection.is_dom0 con)
@@ -441,7 +457,11 @@ let process_packet ~store ~cons ~doms ~con ~req =
                        else
                                Connection.get_transaction con tid
                        in
+
+               let before = Store.copy store in
                let response = input_handle_error ~cons ~doms ~fct ~con ~t ~req 
in
+               let after = Store.copy store in
+               if tid = Transaction.none then record_commit ~con ~tid ~before 
~after;
 
                let response = try
                        if tid <> Transaction.none then
diff --git a/tools/ocaml/xenstored/xenstored.ml 
b/tools/ocaml/xenstored/xenstored.ml
index daefa7c..be6a1ab 100644
--- a/tools/ocaml/xenstored/xenstored.ml
+++ b/tools/ocaml/xenstored/xenstored.ml
@@ -386,6 +386,7 @@ let _ =
                        Symbol.mark_all_as_unused ();
                        Store.mark_symbols store;
                        Connections.iter cons Connection.mark_symbols;
+                       History.mark_symbols ();
                        Symbol.garbage ()
                end;
 
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.5

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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