aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/sch_generic.h
diff options
context:
space:
mode:
authorCong Wang <[email protected]>2017-10-27 01:24:28 +0000
committerDavid S. Miller <[email protected]>2017-10-29 13:49:30 +0000
commit7aa0045dadb6ef37485ea9f2a7d28278ca588b51 (patch)
treee3c535a5d93bef05b780d64e220039f360e19104 /include/net/sch_generic.h
parentMerge branch 'sctp-endianness-fixes' (diff)
downloadkernel-7aa0045dadb6ef37485ea9f2a7d28278ca588b51.tar.gz
kernel-7aa0045dadb6ef37485ea9f2a7d28278ca588b51.zip
net_sched: introduce a workqueue for RCU callbacks of tc filter
This patch introduces a dedicated workqueue for tc filters so that each tc filter's RCU callback could defer their action destroy work to this workqueue. The helper tcf_queue_work() is introduced for them to use. Because we hold RTNL lock when calling tcf_block_put(), we can not simply flush works inside it, therefore we have to defer it again to this workqueue and make sure all flying RCU callbacks have already queued their work before this one, in other words, to ensure this is the last one to execute to prevent any use-after-free. On the other hand, this makes tcf_block_put() ugly and harder to understand. Since David and Eric strongly dislike adding synchronize_rcu(), this is probably the only solution that could make everyone happy. Please also see the code comments below. 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]>
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r--include/net/sch_generic.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 135f5a2dd931..0dec8a23be57 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -10,6 +10,7 @@
#include <linux/dynamic_queue_limits.h>
#include <linux/list.h>
#include <linux/refcount.h>
+#include <linux/workqueue.h>
#include <net/gen_stats.h>
#include <net/rtnetlink.h>
@@ -271,6 +272,7 @@ struct tcf_chain {
struct tcf_block {
struct list_head chain_list;
+ struct work_struct work;
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)