Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/core/netclassid_cgroup.c
26288 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* net/core/netclassid_cgroup.c Classid Cgroupfs Handling
4
*
5
* Authors: Thomas Graf <[email protected]>
6
*/
7
8
#include <linux/slab.h>
9
#include <linux/cgroup.h>
10
#include <linux/fdtable.h>
11
#include <linux/sched/task.h>
12
13
#include <net/cls_cgroup.h>
14
#include <net/sock.h>
15
16
static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
17
{
18
return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
19
}
20
21
struct cgroup_cls_state *task_cls_state(struct task_struct *p)
22
{
23
return css_cls_state(task_css_check(p, net_cls_cgrp_id,
24
rcu_read_lock_held() ||
25
rcu_read_lock_bh_held() ||
26
rcu_read_lock_trace_held()));
27
}
28
EXPORT_SYMBOL_GPL(task_cls_state);
29
30
static struct cgroup_subsys_state *
31
cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
32
{
33
struct cgroup_cls_state *cs;
34
35
cs = kzalloc(sizeof(*cs), GFP_KERNEL);
36
if (!cs)
37
return ERR_PTR(-ENOMEM);
38
39
return &cs->css;
40
}
41
42
static int cgrp_css_online(struct cgroup_subsys_state *css)
43
{
44
struct cgroup_cls_state *cs = css_cls_state(css);
45
struct cgroup_cls_state *parent = css_cls_state(css->parent);
46
47
if (parent)
48
cs->classid = parent->classid;
49
50
return 0;
51
}
52
53
static void cgrp_css_free(struct cgroup_subsys_state *css)
54
{
55
kfree(css_cls_state(css));
56
}
57
58
/*
59
* To avoid freezing of sockets creation for tasks with big number of threads
60
* and opened sockets lets release file_lock every 1000 iterated descriptors.
61
* New sockets will already have been created with new classid.
62
*/
63
64
struct update_classid_context {
65
u32 classid;
66
unsigned int batch;
67
};
68
69
#define UPDATE_CLASSID_BATCH 1000
70
71
static int update_classid_sock(const void *v, struct file *file, unsigned int n)
72
{
73
struct update_classid_context *ctx = (void *)v;
74
struct socket *sock = sock_from_file(file);
75
76
if (sock)
77
sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid);
78
if (--ctx->batch == 0) {
79
ctx->batch = UPDATE_CLASSID_BATCH;
80
return n + 1;
81
}
82
return 0;
83
}
84
85
static void update_classid_task(struct task_struct *p, u32 classid)
86
{
87
struct update_classid_context ctx = {
88
.classid = classid,
89
.batch = UPDATE_CLASSID_BATCH
90
};
91
unsigned int fd = 0;
92
93
/* Only update the leader task, when many threads in this task,
94
* so it can avoid the useless traversal.
95
*/
96
if (p != p->group_leader)
97
return;
98
99
do {
100
task_lock(p);
101
fd = iterate_fd(p->files, fd, update_classid_sock, &ctx);
102
task_unlock(p);
103
cond_resched();
104
} while (fd);
105
}
106
107
static void cgrp_attach(struct cgroup_taskset *tset)
108
{
109
struct cgroup_subsys_state *css;
110
struct task_struct *p;
111
112
cgroup_taskset_for_each(p, css, tset) {
113
update_classid_task(p, css_cls_state(css)->classid);
114
}
115
}
116
117
static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
118
{
119
return css_cls_state(css)->classid;
120
}
121
122
static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
123
u64 value)
124
{
125
struct cgroup_cls_state *cs = css_cls_state(css);
126
struct css_task_iter it;
127
struct task_struct *p;
128
129
cs->classid = (u32)value;
130
131
css_task_iter_start(css, 0, &it);
132
while ((p = css_task_iter_next(&it)))
133
update_classid_task(p, cs->classid);
134
css_task_iter_end(&it);
135
136
return 0;
137
}
138
139
static struct cftype ss_files[] = {
140
{
141
.name = "classid",
142
.read_u64 = read_classid,
143
.write_u64 = write_classid,
144
},
145
{ } /* terminate */
146
};
147
148
struct cgroup_subsys net_cls_cgrp_subsys = {
149
.css_alloc = cgrp_css_alloc,
150
.css_online = cgrp_css_online,
151
.css_free = cgrp_css_free,
152
.attach = cgrp_attach,
153
.legacy_cftypes = ss_files,
154
};
155
156