diff options
Diffstat (limited to 'system/xen/xsa/xsa206-4.8-0014-oxenstored-don-t-wake-to-issue-no-conflict-credit.patch')
-rw-r--r-- | system/xen/xsa/xsa206-4.8-0014-oxenstored-don-t-wake-to-issue-no-conflict-credit.patch | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/system/xen/xsa/xsa206-4.8-0014-oxenstored-don-t-wake-to-issue-no-conflict-credit.patch b/system/xen/xsa/xsa206-4.8-0014-oxenstored-don-t-wake-to-issue-no-conflict-credit.patch new file mode 100644 index 0000000000..8aae281406 --- /dev/null +++ b/system/xen/xsa/xsa206-4.8-0014-oxenstored-don-t-wake-to-issue-no-conflict-credit.patch @@ -0,0 +1,141 @@ +From 374c6a67e3d139a04ecde127a63ce70d24ed7b45 Mon Sep 17 00:00:00 2001 +From: Thomas Sanders <thomas.sanders@citrix.com> +Date: Fri, 24 Mar 2017 19:55:03 +0000 +Subject: [PATCH 14/15] oxenstored: don't wake to issue no conflict-credit + +In the main loop, when choosing the timeout for the select function +call, we were setting it so as to wake up to issue conflict-credit to +any domains that could accept it. When xenstore is idle, this would +mean waking up every 50ms (by default) to do no work. With this +commit, we check whether any domain is below its cap, and if not then +we set the timeout for longer (the same timeout as before the +conflict-protection feature was added). + +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/domains.ml | 51 ++++++++++++++++++++++++++++++-------- + tools/ocaml/xenstored/xenstored.ml | 5 +++- + 2 files changed, 44 insertions(+), 12 deletions(-) + +diff --git a/tools/ocaml/xenstored/domains.ml b/tools/ocaml/xenstored/domains.ml +index 99f68c7..61d1e2e 100644 +--- a/tools/ocaml/xenstored/domains.ml ++++ b/tools/ocaml/xenstored/domains.ml +@@ -35,8 +35,9 @@ type domains = { + on_first_conflict_pause: unit -> unit; + + (* If config is set to use individual instead of aggregate conflict-rate-limiting, +- we use this instead of the queues. *) +- mutable n_paused: int; ++ we use these counts instead of the queues. The second one includes the first. *) ++ mutable n_paused: int; (* Number of domains with zero or negative credit *) ++ mutable n_penalised: int; (* Number of domains with less than maximum credit *) + } + + let init eventchn on_first_conflict_pause = { +@@ -46,6 +47,7 @@ let init eventchn on_first_conflict_pause = { + doms_with_conflict_penalty = Queue.create (); + on_first_conflict_pause = on_first_conflict_pause; + n_paused = 0; ++ n_penalised = 0; + } + let del doms id = Hashtbl.remove doms.table id + let exist doms id = Hashtbl.mem doms.table id +@@ -53,6 +55,23 @@ let find doms id = Hashtbl.find doms.table id + let number doms = Hashtbl.length doms.table + let iter doms fct = Hashtbl.iter (fun _ b -> fct b) doms.table + ++let rec is_empty_queue q = ++ Queue.is_empty q || ++ if !(Queue.peek q) = None ++ then ( ++ ignore (Queue.pop q); ++ is_empty_queue q ++ ) else false ++ ++let all_at_max_credit doms = ++ if !Define.conflict_rate_limit_is_aggregate ++ then ++ (* Check both becuase if burst limit is 1.0 then a domain can go straight ++ * from max-credit to paused without getting into the penalty queue. *) ++ is_empty_queue doms.doms_with_conflict_penalty ++ && is_empty_queue doms.doms_conflict_paused ++ else doms.n_penalised = 0 ++ + (* Functions to handle queues of domains given that the domain might be deleted while in a queue. *) + let push dom queue = + Queue.push (ref (Some dom)) queue +@@ -130,13 +149,16 @@ let decr_conflict_credit doms dom = + let before = dom.Domain.conflict_credit in + let after = max (-1.0) (before -. 1.0) in + dom.Domain.conflict_credit <- after; ++ let newly_penalised = ++ before >= !Define.conflict_burst_limit ++ && after < !Define.conflict_burst_limit in ++ let newly_paused = before > 0.0 && after <= 0.0 in + if !Define.conflict_rate_limit_is_aggregate then ( +- if before >= !Define.conflict_burst_limit +- && after < !Define.conflict_burst_limit ++ if newly_penalised + && after > 0.0 + then ( + push dom doms.doms_with_conflict_penalty +- ) else if before > 0.0 && after <= 0.0 ++ ) else if newly_paused + then ( + let first_pause = Queue.is_empty doms.doms_conflict_paused in + push dom doms.doms_conflict_paused; +@@ -144,9 +166,12 @@ let decr_conflict_credit doms dom = + ) else ( + (* The queues are correct already: no further action needed. *) + ) +- ) else if before > 0.0 && after <= 0.0 then ( +- doms.n_paused <- doms.n_paused + 1; +- if doms.n_paused = 1 then doms.on_first_conflict_pause () ++ ) else ( ++ if newly_penalised then doms.n_penalised <- doms.n_penalised + 1; ++ if newly_paused then ( ++ doms.n_paused <- doms.n_paused + 1; ++ if doms.n_paused = 1 then doms.on_first_conflict_pause () ++ ) + ) + + (* Give one point of credit to one domain, and update the queues appropriately. *) +@@ -175,9 +200,13 @@ let incr_conflict_credit doms = + let before = dom.Domain.conflict_credit in + let after = min (before +. 1.0) !Define.conflict_burst_limit in + dom.Domain.conflict_credit <- after; ++ + if before <= 0.0 && after > 0.0 +- then doms.n_paused <- doms.n_paused - 1 ++ then doms.n_paused <- doms.n_paused - 1; ++ ++ if before < !Define.conflict_burst_limit ++ && after >= !Define.conflict_burst_limit ++ then doms.n_penalised <- doms.n_penalised - 1 + in +- (* Scope for optimisation (probably tiny): avoid iteration if all domains are at max credit *) +- iter doms inc ++ if doms.n_penalised > 0 then iter doms inc + ) +diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml +index d5c50fd..06387a8 100644 +--- a/tools/ocaml/xenstored/xenstored.ml ++++ b/tools/ocaml/xenstored/xenstored.ml +@@ -437,7 +437,10 @@ let _ = + peaceful_mw; + let start_time = Unix.gettimeofday () in + let timeout = +- let until_next_activity = min (max 0. (!next_frequent_ops -. start_time)) period_ops_interval in ++ let until_next_activity = ++ if Domains.all_at_max_credit domains ++ then period_ops_interval ++ else min (max 0. (!next_frequent_ops -. start_time)) period_ops_interval in + if peaceful_mw <> [] then 0. else until_next_activity + in + let inset, outset = Connections.select ~only_if:is_peaceful cons in +-- +2.1.4 + |