aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_basic.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_basic.c')
-rw-r--r--net/sched/cls_basic.c24
1 files changed, 7 insertions, 17 deletions
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 6b7ab3512f5b..95367f37098d 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -35,10 +35,7 @@ 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 union { 38 struct rcu_work rwork;
39 struct work_struct work;
40 struct rcu_head rcu;
41 };
42}; 39};
43 40
44static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp, 41static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -97,21 +94,14 @@ static void __basic_delete_filter(struct basic_filter *f)
97 94
98static void basic_delete_filter_work(struct work_struct *work) 95static void basic_delete_filter_work(struct work_struct *work)
99{ 96{
100 struct basic_filter *f = container_of(work, struct basic_filter, work); 97 struct basic_filter *f = container_of(to_rcu_work(work),
101 98 struct basic_filter,
99 rwork);
102 rtnl_lock(); 100 rtnl_lock();
103 __basic_delete_filter(f); 101 __basic_delete_filter(f);
104 rtnl_unlock(); 102 rtnl_unlock();
105} 103}
106 104
107static void basic_delete_filter(struct rcu_head *head)
108{
109 struct basic_filter *f = container_of(head, struct basic_filter, rcu);
110
111 INIT_WORK(&f->work, basic_delete_filter_work);
112 tcf_queue_work(&f->work);
113}
114
115static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 105static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
116{ 106{
117 struct basic_head *head = rtnl_dereference(tp->root); 107 struct basic_head *head = rtnl_dereference(tp->root);
@@ -122,7 +112,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
122 tcf_unbind_filter(tp, &f->res); 112 tcf_unbind_filter(tp, &f->res);
123 idr_remove(&head->handle_idr, f->handle); 113 idr_remove(&head->handle_idr, f->handle);
124 if (tcf_exts_get_net(&f->exts)) 114 if (tcf_exts_get_net(&f->exts))
125 call_rcu(&f->rcu, basic_delete_filter); 115 tcf_queue_work(&f->rwork, basic_delete_filter_work);
126 else 116 else
127 __basic_delete_filter(f); 117 __basic_delete_filter(f);
128 } 118 }
@@ -140,7 +130,7 @@ static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
140 tcf_unbind_filter(tp, &f->res); 130 tcf_unbind_filter(tp, &f->res);
141 idr_remove(&head->handle_idr, f->handle); 131 idr_remove(&head->handle_idr, f->handle);
142 tcf_exts_get_net(&f->exts); 132 tcf_exts_get_net(&f->exts);
143 call_rcu(&f->rcu, basic_delete_filter); 133 tcf_queue_work(&f->rwork, basic_delete_filter_work);
144 *last = list_empty(&head->flist); 134 *last = list_empty(&head->flist);
145 return 0; 135 return 0;
146} 136}
@@ -234,7 +224,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
234 list_replace_rcu(&fold->link, &fnew->link); 224 list_replace_rcu(&fold->link, &fnew->link);
235 tcf_unbind_filter(tp, &fold->res); 225 tcf_unbind_filter(tp, &fold->res);
236 tcf_exts_get_net(&fold->exts); 226 tcf_exts_get_net(&fold->exts);
237 call_rcu(&fold->rcu, basic_delete_filter); 227 tcf_queue_work(&fold->rwork, basic_delete_filter_work);
238 } else { 228 } else {
239 list_add_rcu(&fnew->link, &head->flist); 229 list_add_rcu(&fnew->link, &head->flist);
240 } 230 }