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 d89ebafd2239..f177649a2419 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -34,7 +34,10 @@ struct basic_filter { | |||
34 | struct tcf_result res; | 34 | struct tcf_result res; |
35 | struct tcf_proto *tp; | 35 | struct tcf_proto *tp; |
36 | struct list_head link; | 36 | struct list_head link; |
37 | struct rcu_head rcu; | 37 | union { |
38 | struct work_struct work; | ||
39 | struct rcu_head rcu; | ||
40 | }; | ||
38 | }; | 41 | }; |
39 | 42 | ||
40 | static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp, | 43 | static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
@@ -82,15 +85,26 @@ static int basic_init(struct tcf_proto *tp) | |||
82 | return 0; | 85 | return 0; |
83 | } | 86 | } |
84 | 87 | ||
85 | static void basic_delete_filter(struct rcu_head *head) | 88 | static void basic_delete_filter_work(struct work_struct *work) |
86 | { | 89 | { |
87 | struct basic_filter *f = container_of(head, struct basic_filter, rcu); | 90 | struct basic_filter *f = container_of(work, struct basic_filter, work); |
88 | 91 | ||
92 | rtnl_lock(); | ||
89 | tcf_exts_destroy(&f->exts); | 93 | tcf_exts_destroy(&f->exts); |
90 | tcf_em_tree_destroy(&f->ematches); | 94 | tcf_em_tree_destroy(&f->ematches); |
95 | rtnl_unlock(); | ||
96 | |||
91 | kfree(f); | 97 | kfree(f); |
92 | } | 98 | } |
93 | 99 | ||
100 | static void basic_delete_filter(struct rcu_head *head) | ||
101 | { | ||
102 | struct basic_filter *f = container_of(head, struct basic_filter, rcu); | ||
103 | |||
104 | INIT_WORK(&f->work, basic_delete_filter_work); | ||
105 | tcf_queue_work(&f->work); | ||
106 | } | ||
107 | |||
94 | static void basic_destroy(struct tcf_proto *tp) | 108 | static void basic_destroy(struct tcf_proto *tp) |
95 | { | 109 | { |
96 | struct basic_head *head = rtnl_dereference(tp->root); | 110 | struct basic_head *head = rtnl_dereference(tp->root); |