| @@ -1,6 +1,7 @@ |
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | #include "cgroup-internal.h" | 2 | #include "cgroup-internal.h" |
| 3 | | 3 | |
| | 4 | #include <linux/cpumask.h> |
| 4 | #include <linux/sched/cputime.h> | 5 | #include <linux/sched/cputime.h> |
| 5 | | 6 | |
| 6 | #include <linux/bpf.h> | 7 | #include <linux/bpf.h> |
| @@ -53,7 +54,7 @@ static inline struct llist_head *ss_lhead_cpu(struct cgroup_subsys *ss, int cpu) · 46 unmodified lines |
| 53 | } | 54 | } |
| 54 | | 55 | |
| 55 | /** | 56 | /** |
| 56 | * css_rstat_updated - keep track of updated rstat_cpu | 57 | * __css_rstat_updated - keep track of updated rstat_cpu |
| 57 | * @css: target cgroup subsystem state | 58 | * @css: target cgroup subsystem state |
| 58 | * @cpu: cpu on which rstat_cpu was updated | 59 | * @cpu: cpu on which rstat_cpu was updated |
| 59 | * | 60 | * |
| @@ -63,20 +64,17 @@ static inline struct llist_head *ss_lhead_cpu(struct cgroup_subsys *ss, int cpu) · 3 unmodified lines |
| 63 | * | 64 | * |
| 64 | * NOTE: if the user needs the guarantee that the updater either add itself in | 65 | * NOTE: if the user needs the guarantee that the updater either add itself in |
| 65 | * the lockless list or the concurrent flusher flushes its updated stats, a | 66 | * the lockless list or the concurrent flusher flushes its updated stats, a |
| 66 | * memory barrier is needed before the call to css_rstat_updated() i.e. a | 67 | * memory barrier is needed before the call to __css_rstat_updated() i.e. a |
| 67 | * barrier after updating the per-cpu stats and before calling | 68 | * barrier after updating the per-cpu stats and before calling |
| 68 | * css_rstat_updated(). | 69 | * __css_rstat_updated(). |
| 69 | */ | 70 | */ |
| 70 | __bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu) | 71 | void __css_rstat_updated(struct cgroup_subsys_state *css, int cpu) |
| 71 | { | 72 | { |
| 72 | struct llist_head *lhead; | 73 | struct llist_head *lhead; |
| 73 | struct css_rstat_cpu *rstatc; | 74 | struct css_rstat_cpu *rstatc; |
| 74 | struct llist_node *self; | 75 | struct llist_node *self; |
| 75 | | 76 | |
| 76 | /* | 77 | /* Prevent access to uninitialized rstat pointers. */ |
| 77 | * Since bpf programs can call this function, prevent access to | | |
| 78 | * uninitialized rstat pointers. | | |
| 79 | */ | | |
| 80 | if (!css_uses_rstat(css)) | 78 | if (!css_uses_rstat(css)) |
| 81 | return; | 79 | return; |
| 82 | | 80 | |
| @@ -125,6 +123,18 @@ __bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu) · 42 unmodified lines |
| 125 | llist_add(&rstatc->lnode, lhead); | 123 | llist_add(&rstatc->lnode, lhead); |
| 126 | } | 124 | } |
| 127 | | 125 | |
| | 126 | /* |
| | 127 | * BPF-facing wrapper for __css_rstat_updated(). Validate the caller-provided |
| | 128 | * CPU before passing it to the internal rstat updater. |
| | 129 | */ |
| | 130 | __bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu) |
| | 131 | { |
| | 132 | if (unlikely(cpu < 0 || cpu >= nr_cpu_ids || !cpu_possible(cpu))) |
| | 133 | return; |
| | 134 | |
| | 135 | __css_rstat_updated(css, cpu); |
| | 136 | } |
| | 137 | |
| 128 | static void __css_process_update_tree(struct cgroup_subsys_state *css, int cpu) | 138 | static void __css_process_update_tree(struct cgroup_subsys_state *css, int cpu) |
| 129 | { | 139 | { |
| 130 | /* put @css and all ancestors on the corresponding updated lists */ | 140 | /* put @css and all ancestors on the corresponding updated lists */ |
| @@ -170,7 +180,7 @@ static void css_process_update_tree(struct cgroup_subsys *ss, int cpu) · 39 unmodified lines |
| 170 | * flusher flush the stats updated by the updater who have | 180 | * flusher flush the stats updated by the updater who have |
| 171 | * observed that they are already on the list. The | 181 | * observed that they are already on the list. The |
| 172 | * corresponding barrier pair for this one should be before | 182 | * corresponding barrier pair for this one should be before |
| 173 | * css_rstat_updated() by the user. | 183 | * __css_rstat_updated() by the user. |
| 174 | * | 184 | * |
| 175 | * For now, there aren't any such user, so not adding the | 185 | * For now, there aren't any such user, so not adding the |
| 176 | * barrier here but if such a use-case arise, please add | 186 | * barrier here but if such a use-case arise, please add |
| @@ -614,7 +624,7 @@ static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp, · 437 unmodified lines |
| 614 | unsigned long flags) | 624 | unsigned long flags) |
| 615 | { | 625 | { |
| 616 | u64_stats_update_end_irqrestore(&rstatbc->bsync, flags); | 626 | u64_stats_update_end_irqrestore(&rstatbc->bsync, flags); |
| 617 | css_rstat_updated(&cgrp->self, smp_processor_id()); | 627 | __css_rstat_updated(&cgrp->self, smp_processor_id()); |
| 618 | put_cpu_ptr(rstatbc); | 628 | put_cpu_ptr(rstatbc); |
| 619 | } | 629 | } |
| 620 | | 630 | |