hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
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
....@@ -294,44 +294,48 @@
294294 * Functions for cgroup basic resource statistics implemented on top of
295295 * rstat.
296296 */
297
-static void cgroup_base_stat_accumulate(struct cgroup_base_stat *dst_bstat,
298
- struct cgroup_base_stat *src_bstat)
297
+static void cgroup_base_stat_add(struct cgroup_base_stat *dst_bstat,
298
+ struct cgroup_base_stat *src_bstat)
299299 {
300300 dst_bstat->cputime.utime += src_bstat->cputime.utime;
301301 dst_bstat->cputime.stime += src_bstat->cputime.stime;
302302 dst_bstat->cputime.sum_exec_runtime += src_bstat->cputime.sum_exec_runtime;
303303 }
304304
305
+static void cgroup_base_stat_sub(struct cgroup_base_stat *dst_bstat,
306
+ struct cgroup_base_stat *src_bstat)
307
+{
308
+ dst_bstat->cputime.utime -= src_bstat->cputime.utime;
309
+ dst_bstat->cputime.stime -= src_bstat->cputime.stime;
310
+ dst_bstat->cputime.sum_exec_runtime -= src_bstat->cputime.sum_exec_runtime;
311
+}
312
+
305313 static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu)
306314 {
307315 struct cgroup *parent = cgroup_parent(cgrp);
308316 struct cgroup_rstat_cpu *rstatc = cgroup_rstat_cpu(cgrp, cpu);
309
- struct task_cputime *last_cputime = &rstatc->last_bstat.cputime;
310
- struct task_cputime cputime;
311
- struct cgroup_base_stat delta;
317
+ struct cgroup_base_stat cur, delta;
312318 unsigned seq;
313319
314320 /* fetch the current per-cpu values */
315321 do {
316322 seq = __u64_stats_fetch_begin(&rstatc->bsync);
317
- cputime = rstatc->bstat.cputime;
323
+ cur.cputime = rstatc->bstat.cputime;
318324 } while (__u64_stats_fetch_retry(&rstatc->bsync, seq));
319325
320
- /* calculate the delta to propgate */
321
- delta.cputime.utime = cputime.utime - last_cputime->utime;
322
- delta.cputime.stime = cputime.stime - last_cputime->stime;
323
- delta.cputime.sum_exec_runtime = cputime.sum_exec_runtime -
324
- last_cputime->sum_exec_runtime;
325
- *last_cputime = cputime;
326
+ /* propagate percpu delta to global */
327
+ delta = cur;
328
+ cgroup_base_stat_sub(&delta, &rstatc->last_bstat);
329
+ cgroup_base_stat_add(&cgrp->bstat, &delta);
330
+ cgroup_base_stat_add(&rstatc->last_bstat, &delta);
326331
327
- /* transfer the pending stat into delta */
328
- cgroup_base_stat_accumulate(&delta, &cgrp->pending_bstat);
329
- memset(&cgrp->pending_bstat, 0, sizeof(cgrp->pending_bstat));
330
-
331
- /* propagate delta into the global stat and the parent's pending */
332
- cgroup_base_stat_accumulate(&cgrp->bstat, &delta);
333
- if (parent)
334
- cgroup_base_stat_accumulate(&parent->pending_bstat, &delta);
332
+ /* propagate global delta to parent */
333
+ if (parent) {
334
+ delta = cgrp->bstat;
335
+ cgroup_base_stat_sub(&delta, &cgrp->last_bstat);
336
+ cgroup_base_stat_add(&parent->bstat, &delta);
337
+ cgroup_base_stat_add(&cgrp->last_bstat, &delta);
338
+ }
335339 }
336340
337341 static struct cgroup_rstat_cpu *
....@@ -385,18 +389,60 @@
385389 cgroup_base_stat_cputime_account_end(cgrp, rstatc);
386390 }
387391
392
+/*
393
+ * compute the cputime for the root cgroup by getting the per cpu data
394
+ * at a global level, then categorizing the fields in a manner consistent
395
+ * with how it is done by __cgroup_account_cputime_field for each bit of
396
+ * cpu time attributed to a cgroup.
397
+ */
398
+static void root_cgroup_cputime(struct task_cputime *cputime)
399
+{
400
+ int i;
401
+
402
+ cputime->stime = 0;
403
+ cputime->utime = 0;
404
+ cputime->sum_exec_runtime = 0;
405
+ for_each_possible_cpu(i) {
406
+ struct kernel_cpustat kcpustat;
407
+ u64 *cpustat = kcpustat.cpustat;
408
+ u64 user = 0;
409
+ u64 sys = 0;
410
+
411
+ kcpustat_cpu_fetch(&kcpustat, i);
412
+
413
+ user += cpustat[CPUTIME_USER];
414
+ user += cpustat[CPUTIME_NICE];
415
+ cputime->utime += user;
416
+
417
+ sys += cpustat[CPUTIME_SYSTEM];
418
+ sys += cpustat[CPUTIME_IRQ];
419
+ sys += cpustat[CPUTIME_SOFTIRQ];
420
+ cputime->stime += sys;
421
+
422
+ cputime->sum_exec_runtime += user;
423
+ cputime->sum_exec_runtime += sys;
424
+ cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL];
425
+ }
426
+}
427
+
388428 void cgroup_base_stat_cputime_show(struct seq_file *seq)
389429 {
390430 struct cgroup *cgrp = seq_css(seq)->cgroup;
391431 u64 usage, utime, stime;
432
+ struct task_cputime cputime;
392433
393
- if (!cgroup_parent(cgrp))
394
- return;
395
-
396
- cgroup_rstat_flush_hold(cgrp);
397
- usage = cgrp->bstat.cputime.sum_exec_runtime;
398
- cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime, &utime, &stime);
399
- cgroup_rstat_flush_release();
434
+ if (cgroup_parent(cgrp)) {
435
+ cgroup_rstat_flush_hold(cgrp);
436
+ usage = cgrp->bstat.cputime.sum_exec_runtime;
437
+ cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime,
438
+ &utime, &stime);
439
+ cgroup_rstat_flush_release();
440
+ } else {
441
+ root_cgroup_cputime(&cputime);
442
+ usage = cputime.sum_exec_runtime;
443
+ utime = cputime.utime;
444
+ stime = cputime.stime;
445
+ }
400446
401447 do_div(usage, NSEC_PER_USEC);
402448 do_div(utime, NSEC_PER_USEC);