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
....@@ -149,9 +149,8 @@
149149 raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock,
150150 cpu);
151151 struct cgroup *pos = NULL;
152
- unsigned long flags;
153152
154
- raw_spin_lock_irqsave(cpu_lock, flags);
153
+ raw_spin_lock(cpu_lock);
155154 while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu))) {
156155 struct cgroup_subsys_state *css;
157156
....@@ -163,7 +162,7 @@
163162 css->ss->css_rstat_flush(css, cpu);
164163 rcu_read_unlock();
165164 }
166
- raw_spin_unlock_irqrestore(cpu_lock, flags);
165
+ raw_spin_unlock(cpu_lock);
167166
168167 /* if @may_sleep, play nice and yield if necessary */
169168 if (may_sleep && (need_resched() ||
....@@ -294,44 +293,48 @@
294293 * Functions for cgroup basic resource statistics implemented on top of
295294 * rstat.
296295 */
297
-static void cgroup_base_stat_accumulate(struct cgroup_base_stat *dst_bstat,
298
- 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)
299298 {
300299 dst_bstat->cputime.utime += src_bstat->cputime.utime;
301300 dst_bstat->cputime.stime += src_bstat->cputime.stime;
302301 dst_bstat->cputime.sum_exec_runtime += src_bstat->cputime.sum_exec_runtime;
303302 }
304303
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
+
305312 static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu)
306313 {
307314 struct cgroup *parent = cgroup_parent(cgrp);
308315 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;
316
+ struct cgroup_base_stat cur, delta;
312317 unsigned seq;
313318
314319 /* fetch the current per-cpu values */
315320 do {
316321 seq = __u64_stats_fetch_begin(&rstatc->bsync);
317
- cputime = rstatc->bstat.cputime;
322
+ cur.cputime = rstatc->bstat.cputime;
318323 } while (__u64_stats_fetch_retry(&rstatc->bsync, seq));
319324
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;
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);
326330
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);
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
+ }
335338 }
336339
337340 static struct cgroup_rstat_cpu *
....@@ -385,18 +388,60 @@
385388 cgroup_base_stat_cputime_account_end(cgrp, rstatc);
386389 }
387390
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
+
388427 void cgroup_base_stat_cputime_show(struct seq_file *seq)
389428 {
390429 struct cgroup *cgrp = seq_css(seq)->cgroup;
391430 u64 usage, utime, stime;
431
+ struct task_cputime cputime;
392432
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();
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
+ }
400445
401446 do_div(usage, NSEC_PER_USEC);
402447 do_div(utime, NSEC_PER_USEC);