diff options
| author | Cong Wang <xiyou.wangcong@gmail.com> | 2017-10-26 21:24:34 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-10-29 09:49:31 -0400 |
| commit | e071dff2a6beeccb6f9744f9a0251ab773ca2ab8 (patch) | |
| tree | 28ddec66cf18004c8c8ce9bff76e78e70c3a6600 | |
| parent | 0552c8afa077889b4704ef5ee88b03063ad45023 (diff) | |
net_sched: use tcf_queue_work() in fw 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>
| -rw-r--r-- | net/sched/cls_fw.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 941245ad07fd..99183b8621ec 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
| @@ -46,7 +46,10 @@ struct fw_filter { | |||
| 46 | #endif /* CONFIG_NET_CLS_IND */ | 46 | #endif /* CONFIG_NET_CLS_IND */ |
| 47 | struct tcf_exts exts; | 47 | struct tcf_exts exts; |
| 48 | struct tcf_proto *tp; | 48 | struct tcf_proto *tp; |
| 49 | struct rcu_head rcu; | 49 | union { |
| 50 | struct work_struct work; | ||
| 51 | struct rcu_head rcu; | ||
| 52 | }; | ||
| 50 | }; | 53 | }; |
| 51 | 54 | ||
| 52 | static u32 fw_hash(u32 handle) | 55 | static u32 fw_hash(u32 handle) |
| @@ -119,12 +122,22 @@ static int fw_init(struct tcf_proto *tp) | |||
| 119 | return 0; | 122 | return 0; |
| 120 | } | 123 | } |
| 121 | 124 | ||
| 122 | static void fw_delete_filter(struct rcu_head *head) | 125 | static void fw_delete_filter_work(struct work_struct *work) |
| 123 | { | 126 | { |
| 124 | struct fw_filter *f = container_of(head, struct fw_filter, rcu); | 127 | struct fw_filter *f = container_of(work, struct fw_filter, work); |
| 125 | 128 | ||
| 129 | rtnl_lock(); | ||
| 126 | tcf_exts_destroy(&f->exts); | 130 | tcf_exts_destroy(&f->exts); |
| 127 | kfree(f); | 131 | kfree(f); |
| 132 | rtnl_unlock(); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void fw_delete_filter(struct rcu_head *head) | ||
| 136 | { | ||
| 137 | struct fw_filter *f = container_of(head, struct fw_filter, rcu); | ||
| 138 | |||
| 139 | INIT_WORK(&f->work, fw_delete_filter_work); | ||
| 140 | tcf_queue_work(&f->work); | ||
| 128 | } | 141 | } |
| 129 | 142 | ||
| 130 | static void fw_destroy(struct tcf_proto *tp) | 143 | static void fw_destroy(struct tcf_proto *tp) |
