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