hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/kernel/cgroup/rstat.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 #include "cgroup-internal.h"
23
34 #include <linux/sched/cputime.h>
....@@ -63,7 +64,6 @@
6364
6465 raw_spin_unlock_irqrestore(cpu_lock, flags);
6566 }
66
-EXPORT_SYMBOL_GPL(cgroup_rstat_updated);
6767
6868 /**
6969 * cgroup_rstat_cpu_pop_updated - iterate and dismantle rstat_cpu updated tree
....@@ -293,44 +293,48 @@
293293 * Functions for cgroup basic resource statistics implemented on top of
294294 * rstat.
295295 */
296
-static void cgroup_base_stat_accumulate(struct cgroup_base_stat *dst_bstat,
297
- struct cgroup_base_stat *src_bstat)
296
+static void cgroup_base_stat_add(struct cgroup_base_stat *dst_bstat,
297
+ struct cgroup_base_stat *src_bstat)
298298 {
299299 dst_bstat->cputime.utime += src_bstat->cputime.utime;
300300 dst_bstat->cputime.stime += src_bstat->cputime.stime;
301301 dst_bstat->cputime.sum_exec_runtime += src_bstat->cputime.sum_exec_runtime;
302302 }
303303
304
+static void cgroup_base_stat_sub(struct cgroup_base_stat *dst_bstat,
305
+ struct cgroup_base_stat *src_bstat)
306
+{
307
+ dst_bstat->cputime.utime -= src_bstat->cputime.utime;
308
+ dst_bstat->cputime.stime -= src_bstat->cputime.stime;
309
+ dst_bstat->cputime.sum_exec_runtime -= src_bstat->cputime.sum_exec_runtime;
310
+}
311
+
304312 static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu)
305313 {
306314 struct cgroup *parent = cgroup_parent(cgrp);
307315 struct cgroup_rstat_cpu *rstatc = cgroup_rstat_cpu(cgrp, cpu);
308
- struct task_cputime *last_cputime = &rstatc->last_bstat.cputime;
309
- struct task_cputime cputime;
310
- struct cgroup_base_stat delta;
316
+ struct cgroup_base_stat cur, delta;
311317 unsigned seq;
312318
313319 /* fetch the current per-cpu values */
314320 do {
315321 seq = __u64_stats_fetch_begin(&rstatc->bsync);
316
- cputime = rstatc->bstat.cputime;
322
+ cur.cputime = rstatc->bstat.cputime;
317323 } while (__u64_stats_fetch_retry(&rstatc->bsync, seq));
318324
319
- /* calculate the delta to propgate */
320
- delta.cputime.utime = cputime.utime - last_cputime->utime;
321
- delta.cputime.stime = cputime.stime - last_cputime->stime;
322
- delta.cputime.sum_exec_runtime = cputime.sum_exec_runtime -
323
- last_cputime->sum_exec_runtime;
324
- *last_cputime = cputime;
325
+ /* propagate percpu delta to global */
326
+ delta = cur;
327
+ cgroup_base_stat_sub(&delta, &rstatc->last_bstat);
328
+ cgroup_base_stat_add(&cgrp->bstat, &delta);
329
+ cgroup_base_stat_add(&rstatc->last_bstat, &delta);
325330
326
- /* transfer the pending stat into delta */
327
- cgroup_base_stat_accumulate(&delta, &cgrp->pending_bstat);
328
- memset(&cgrp->pending_bstat, 0, sizeof(cgrp->pending_bstat));
329
-
330
- /* propagate delta into the global stat and the parent's pending */
331
- cgroup_base_stat_accumulate(&cgrp->bstat, &delta);
332
- if (parent)
333
- cgroup_base_stat_accumulate(&parent->pending_bstat, &delta);
331
+ /* propagate global delta to parent */
332
+ if (parent) {
333
+ delta = cgrp->bstat;
334
+ cgroup_base_stat_sub(&delta, &cgrp->last_bstat);
335
+ cgroup_base_stat_add(&parent->bstat, &delta);
336
+ cgroup_base_stat_add(&cgrp->last_bstat, &delta);
337
+ }
334338 }
335339
336340 static struct cgroup_rstat_cpu *
....@@ -384,18 +388,60 @@
384388 cgroup_base_stat_cputime_account_end(cgrp, rstatc);
385389 }
386390
391
+/*
392
+ * compute the cputime for the root cgroup by getting the per cpu data
393
+ * at a global level, then categorizing the fields in a manner consistent
394
+ * with how it is done by __cgroup_account_cputime_field for each bit of
395
+ * cpu time attributed to a cgroup.
396
+ */
397
+static void root_cgroup_cputime(struct task_cputime *cputime)
398
+{
399
+ int i;
400
+
401
+ cputime->stime = 0;
402
+ cputime->utime = 0;
403
+ cputime->sum_exec_runtime = 0;
404
+ for_each_possible_cpu(i) {
405
+ struct kernel_cpustat kcpustat;
406
+ u64 *cpustat = kcpustat.cpustat;
407
+ u64 user = 0;
408
+ u64 sys = 0;
409
+
410
+ kcpustat_cpu_fetch(&kcpustat, i);
411
+
412
+ user += cpustat[CPUTIME_USER];
413
+ user += cpustat[CPUTIME_NICE];
414
+ cputime->utime += user;
415
+
416
+ sys += cpustat[CPUTIME_SYSTEM];
417
+ sys += cpustat[CPUTIME_IRQ];
418
+ sys += cpustat[CPUTIME_SOFTIRQ];
419
+ cputime->stime += sys;
420
+
421
+ cputime->sum_exec_runtime += user;
422
+ cputime->sum_exec_runtime += sys;
423
+ cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL];
424
+ }
425
+}
426
+
387427 void cgroup_base_stat_cputime_show(struct seq_file *seq)
388428 {
389429 struct cgroup *cgrp = seq_css(seq)->cgroup;
390430 u64 usage, utime, stime;
431
+ struct task_cputime cputime;
391432
392
- if (!cgroup_parent(cgrp))
393
- return;
394
-
395
- cgroup_rstat_flush_hold(cgrp);
396
- usage = cgrp->bstat.cputime.sum_exec_runtime;
397
- cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime, &utime, &stime);
398
- cgroup_rstat_flush_release();
433
+ if (cgroup_parent(cgrp)) {
434
+ cgroup_rstat_flush_hold(cgrp);
435
+ usage = cgrp->bstat.cputime.sum_exec_runtime;
436
+ cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime,
437
+ &utime, &stime);
438
+ cgroup_rstat_flush_release();
439
+ } else {
440
+ root_cgroup_cputime(&cputime);
441
+ usage = cputime.sum_exec_runtime;
442
+ utime = cputime.utime;
443
+ stime = cputime.stime;
444
+ }
399445
400446 do_div(usage, NSEC_PER_USEC);
401447 do_div(utime, NSEC_PER_USEC);