diff options
Diffstat (limited to 'net/sched/cls_basic.c')
-rw-r--r-- | net/sched/cls_basic.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 700b345b07f9..871351358c10 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -35,7 +35,10 @@ struct basic_filter { | |||
35 | struct tcf_result res; | 35 | struct tcf_result res; |
36 | struct tcf_proto *tp; | 36 | struct tcf_proto *tp; |
37 | struct list_head link; | 37 | struct list_head link; |
38 | struct rcu_head rcu; | 38 | union { |
39 | struct work_struct work; | ||
40 | struct rcu_head rcu; | ||
41 | }; | ||
39 | }; | 42 | }; |
40 | 43 | ||
41 | static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp, | 44 | static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
@@ -84,15 +87,26 @@ static int basic_init(struct tcf_proto *tp) | |||
84 | return 0; | 87 | return 0; |
85 | } | 88 | } |
86 | 89 | ||
87 | static void basic_delete_filter(struct rcu_head *head) | 90 | static void basic_delete_filter_work(struct work_struct *work) |
88 | { | 91 | { |
89 | struct basic_filter *f = container_of(head, struct basic_filter, rcu); | 92 | struct basic_filter *f = container_of(work, struct basic_filter, work); |
90 | 93 | ||
94 | rtnl_lock(); | ||
91 | tcf_exts_destroy(&f->exts); | 95 | tcf_exts_destroy(&f->exts); |
92 | tcf_em_tree_destroy(&f->ematches); | 96 | tcf_em_tree_destroy(&f->ematches); |
97 | rtnl_unlock(); | ||
98 | |||
93 | kfree(f); | 99 | kfree(f); |
94 | } | 100 | } |
95 | 101 | ||
102 | static void basic_delete_filter(struct rcu_head *head) | ||
103 | { | ||
104 | struct basic_filter *f = container_of(head, struct basic_filter, rcu); | ||
105 | |||
106 | INIT_WORK(&f->work, basic_delete_filter_work); | ||
107 | tcf_queue_work(&f->work); | ||
108 | } | ||
109 | |||
96 | static void basic_destroy(struct tcf_proto *tp) | 110 | static void basic_destroy(struct tcf_proto *tp) |
97 | { | 111 | { |
98 | struct basic_head *head = rtnl_dereference(tp->root); | 112 | struct basic_head *head = rtnl_dereference(tp->root); |