Skip to content

Commit e071dff

Browse files
congwangdavem330
authored andcommitted
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 <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: Jiri Pirko <[email protected]> Cc: John Fastabend <[email protected]> Cc: Jamal Hadi Salim <[email protected]> Cc: "Paul E. McKenney" <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0552c8a commit e071dff

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

net/sched/cls_fw.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ struct fw_filter {
4646
#endif /* CONFIG_NET_CLS_IND */
4747
struct tcf_exts exts;
4848
struct tcf_proto *tp;
49-
struct rcu_head rcu;
49+
union {
50+
struct work_struct work;
51+
struct rcu_head rcu;
52+
};
5053
};
5154

5255
static u32 fw_hash(u32 handle)
@@ -119,12 +122,22 @@ static int fw_init(struct tcf_proto *tp)
119122
return 0;
120123
}
121124

122-
static void fw_delete_filter(struct rcu_head *head)
125+
static void fw_delete_filter_work(struct work_struct *work)
123126
{
124-
struct fw_filter *f = container_of(head, struct fw_filter, rcu);
127+
struct fw_filter *f = container_of(work, struct fw_filter, work);
125128

129+
rtnl_lock();
126130
tcf_exts_destroy(&f->exts);
127131
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);
128141
}
129142

130143
static void fw_destroy(struct tcf_proto *tp)

0 commit comments

Comments
 (0)