Skip to content

Commit 27ce4f0

Browse files
congwangdavem330
authored andcommitted
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>
1 parent d4f84a4 commit 27ce4f0

1 file changed

Lines changed: 33 additions & 5 deletions

File tree

net/sched/cls_tcindex.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,20 @@
2727
struct tcindex_filter_result {
2828
struct tcf_exts exts;
2929
struct tcf_result res;
30-
struct rcu_head rcu;
30+
union {
31+
struct work_struct work;
32+
struct rcu_head rcu;
33+
};
3134
};
3235

3336
struct tcindex_filter {
3437
u16 key;
3538
struct tcindex_filter_result result;
3639
struct tcindex_filter __rcu *next;
37-
struct rcu_head rcu;
40+
union {
41+
struct work_struct work;
42+
struct rcu_head rcu;
43+
};
3844
};
3945

4046

@@ -133,21 +139,43 @@ static int tcindex_init(struct tcf_proto *tp)
133139
return 0;
134140
}
135141

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+
136152
static void tcindex_destroy_rexts(struct rcu_head *head)
137153
{
138154
struct tcindex_filter_result *r;
139155

140156
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();
142170
}
143171

144172
static void tcindex_destroy_fexts(struct rcu_head *head)
145173
{
146174
struct tcindex_filter *f = container_of(head, struct tcindex_filter,
147175
rcu);
148176

149-
tcf_exts_destroy(&f->result.exts);
150-
kfree(f);
177+
INIT_WORK(&f->work, tcindex_destroy_fexts_work);
178+
tcf_queue_work(&f->work);
151179
}
152180

153181
static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last)

0 commit comments

Comments
 (0)