[v1,VZ] beancounter: /sys/fs/cgroup/beancounter/{CT}/beancounter.numproc.failcnt output fixed

Submitted by Valeriy Vdovin on Feb. 27, 2020, 12:53 p.m.

Details

Message ID 1582808020-478688-1-git-send-email-valeriy.vdovin@virtuozzo.com
State New
Series "beancounter: /sys/fs/cgroup/beancounter/{CT}/beancounter.numproc.failcnt output fixed"
Headers show

Commit Message

Valeriy Vdovin Feb. 27, 2020, 12:53 p.m.
https://jira.sw.ru/browse/PSBM-95266
Added code that updates beancounter params from pids cgroup before
writing them to userspace.
Added helper function to collect precharge value from all cpus to
take it into account at 'held' calculation for corresponding
beancounted resource.

Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
---
 include/bc/beancounter.h | 30 +++++++++++++++++++++++++++++-
 kernel/bc/beancounter.c  | 35 +++++++++++++++++++++++++++++++----
 kernel/bc/proc.c         |  9 ++++-----
 3 files changed, 64 insertions(+), 10 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/bc/beancounter.h b/include/bc/beancounter.h
index a06d9b6..687de31 100644
--- a/include/bc/beancounter.h
+++ b/include/bc/beancounter.h
@@ -483,12 +483,40 @@  static inline void uncharge_beancounter_fast(struct user_beancounter *ub,
 	local_irq_restore(flags);
 }
 
+/*
+ * For a particular beancounter param return real 'held' value with
+ * respect to precharge.
+ */
+static inline unsigned long get_beancounter_held_real(struct ubparm *ubparm,
+		int precharge)
+{
+	unsigned long val = ubparm->held;
+
+	/*
+	 * We want to catch cases where precharge might be greater
+	 * than held.
+	 */
+	WARN_ON_ONCE(val < precharge);
+
+	return (val > precharge) ? (val - precharge) : 0;
+}
+
+
 unsigned long __get_beancounter_usage_percpu(struct user_beancounter *ub,
 		int resource);
 
 int precharge_beancounter(struct user_beancounter *ub,
 		int resource, unsigned long val);
-void ub_precharge_snapshot(struct user_beancounter *ub, int *precharge);
+
+/*
+ * Collect precharge for a single resource from all cpus
+ */
+int ub_precharge_snapshot_one(struct user_beancounter *ub, int resource);
+
+/*
+ * Collect precharge for each beancounter resource from all cpus
+ */
+void ub_precharge_snapshot_all(struct user_beancounter *ub, int *precharge);
 
 #define UB_IOPRIO_MIN 0
 #define UB_IOPRIO_MAX 8
diff --git a/kernel/bc/beancounter.c b/kernel/bc/beancounter.c
index fb63023..0bec513 100644
--- a/kernel/bc/beancounter.c
+++ b/kernel/bc/beancounter.c
@@ -292,7 +292,17 @@  static void __init init_beancounter_precharges_early(struct user_beancounter *ub
 	}
 }
 
-void ub_precharge_snapshot(struct user_beancounter *ub, int *precharge)
+int ub_precharge_snapshot_one(struct user_beancounter *ub, int resource)
+{
+	int cpu, result = 0;
+	for_each_possible_cpu(cpu) {
+		struct ub_percpu_struct *pcpu = ub_percpu(ub, cpu);
+		result += pcpu->precharge[resource];
+	}
+	return result;
+}
+
+void ub_precharge_snapshot_all(struct user_beancounter *ub, int *precharge)
 {
 	int cpu, resource;
 
@@ -308,7 +318,7 @@  static void uncharge_beancounter_precharge(struct user_beancounter *ub)
 {
 	int resource, precharge[UB_RESOURCES];
 
-	ub_precharge_snapshot(ub, precharge);
+	ub_precharge_snapshot_all(ub, precharge);
 	for ( resource = 0 ; resource < UB_RESOURCES ; resource++ )
 		ub->ub_parms[resource].held -= precharge[resource];
 }
@@ -723,19 +733,36 @@  static ssize_t ub_cgroup_resource_read(struct cgroup *cg, struct cftype *cft,
 {
 	struct user_beancounter *ub = cgroup_ub(cg);
 	struct ubparm *ubparm;
-	unsigned long val;
+	unsigned long val, precharge;
 	int res, attr;
 	int len;
 	char str[32];
 
 	res = UB_CGROUP_RES(cft->private);
+
+	switch (res) {
+	case UB_NUMPROC:
+		ub_sync_pids(ub);
+		break;
+	case UB_KMEMSIZE:
+	case UB_DCACHESIZE:
+	case UB_PHYSPAGES:
+	case UB_SWAPPAGES:
+	case UB_OOMGUARPAGES:
+		ub_sync_memcg(ub);
+		break;
+	default:
+		break;
+	}
+
 	attr = UB_CGROUP_ATTR(cft->private);
 
 	ubparm = &ub->ub_parms[res];
 
 	switch (attr) {
 	case UB_CGROUP_ATTR_HELD:
-		val = ubparm->held;
+		precharge = ub_precharge_snapshot_one(ub, res);
+		val = get_beancounter_held_real(ubparm, precharge);
 		break;
 	case UB_CGROUP_ATTR_MAXHELD:
 		val = ubparm->maxheld;
diff --git a/kernel/bc/proc.c b/kernel/bc/proc.c
index efcfdbc..a65c2ae 100644
--- a/kernel/bc/proc.c
+++ b/kernel/bc/proc.c
@@ -52,8 +52,7 @@  static void ub_show_res(struct seq_file *f, struct user_beancounter *ub,
 	unsigned long held;
 
 	p = &ub->ub_parms[r];
-	held = p->held;
-	held = (held > precharge) ? (held - precharge) : 0;
+	held = get_beancounter_held_real(p, precharge);
 
 	seq_printf(f, res_fmt,
 			show_uid && r == 0 ? ub->ub_name : "",
@@ -73,7 +72,7 @@  static void __show_resources(struct seq_file *f, struct user_beancounter *ub,
 
 	ub_sync_memcg(ub);
 	ub_sync_pids(ub);
-	ub_precharge_snapshot(ub, precharge);
+	ub_precharge_snapshot_all(ub, precharge);
 
 	for (i = 0; i < UB_RESOURCES_COMPAT; i++)
 		if (strcmp(ub_rnames[i], "dummy") != 0)
@@ -104,7 +103,7 @@  static int bc_precharge_show(struct seq_file *f, void *v)
 			"resource", "real_held", "precharge", "max_precharge");
 
 	ub = seq_beancounter(f);
-	ub_precharge_snapshot(ub, precharge);
+	ub_precharge_snapshot_all(ub, precharge);
 	for ( i = 0 ; i < UB_RESOURCES ; i++ ) {
 		if (!strcmp(ub_rnames[i], "dummy"))
 			continue;
@@ -183,7 +182,7 @@  static int ub_show(struct seq_file *f, void *v)
 
 	ub_sync_memcg(ub);
 	ub_sync_pids(ub);
-	ub_precharge_snapshot(ub, precharge);
+	ub_precharge_snapshot_all(ub, precharge);
 
 	for (i = 0; i < UB_RESOURCES_COMPAT; i++)
 		ub_show_res(f, ub, i, precharge[i], 1);