1#ifndef _LINUX_CGROUP_H
2#define _LINUX_CGROUP_H
3
4
5
6
7
8
9
10
11#include <linux/sched.h>
12#include <linux/cpumask.h>
13#include <linux/nodemask.h>
14#include <linux/rculist.h>
15#include <linux/cgroupstats.h>
16#include <linux/fs.h>
17#include <linux/seq_file.h>
18#include <linux/kernfs.h>
19#include <linux/jump_label.h>
20#include <linux/nsproxy.h>
21#include <linux/types.h>
22#include <linux/ns_common.h>
23#include <linux/nsproxy.h>
24#include <linux/user_namespace.h>
25
26#include <linux/cgroup-defs.h>
27
28#ifdef CONFIG_CGROUPS
29
30
31
32
33
34
35#define CGROUP_WEIGHT_MIN 1
36#define CGROUP_WEIGHT_DFL 100
37#define CGROUP_WEIGHT_MAX 10000
38
39
40struct css_task_iter {
41 struct cgroup_subsys *ss;
42
43 struct list_head *cset_pos;
44 struct list_head *cset_head;
45
46 struct list_head *task_pos;
47 struct list_head *tasks_head;
48 struct list_head *mg_tasks_head;
49
50 struct css_set *cur_cset;
51 struct task_struct *cur_task;
52 struct list_head iters_node;
53};
54
55extern struct cgroup_root cgrp_dfl_root;
56extern struct css_set init_css_set;
57
58#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
59#include <linux/cgroup_subsys.h>
60#undef SUBSYS
61
62#define SUBSYS(_x) \
63 extern struct static_key_true _x ## _cgrp_subsys_enabled_key; \
64 extern struct static_key_true _x ## _cgrp_subsys_on_dfl_key;
65#include <linux/cgroup_subsys.h>
66#undef SUBSYS
67
68
69
70
71
72#define cgroup_subsys_enabled(ss) \
73 static_branch_likely(&ss ## _enabled_key)
74
75
76
77
78
79#define cgroup_subsys_on_dfl(ss) \
80 static_branch_likely(&ss ## _on_dfl_key)
81
82bool css_has_online_children(struct cgroup_subsys_state *css);
83struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss);
84struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup,
85 struct cgroup_subsys *ss);
86struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
87 struct cgroup_subsys *ss);
88
89struct cgroup *cgroup_get_from_path(const char *path);
90
91int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
92int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
93
94int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
95int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
96int cgroup_rm_cftypes(struct cftype *cfts);
97void cgroup_file_notify(struct cgroup_file *cfile);
98
99char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
100int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry);
101int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
102 struct pid *pid, struct task_struct *tsk);
103
104void cgroup_fork(struct task_struct *p);
105extern int cgroup_can_fork(struct task_struct *p);
106extern void cgroup_cancel_fork(struct task_struct *p);
107extern void cgroup_post_fork(struct task_struct *p);
108void cgroup_exit(struct task_struct *p);
109void cgroup_free(struct task_struct *p);
110
111int cgroup_init_early(void);
112int cgroup_init(void);
113
114
115
116
117
118struct cgroup_subsys_state *css_next_child(struct cgroup_subsys_state *pos,
119 struct cgroup_subsys_state *parent);
120struct cgroup_subsys_state *css_next_descendant_pre(struct cgroup_subsys_state *pos,
121 struct cgroup_subsys_state *css);
122struct cgroup_subsys_state *css_rightmost_descendant(struct cgroup_subsys_state *pos);
123struct cgroup_subsys_state *css_next_descendant_post(struct cgroup_subsys_state *pos,
124 struct cgroup_subsys_state *css);
125
126struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset,
127 struct cgroup_subsys_state **dst_cssp);
128struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
129 struct cgroup_subsys_state **dst_cssp);
130
131void css_task_iter_start(struct cgroup_subsys_state *css,
132 struct css_task_iter *it);
133struct task_struct *css_task_iter_next(struct css_task_iter *it);
134void css_task_iter_end(struct css_task_iter *it);
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154#define css_for_each_child(pos, parent) \
155 for ((pos) = css_next_child(NULL, (parent)); (pos); \
156 (pos) = css_next_child((pos), (parent)))
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214#define css_for_each_descendant_pre(pos, css) \
215 for ((pos) = css_next_descendant_pre(NULL, (css)); (pos); \
216 (pos) = css_next_descendant_pre((pos), (css)))
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237#define css_for_each_descendant_post(pos, css) \
238 for ((pos) = css_next_descendant_post(NULL, (css)); (pos); \
239 (pos) = css_next_descendant_post((pos), (css)))
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259#define cgroup_taskset_for_each(task, dst_css, tset) \
260 for ((task) = cgroup_taskset_first((tset), &(dst_css)); \
261 (task); \
262 (task) = cgroup_taskset_next((tset), &(dst_css)))
263
264
265
266
267
268
269
270
271
272
273#define cgroup_taskset_for_each_leader(leader, dst_css, tset) \
274 for ((leader) = cgroup_taskset_first((tset), &(dst_css)); \
275 (leader); \
276 (leader) = cgroup_taskset_next((tset), &(dst_css))) \
277 if ((leader) != (leader)->group_leader) \
278 ; \
279 else
280
281
282
283
284
285
286
287
288
289
290
291static inline void css_get(struct cgroup_subsys_state *css)
292{
293 if (!(css->flags & CSS_NO_REF))
294 percpu_ref_get(&css->refcnt);
295}
296
297
298
299
300
301
302
303
304static inline void css_get_many(struct cgroup_subsys_state *css, unsigned int n)
305{
306 if (!(css->flags & CSS_NO_REF))
307 percpu_ref_get_many(&css->refcnt, n);
308}
309
310
311
312
313
314
315
316
317
318
319
320
321static inline bool css_tryget(struct cgroup_subsys_state *css)
322{
323 if (!(css->flags & CSS_NO_REF))
324 return percpu_ref_tryget(&css->refcnt);
325 return true;
326}
327
328
329
330
331
332
333
334
335
336
337
338static inline bool css_tryget_online(struct cgroup_subsys_state *css)
339{
340 if (!(css->flags & CSS_NO_REF))
341 return percpu_ref_tryget_live(&css->refcnt);
342 return true;
343}
344
345
346
347
348
349
350
351static inline void css_put(struct cgroup_subsys_state *css)
352{
353 if (!(css->flags & CSS_NO_REF))
354 percpu_ref_put(&css->refcnt);
355}
356
357
358
359
360
361
362
363
364static inline void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
365{
366 if (!(css->flags & CSS_NO_REF))
367 percpu_ref_put_many(&css->refcnt, n);
368}
369
370static inline void cgroup_put(struct cgroup *cgrp)
371{
372 css_put(&cgrp->self);
373}
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388#ifdef CONFIG_PROVE_RCU
389extern struct mutex cgroup_mutex;
390extern spinlock_t css_set_lock;
391#define task_css_set_check(task, __c) \
392 rcu_dereference_check((task)->cgroups, \
393 lockdep_is_held(&cgroup_mutex) || \
394 lockdep_is_held(&css_set_lock) || \
395 ((task)->flags & PF_EXITING) || (__c))
396#else
397#define task_css_set_check(task, __c) \
398 rcu_dereference((task)->cgroups)
399#endif
400
401
402
403
404
405
406
407
408
409
410#define task_css_check(task, subsys_id, __c) \
411 task_css_set_check((task), (__c))->subsys[(subsys_id)]
412
413
414
415
416
417
418
419static inline struct css_set *task_css_set(struct task_struct *task)
420{
421 return task_css_set_check(task, false);
422}
423
424
425
426
427
428
429
430
431static inline struct cgroup_subsys_state *task_css(struct task_struct *task,
432 int subsys_id)
433{
434 return task_css_check(task, subsys_id, false);
435}
436
437
438
439
440
441
442
443
444
445
446static inline struct cgroup_subsys_state *
447task_get_css(struct task_struct *task, int subsys_id)
448{
449 struct cgroup_subsys_state *css;
450
451 rcu_read_lock();
452 while (true) {
453 css = task_css(task, subsys_id);
454 if (likely(css_tryget_online(css)))
455 break;
456 cpu_relax();
457 }
458 rcu_read_unlock();
459 return css;
460}
461
462
463
464
465
466
467
468
469
470static inline bool task_css_is_root(struct task_struct *task, int subsys_id)
471{
472 return task_css_check(task, subsys_id, true) ==
473 init_css_set.subsys[subsys_id];
474}
475
476static inline struct cgroup *task_cgroup(struct task_struct *task,
477 int subsys_id)
478{
479 return task_css(task, subsys_id)->cgroup;
480}
481
482
483
484
485
486
487
488
489
490
491static inline bool cgroup_is_descendant(struct cgroup *cgrp,
492 struct cgroup *ancestor)
493{
494 if (cgrp->root != ancestor->root || cgrp->level < ancestor->level)
495 return false;
496 return cgrp->ancestor_ids[ancestor->level] == ancestor->id;
497}
498
499
500static inline bool cgroup_is_populated(struct cgroup *cgrp)
501{
502 return cgrp->populated_cnt;
503}
504
505
506static inline ino_t cgroup_ino(struct cgroup *cgrp)
507{
508 return cgrp->kn->ino;
509}
510
511
512static inline struct cftype *of_cft(struct kernfs_open_file *of)
513{
514 return of->kn->priv;
515}
516
517struct cgroup_subsys_state *of_css(struct kernfs_open_file *of);
518
519
520static inline struct cftype *seq_cft(struct seq_file *seq)
521{
522 return of_cft(seq->private);
523}
524
525static inline struct cgroup_subsys_state *seq_css(struct seq_file *seq)
526{
527 return of_css(seq->private);
528}
529
530
531
532
533
534
535static inline int cgroup_name(struct cgroup *cgrp, char *buf, size_t buflen)
536{
537 return kernfs_name(cgrp->kn, buf, buflen);
538}
539
540static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
541 size_t buflen)
542{
543 return kernfs_path(cgrp->kn, buf, buflen);
544}
545
546static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
547{
548 pr_cont_kernfs_name(cgrp->kn);
549}
550
551static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
552{
553 pr_cont_kernfs_path(cgrp->kn);
554}
555
556#else
557
558struct cgroup_subsys_state;
559
560static inline void css_put(struct cgroup_subsys_state *css) {}
561static inline int cgroup_attach_task_all(struct task_struct *from,
562 struct task_struct *t) { return 0; }
563static inline int cgroupstats_build(struct cgroupstats *stats,
564 struct dentry *dentry) { return -EINVAL; }
565
566static inline void cgroup_fork(struct task_struct *p) {}
567static inline int cgroup_can_fork(struct task_struct *p) { return 0; }
568static inline void cgroup_cancel_fork(struct task_struct *p) {}
569static inline void cgroup_post_fork(struct task_struct *p) {}
570static inline void cgroup_exit(struct task_struct *p) {}
571static inline void cgroup_free(struct task_struct *p) {}
572
573static inline int cgroup_init_early(void) { return 0; }
574static inline int cgroup_init(void) { return 0; }
575
576#endif
577
578
579
580
581
582#ifdef CONFIG_SOCK_CGROUP_DATA
583
584#if defined(CONFIG_CGROUP_NET_PRIO) || defined(CONFIG_CGROUP_NET_CLASSID)
585extern spinlock_t cgroup_sk_update_lock;
586#endif
587
588void cgroup_sk_alloc_disable(void);
589void cgroup_sk_alloc(struct sock_cgroup_data *skcd);
590void cgroup_sk_free(struct sock_cgroup_data *skcd);
591
592static inline struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)
593{
594#if defined(CONFIG_CGROUP_NET_PRIO) || defined(CONFIG_CGROUP_NET_CLASSID)
595 unsigned long v;
596
597
598
599
600
601 v = READ_ONCE(skcd->val);
602
603 if (v & 1)
604 return &cgrp_dfl_root.cgrp;
605
606 return (struct cgroup *)(unsigned long)v ?: &cgrp_dfl_root.cgrp;
607#else
608 return (struct cgroup *)(unsigned long)skcd->val;
609#endif
610}
611
612#else
613
614static inline void cgroup_sk_alloc(struct sock_cgroup_data *skcd) {}
615static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}
616
617#endif
618
619struct cgroup_namespace {
620 atomic_t count;
621 struct ns_common ns;
622 struct user_namespace *user_ns;
623 struct css_set *root_cset;
624};
625
626extern struct cgroup_namespace init_cgroup_ns;
627
628#ifdef CONFIG_CGROUPS
629
630void free_cgroup_ns(struct cgroup_namespace *ns);
631
632struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
633 struct user_namespace *user_ns,
634 struct cgroup_namespace *old_ns);
635
636char *cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
637 struct cgroup_namespace *ns);
638
639#else
640
641static inline void free_cgroup_ns(struct cgroup_namespace *ns) { }
642static inline struct cgroup_namespace *
643copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
644 struct cgroup_namespace *old_ns)
645{
646 return old_ns;
647}
648
649#endif
650
651static inline void get_cgroup_ns(struct cgroup_namespace *ns)
652{
653 if (ns)
654 atomic_inc(&ns->count);
655}
656
657static inline void put_cgroup_ns(struct cgroup_namespace *ns)
658{
659 if (ns && atomic_dec_and_test(&ns->count))
660 free_cgroup_ns(ns);
661}
662
663#endif
664