Commit f0023436 authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller

net: sched: implement functions to put and flush all chains

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: default avatarVlad Buslov <vladbu@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cfebd7e2
...@@ -527,6 +527,31 @@ static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index) ...@@ -527,6 +527,31 @@ static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index)
return idr_find(&tn->idr, block_index); 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. /* Find tcf block.
* Set q, parent, cl when appropriate. * Set q, parent, cl when appropriate.
*/ */
...@@ -786,8 +811,6 @@ EXPORT_SYMBOL(tcf_block_get); ...@@ -786,8 +811,6 @@ EXPORT_SYMBOL(tcf_block_get);
void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
struct tcf_block_ext_info *ei) struct tcf_block_ext_info *ei)
{ {
struct tcf_chain *chain, *tmp;
if (!block) if (!block)
return; return;
tcf_chain0_head_change_cb_del(block, ei); tcf_chain0_head_change_cb_del(block, ei);
...@@ -804,32 +827,14 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, ...@@ -804,32 +827,14 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
if (tcf_block_shared(block)) if (tcf_block_shared(block))
tcf_block_remove(block, block->net); tcf_block_remove(block, block->net);
if (!free_block)
if (!free_block) { tcf_block_flush_all_chains(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);
}
tcf_block_offload_unbind(block, q, ei); tcf_block_offload_unbind(block, q, ei);
if (free_block) { if (free_block)
kfree(block); kfree(block);
} else { else
/* At this point, all the chains should have tcf_block_put_all_chains(block);
* refcnt >= 1.
*/
list_for_each_entry_safe(chain, tmp, &block->chain_list,
list) {
tcf_chain_put_explicitly_created(chain);
tcf_chain_put(chain);
}
}
} else { } else {
tcf_block_offload_unbind(block, q, ei); tcf_block_offload_unbind(block, q, ei);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment