From: Cong Wang <xiyou.wangcong@gmail.com>
To: netdev@vger.kernel.org
Cc: jiri@mellanox.com, jakub.kicinski@netronome.com,
jhs@mojatatu.com, Cong Wang <xiyou.wangcong@gmail.com>
Subject: [Patch net v3 3/3] net_sched: carefully handle tcf_block_put()
Date: Mon, 11 Sep 2017 16:33:32 -0700 [thread overview]
Message-ID: <20170911233332.7594-4-xiyou.wangcong@gmail.com> (raw)
In-Reply-To: <20170911233332.7594-1-xiyou.wangcong@gmail.com>
As pointed out by Jiri, there is still a race condition between
tcf_block_put() and tcf_chain_destroy() in a RCU callback. There
is no way to make it correct without proper locking or synchronization,
because both operate on a shared list.
Locking is hard, because the only lock we can pick here is a spinlock,
however, in tc_dump_tfilter() we iterate this list with a sleeping
function called (tcf_chain_dump()), which makes using a lock to protect
chain_list almost impossible.
Jiri suggested the idea of holding a refcnt before flushing, this works
because it guarantees us there would be no parallel tcf_chain_destroy()
during the loop, therefore the race condition is gone. But we have to
be very careful with proper synchronization with RCU callbacks.
Suggested-by: Jiri Pirko <jiri@mellanox.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
net/sched/cls_api.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index d29e79d98a69..0b2219adf520 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -275,15 +275,27 @@ void tcf_block_put(struct tcf_block *block)
/* XXX: Standalone actions are not allowed to jump to any chain, and
* bound actions should be all removed after flushing. However,
- * filters are destroyed in RCU callbacks, we have to flush and wait
- * for them inside the loop, otherwise we race with RCU callbacks on
- * this list.
+ * filters are destroyed in RCU callbacks, we have to hold the chains
+ * first, otherwise we would always race with RCU callbacks on this list
+ * without proper locking.
*/
- list_for_each_entry_safe(chain, tmp, &block->chain_list, list) {
+
+ /* Wait for existing RCU callbacks to cool down. */
+ rcu_barrier();
+
+ /* Hold a refcnt for all chains, except 0, in case they are gone. */
+ list_for_each_entry(chain, &block->chain_list, list)
+ if (chain->index)
+ tcf_chain_hold(chain);
+
+ /* No race on the list, because no chain could be destroyed. */
+ list_for_each_entry(chain, &block->chain_list, list)
tcf_chain_flush(chain);
- rcu_barrier();
- }
+ /* Wait for RCU callbacks to release the reference count. */
+ rcu_barrier();
+
+ /* At this point, all the chains should have refcnt == 1. */
list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
tcf_chain_put(chain);
kfree(block);
--
2.13.0
next prev parent reply other threads:[~2017-09-11 23:33 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-11 23:33 [Patch net v3 0/3] net_sched: fix filter chain reference counting Cong Wang
2017-09-11 23:33 ` [Patch net v3 1/3] net_sched: get rid of tcfa_rcu Cong Wang
2017-09-12 9:42 ` Jiri Pirko
2017-09-12 10:40 ` Jiri Pirko
2017-09-12 21:10 ` Cong Wang
2017-09-12 21:36 ` Jiri Pirko
2017-09-12 21:53 ` Cong Wang
2017-09-13 6:13 ` Jiri Pirko
2017-09-11 23:33 ` [Patch net v3 2/3] net_sched: fix reference counting of tc filter chain Cong Wang
2017-09-12 10:43 ` Jiri Pirko
2017-09-11 23:33 ` Cong Wang [this message]
2017-09-12 10:43 ` [Patch net v3 3/3] net_sched: carefully handle tcf_block_put() Jiri Pirko
2017-09-13 3:41 ` [Patch net v3 0/3] net_sched: fix filter chain reference counting David Miller
2017-09-13 6:13 ` Jiri Pirko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170911233332.7594-4-xiyou.wangcong@gmail.com \
--to=xiyou.wangcong@gmail.com \
--cc=jakub.kicinski@netronome.com \
--cc=jhs@mojatatu.com \
--cc=jiri@mellanox.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.