diff options
| author | Cong Wang <xiyou.wangcong@gmail.com> | 2017-10-26 21:24:39 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-10-29 09:49:31 -0400 |
| commit | 27ce4f05e2abbe2d3ec7434e456619a5178cd3bd (patch) | |
| tree | 6e1a1cbab4be66363cec571b853cae925689fe23 | |
| parent | d4f84a41dc615c166555cd332b0235bf6b9bcb4a (diff) | |
net_sched: use tcf_queue_work() in tcindex 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_tcindex.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 14a7e08b2fa9..beaa95e09c25 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
| @@ -27,14 +27,20 @@ | |||
| 27 | struct tcindex_filter_result { | 27 | struct tcindex_filter_result { |
| 28 | struct tcf_exts exts; | 28 | struct tcf_exts exts; |
| 29 | struct tcf_result res; | 29 | struct tcf_result res; |
| 30 | struct rcu_head rcu; | 30 | union { |
| 31 | struct work_struct work; | ||
| 32 | struct rcu_head rcu; | ||
| 33 | }; | ||
| 31 | }; | 34 | }; |
| 32 | 35 | ||
| 33 | struct tcindex_filter { | 36 | struct tcindex_filter { |
| 34 | u16 key; | 37 | u16 key; |
| 35 | struct tcindex_filter_result result; | 38 | struct tcindex_filter_result result; |
| 36 | struct tcindex_filter __rcu *next; | 39 | struct tcindex_filter __rcu *next; |
| 37 | struct rcu_head rcu; | 40 | union { |
| 41 | struct work_struct work; | ||
| 42 | struct rcu_head rcu; | ||
| 43 | }; | ||
| 38 | }; | 44 | }; |
| 39 | 45 | ||
| 40 | 46 | ||
| @@ -133,12 +139,34 @@ static int tcindex_init(struct tcf_proto *tp) | |||
| 133 | return 0; | 139 | return 0; |
| 134 | } | 140 | } |
| 135 | 141 | ||
| 142 | static void tcindex_destroy_rexts_work(struct work_struct *work) | ||
| 143 | { | ||
| 144 | struct tcindex_filter_result *r; | ||
| 145 | |||
| 146 | r = container_of(work, struct tcindex_filter_result, work); | ||
| 147 | rtnl_lock(); | ||
| 148 | tcf_exts_destroy(&r->exts); | ||
| 149 | rtnl_unlock(); | ||
| 150 | } | ||
| 151 | |||
| 136 | static void tcindex_destroy_rexts(struct rcu_head *head) | 152 | static void tcindex_destroy_rexts(struct rcu_head *head) |
| 137 | { | 153 | { |
| 138 | struct tcindex_filter_result *r; | 154 | struct tcindex_filter_result *r; |
| 139 | 155 | ||
| 140 | r = container_of(head, struct tcindex_filter_result, rcu); | 156 | r = container_of(head, struct tcindex_filter_result, rcu); |
| 141 | tcf_exts_destroy(&r->exts); | 157 | INIT_WORK(&r->work, tcindex_destroy_rexts_work); |
| 158 | tcf_queue_work(&r->work); | ||
| 159 | } | ||
| 160 | |||
| 161 | static void tcindex_destroy_fexts_work(struct work_struct *work) | ||
| 162 | { | ||
| 163 | struct tcindex_filter *f = container_of(work, struct tcindex_filter, | ||
| 164 | work); | ||
| 165 | |||
| 166 | rtnl_lock(); | ||
| 167 | tcf_exts_destroy(&f->result.exts); | ||
| 168 | kfree(f); | ||
| 169 | rtnl_unlock(); | ||
| 142 | } | 170 | } |
| 143 | 171 | ||
| 144 | static void tcindex_destroy_fexts(struct rcu_head *head) | 172 | static void tcindex_destroy_fexts(struct rcu_head *head) |
| @@ -146,8 +174,8 @@ static void tcindex_destroy_fexts(struct rcu_head *head) | |||
| 146 | struct tcindex_filter *f = container_of(head, struct tcindex_filter, | 174 | struct tcindex_filter *f = container_of(head, struct tcindex_filter, |
| 147 | rcu); | 175 | rcu); |
| 148 | 176 | ||
| 149 | tcf_exts_destroy(&f->result.exts); | 177 | INIT_WORK(&f->work, tcindex_destroy_fexts_work); |
| 150 | kfree(f); | 178 | tcf_queue_work(&f->work); |
| 151 | } | 179 | } |
| 152 | 180 | ||
| 153 | static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last) | 181 | static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last) |
