diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2017-10-26 21:24:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-10-29 09:49:31 -0400 |
commit | d4f84a41dc615c166555cd332b0235bf6b9bcb4a (patch) | |
tree | 414c620af8738cd13652a1db44bf2661fbee2c2e /net | |
parent | c2f3f31d402be4849b06282c3a5278f2865c9fcc (diff) |
net_sched: use tcf_queue_work() in rsvp filter
Defer the tcf_exts_destroy() in RCU callback to
tc filter workqueue and get RTNL lock.
Reported-by: Chris Mi <chrism@mellanox.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jiri Pirko <jiri@resnulli.us>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/sched/cls_rsvp.h | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index b1f6ed48bc72..bdbc541787f8 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -97,7 +97,10 @@ struct rsvp_filter { | |||
97 | 97 | ||
98 | u32 handle; | 98 | u32 handle; |
99 | struct rsvp_session *sess; | 99 | struct rsvp_session *sess; |
100 | struct rcu_head rcu; | 100 | union { |
101 | struct work_struct work; | ||
102 | struct rcu_head rcu; | ||
103 | }; | ||
101 | }; | 104 | }; |
102 | 105 | ||
103 | static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid) | 106 | static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid) |
@@ -282,12 +285,22 @@ static int rsvp_init(struct tcf_proto *tp) | |||
282 | return -ENOBUFS; | 285 | return -ENOBUFS; |
283 | } | 286 | } |
284 | 287 | ||
285 | static void rsvp_delete_filter_rcu(struct rcu_head *head) | 288 | static void rsvp_delete_filter_work(struct work_struct *work) |
286 | { | 289 | { |
287 | struct rsvp_filter *f = container_of(head, struct rsvp_filter, rcu); | 290 | struct rsvp_filter *f = container_of(work, struct rsvp_filter, work); |
288 | 291 | ||
292 | rtnl_lock(); | ||
289 | tcf_exts_destroy(&f->exts); | 293 | tcf_exts_destroy(&f->exts); |
290 | kfree(f); | 294 | kfree(f); |
295 | rtnl_unlock(); | ||
296 | } | ||
297 | |||
298 | static void rsvp_delete_filter_rcu(struct rcu_head *head) | ||
299 | { | ||
300 | struct rsvp_filter *f = container_of(head, struct rsvp_filter, rcu); | ||
301 | |||
302 | INIT_WORK(&f->work, rsvp_delete_filter_work); | ||
303 | tcf_queue_work(&f->work); | ||
291 | } | 304 | } |
292 | 305 | ||
293 | static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) | 306 | static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) |