summaryrefslogtreecommitdiff
path: root/system/xen/xsa/xsa206-4.8-0012-oxenstored-allow-self-conflicts.patch
blob: 4a46db4c1448cecf3d44133a0def11e485af4b86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
From d3a8b4ffde38f01aa7f497d07404478b6f90041c Mon Sep 17 00:00:00 2001
From: Thomas Sanders <thomas.sanders@citrix.com>
Date: Thu, 23 Mar 2017 19:06:54 +0000
Subject: [PATCH 12/15] oxenstored: allow self-conflicts

We already avoid inter-domain conflicts but now allow intra-domain
conflicts.  Although there are no known practical examples of a domain
that might perform operations that conflict with its own transactions,
this is conceivable, so here we avoid changing those semantics
unnecessarily.

When a transaction commit fails with a conflict and we look through
the history of commits to see which connection(s) to blame, ignore
historical commits that were made by the same connection as the
failing commit.

Reported-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Thomas Sanders <thomas.sanders@citrix.com>
Reviewed-by: Jonathan Davies <jonathan.davies@citrix.com>
---
 tools/ocaml/xenstored/history.ml | 3 ++-
 tools/ocaml/xenstored/process.ml | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/ocaml/xenstored/history.ml b/tools/ocaml/xenstored/history.ml
index e941e2b..4079588 100644
--- a/tools/ocaml/xenstored/history.ml
+++ b/tools/ocaml/xenstored/history.ml
@@ -60,11 +60,12 @@ let push (x: history_record) =
 	| Some d -> if not (Domain.is_free_to_conflict d) then history := x :: !history
 
 (* Find the connections from records since commit-count [since] for which [f record] returns [true] *)
-let filter_connections ~since ~f =
+let filter_connections ~ignore ~since ~f =
 	(* The "mem" call is an optimisation, to avoid calling f if we have picked con already. *)
 	(* Using a hash table rather than a list is to optimise the "mem" call. *)
 	List.fold_left (fun acc hist_rec ->
 		if hist_rec.finish_count > since
+		&& not (hist_rec.con == ignore)
 		&& not (Hashtbl.mem acc hist_rec.con)
 		&& f hist_rec
 		then Hashtbl.replace acc hist_rec.con ();
diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
index 5e5a1ab..b56e3fc 100644
--- a/tools/ocaml/xenstored/process.ml
+++ b/tools/ocaml/xenstored/process.ml
@@ -350,7 +350,7 @@ let transaction_replay c t doms cons =
 					then (punish hist_rec.History.con; true)
 					else false
 				) in
-				let guilty_cons = History.filter_connections ~since:t.Transaction.start_count ~f:judge_and_sentence in
+				let guilty_cons = History.filter_connections ~ignore:c ~since:t.Transaction.start_count ~f:judge_and_sentence in
 				if Hashtbl.length guilty_cons = 0 then debug "Found no culprit for conflict in %s: must be self or not in history." con;
 				false
 			)
-- 
2.1.4