aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_cgroup.c')
-rw-r--r--net/sched/cls_cgroup.c75
1 files changed, 56 insertions, 19 deletions
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index e4877ca6727c..78ef2c5e130b 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -10,20 +10,37 @@
10 */ 10 */
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/slab.h>
13#include <linux/types.h> 14#include <linux/types.h>
14#include <linux/string.h> 15#include <linux/string.h>
15#include <linux/errno.h> 16#include <linux/errno.h>
16#include <linux/skbuff.h> 17#include <linux/skbuff.h>
17#include <linux/cgroup.h> 18#include <linux/cgroup.h>
19#include <linux/rcupdate.h>
18#include <net/rtnetlink.h> 20#include <net/rtnetlink.h>
19#include <net/pkt_cls.h> 21#include <net/pkt_cls.h>
22#include <net/sock.h>
23#include <net/cls_cgroup.h>
20 24
21struct cgroup_cls_state 25static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
22{ 26 struct cgroup *cgrp);
23 struct cgroup_subsys_state css; 27static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp);
24 u32 classid; 28static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
29
30struct cgroup_subsys net_cls_subsys = {
31 .name = "net_cls",
32 .create = cgrp_create,
33 .destroy = cgrp_destroy,
34 .populate = cgrp_populate,
35#ifdef CONFIG_NET_CLS_CGROUP
36 .subsys_id = net_cls_subsys_id,
37#else
38#define net_cls_subsys_id net_cls_subsys.subsys_id
39#endif
40 .module = THIS_MODULE,
25}; 41};
26 42
43
27static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp) 44static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp)
28{ 45{
29 return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id), 46 return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id),
@@ -79,14 +96,6 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
79 return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files)); 96 return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
80} 97}
81 98
82struct cgroup_subsys net_cls_subsys = {
83 .name = "net_cls",
84 .create = cgrp_create,
85 .destroy = cgrp_destroy,
86 .populate = cgrp_populate,
87 .subsys_id = net_cls_subsys_id,
88};
89
90struct cls_cgroup_head 99struct cls_cgroup_head
91{ 100{
92 u32 handle; 101 u32 handle;
@@ -100,6 +109,10 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
100 struct cls_cgroup_head *head = tp->root; 109 struct cls_cgroup_head *head = tp->root;
101 u32 classid; 110 u32 classid;
102 111
112 rcu_read_lock();
113 classid = task_cls_state(current)->classid;
114 rcu_read_unlock();
115
103 /* 116 /*
104 * Due to the nature of the classifier it is required to ignore all 117 * Due to the nature of the classifier it is required to ignore all
105 * packets originating from softirq context as accessing `current' 118 * packets originating from softirq context as accessing `current'
@@ -110,12 +123,12 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
110 * calls by looking at the number of nested bh disable calls because 123 * calls by looking at the number of nested bh disable calls because
111 * softirqs always disables bh. 124 * softirqs always disables bh.
112 */ 125 */
113 if (softirq_count() != SOFTIRQ_OFFSET) 126 if (softirq_count() != SOFTIRQ_OFFSET) {
114 return -1; 127 /* If there is an sk_classid we'll use that. */
115 128 if (!skb->sk)
116 rcu_read_lock(); 129 return -1;
117 classid = task_cls_state(current)->classid; 130 classid = skb->sk->sk_classid;
118 rcu_read_unlock(); 131 }
119 132
120 if (!classid) 133 if (!classid)
121 return -1; 134 return -1;
@@ -277,12 +290,36 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
277 290
278static int __init init_cgroup_cls(void) 291static int __init init_cgroup_cls(void)
279{ 292{
280 return register_tcf_proto_ops(&cls_cgroup_ops); 293 int ret;
294
295 ret = cgroup_load_subsys(&net_cls_subsys);
296 if (ret)
297 goto out;
298
299#ifndef CONFIG_NET_CLS_CGROUP
300 /* We can't use rcu_assign_pointer because this is an int. */
301 smp_wmb();
302 net_cls_subsys_id = net_cls_subsys.subsys_id;
303#endif
304
305 ret = register_tcf_proto_ops(&cls_cgroup_ops);
306 if (ret)
307 cgroup_unload_subsys(&net_cls_subsys);
308
309out:
310 return ret;
281} 311}
282 312
283static void __exit exit_cgroup_cls(void) 313static void __exit exit_cgroup_cls(void)
284{ 314{
285 unregister_tcf_proto_ops(&cls_cgroup_ops); 315 unregister_tcf_proto_ops(&cls_cgroup_ops);
316
317#ifndef CONFIG_NET_CLS_CGROUP
318 net_cls_subsys_id = -1;
319 synchronize_rcu();
320#endif
321
322 cgroup_unload_subsys(&net_cls_subsys);
286} 323}
287 324
288module_init(init_cgroup_cls); 325module_init(init_cgroup_cls);