From: Vlad Buslov <vladbu@mellanox.com>
Date: Mon, 24 Sep 2018 19:22:55 +0300
Subject: net: sched: implement functions to put and flush all chains
Patch-mainline: v4.20-rc1
Git-commit: f00234367b64503d2436bb3d0f37bbe98ac2cc97
References: bsc#1109837
Extract code that flushes and puts all chains on tcf block to two
standalone function to be shared with functions that locklessly get/put
reference to block.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
net/sched/cls_api.c | 55 ++++++++++++++++++++++++++++------------------------
1 file changed, 30 insertions(+), 25 deletions(-)
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -530,6 +530,31 @@ static struct tcf_block *tcf_block_looku
return idr_find(&tn->idr, block_index);
}
+static void tcf_block_flush_all_chains(struct tcf_block *block)
+{
+ struct tcf_chain *chain;
+
+ /* Hold a refcnt for all chains, so that they don't disappear
+ * while we are iterating.
+ */
+ list_for_each_entry(chain, &block->chain_list, list)
+ tcf_chain_hold(chain);
+
+ list_for_each_entry(chain, &block->chain_list, list)
+ tcf_chain_flush(chain);
+}
+
+static void tcf_block_put_all_chains(struct tcf_block *block)
+{
+ struct tcf_chain *chain, *tmp;
+
+ /* At this point, all the chains should have refcnt >= 1. */
+ list_for_each_entry_safe(chain, tmp, &block->chain_list, list) {
+ tcf_chain_put_explicitly_created(chain);
+ tcf_chain_put(chain);
+ }
+}
+
/* Find tcf block.
* Set q, parent, cl when appropriate.
*/
@@ -789,8 +814,6 @@ EXPORT_SYMBOL(tcf_block_get);
void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
struct tcf_block_ext_info *ei)
{
- struct tcf_chain *chain, *tmp;
-
if (!block)
return;
tcf_chain0_head_change_cb_del(block, ei);
@@ -807,32 +830,14 @@ void tcf_block_put_ext(struct tcf_block
if (tcf_block_shared(block))
tcf_block_remove(block, block->net);
-
- if (!free_block) {
- /* Hold a refcnt for all chains, so that they don't
- * disappear while we are iterating.
- */
- list_for_each_entry(chain, &block->chain_list, list)
- tcf_chain_hold(chain);
-
- list_for_each_entry(chain, &block->chain_list, list)
- tcf_chain_flush(chain);
- }
-
+ if (!free_block)
+ tcf_block_flush_all_chains(block);
tcf_block_offload_unbind(block, q, ei);
- if (free_block) {
+ if (free_block)
kfree(block);
- } else {
- /* At this point, all the chains should have
- * refcnt >= 1.
- */
- list_for_each_entry_safe(chain, tmp, &block->chain_list,
- list) {
- tcf_chain_put_explicitly_created(chain);
- tcf_chain_put(chain);
- }
- }
+ else
+ tcf_block_put_all_chains(block);
} else {
tcf_block_offload_unbind(block, q, ei);
}