[rh7] ub: honor precharge when close to barrier/limit on charge

Submitted by Konstantin Khorenko on June 22, 2018, 2:42 p.m.

Details

Message ID 20180622144205.3781-1-khorenko@virtuozzo.com
State New
Series "ub: honor precharge when close to barrier/limit on charge"
Headers show

Commit Message

Konstantin Khorenko June 22, 2018, 2:42 p.m.
charge_beancounter() does not check precharged value, it just prohibits
.held to grow more than limit/barrier which is wrong.

Solution: if fast path fails (i.e. .held is greater than limit/barrier)
than carefully count all precharges and consider them into accounting.

That way we allow .held to grow above limit/barrier due to precharge.

Fixes: d821108a8a1a ("ubc: initial patch")
https://jira.sw.ru/browse/PSBM-86044

Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 kernel/bc/beancounter.c | 39 ++++++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/kernel/bc/beancounter.c b/kernel/bc/beancounter.c
index d5de31008a5e..039b011e53af 100644
--- a/kernel/bc/beancounter.c
+++ b/kernel/bc/beancounter.c
@@ -271,6 +271,17 @@  static void __init init_beancounter_precharges_early(struct user_beancounter *ub
 	}
 }
 
+static int get_ub_precharge(struct user_beancounter *ub, int resource)
+{
+	int cpu, precharge = 0;
+
+	for_each_possible_cpu(cpu) {
+		struct ub_percpu_struct *pcpu = ub_percpu(ub, cpu);
+		precharge += pcpu->precharge[resource];
+	}
+	return precharge;
+}
+
 void ub_precharge_snapshot(struct user_beancounter *ub, int *precharge)
 {
 	int cpu, resource;
@@ -841,21 +852,35 @@  EXPORT_SYMBOL(ub_subsys);
 int __charge_beancounter_locked(struct user_beancounter *ub,
 		int resource, unsigned long val, enum ub_severity strict)
 {
+	int precharge = 0;
+	unsigned long held, limit;
 	/*
 	 * ub_value <= UB_MAXVALUE, value <= UB_MAXVALUE, and only one addition
-	 * at the moment is possible so an overflow is impossible.  
+	 * at the moment is possible so an overflow is impossible.
 	 */
 	ub->ub_parms[resource].held += val;
+	held = ub->ub_parms[resource].held;
 
 	switch (strict & ~UB_SEV_FLAGS) {
 		case UB_HARD:
-			if (ub->ub_parms[resource].held >
-					ub->ub_parms[resource].barrier)
-				break;
+			if (held > ub->ub_parms[resource].barrier) {
+				/* close to barrier - check precharge */
+				limit = ub->ub_parms[resource].barrier;
+				precharge = get_ub_precharge(ub, resource);
+
+				if (held - precharge > limit)
+					break;
+			}
 		case UB_SOFT:
-			if (ub->ub_parms[resource].held >
-					ub->ub_parms[resource].limit)
-				break;
+			if (held > ub->ub_parms[resource].limit) {
+				/* close to limit - check precharge */
+				limit = ub->ub_parms[resource].limit;
+				precharge = precharge ? :
+					    get_ub_precharge(ub, resource);
+
+				if (held - precharge > limit)
+					break;
+			}
 		case UB_FORCE:
 			ub_adjust_maxheld(ub, resource);
 			return 0;