forked from Minki/linux
net: sched: protect chain->explicitly_created with block->lock
In order to remove dependency on rtnl lock, protect tcf_chain->explicitly_created flag with block->lock. Consolidate code that checks and resets 'explicitly_created' flag into __tcf_chain_put() to execute it atomically with rest of code that puts chain reference. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c266f64dbf
commit
91052fa1c6
@ -370,13 +370,22 @@ EXPORT_SYMBOL(tcf_chain_get_by_act);
|
|||||||
|
|
||||||
static void tc_chain_tmplt_del(struct tcf_chain *chain);
|
static void tc_chain_tmplt_del(struct tcf_chain *chain);
|
||||||
|
|
||||||
static void __tcf_chain_put(struct tcf_chain *chain, bool by_act)
|
static void __tcf_chain_put(struct tcf_chain *chain, bool by_act,
|
||||||
|
bool explicitly_created)
|
||||||
{
|
{
|
||||||
struct tcf_block *block = chain->block;
|
struct tcf_block *block = chain->block;
|
||||||
bool is_last, free_block = false;
|
bool is_last, free_block = false;
|
||||||
unsigned int refcnt;
|
unsigned int refcnt;
|
||||||
|
|
||||||
mutex_lock(&block->lock);
|
mutex_lock(&block->lock);
|
||||||
|
if (explicitly_created) {
|
||||||
|
if (!chain->explicitly_created) {
|
||||||
|
mutex_unlock(&block->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chain->explicitly_created = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (by_act)
|
if (by_act)
|
||||||
chain->action_refcnt--;
|
chain->action_refcnt--;
|
||||||
|
|
||||||
@ -402,19 +411,18 @@ static void __tcf_chain_put(struct tcf_chain *chain, bool by_act)
|
|||||||
|
|
||||||
static void tcf_chain_put(struct tcf_chain *chain)
|
static void tcf_chain_put(struct tcf_chain *chain)
|
||||||
{
|
{
|
||||||
__tcf_chain_put(chain, false);
|
__tcf_chain_put(chain, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcf_chain_put_by_act(struct tcf_chain *chain)
|
void tcf_chain_put_by_act(struct tcf_chain *chain)
|
||||||
{
|
{
|
||||||
__tcf_chain_put(chain, true);
|
__tcf_chain_put(chain, true, false);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tcf_chain_put_by_act);
|
EXPORT_SYMBOL(tcf_chain_put_by_act);
|
||||||
|
|
||||||
static void tcf_chain_put_explicitly_created(struct tcf_chain *chain)
|
static void tcf_chain_put_explicitly_created(struct tcf_chain *chain)
|
||||||
{
|
{
|
||||||
if (chain->explicitly_created)
|
__tcf_chain_put(chain, false, true);
|
||||||
tcf_chain_put(chain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcf_chain_flush(struct tcf_chain *chain)
|
static void tcf_chain_flush(struct tcf_chain *chain)
|
||||||
@ -2305,7 +2313,6 @@ replay:
|
|||||||
* to the chain previously taken during addition.
|
* to the chain previously taken during addition.
|
||||||
*/
|
*/
|
||||||
tcf_chain_put_explicitly_created(chain);
|
tcf_chain_put_explicitly_created(chain);
|
||||||
chain->explicitly_created = false;
|
|
||||||
break;
|
break;
|
||||||
case RTM_GETCHAIN:
|
case RTM_GETCHAIN:
|
||||||
err = tc_chain_notify(chain, skb, n->nlmsg_seq,
|
err = tc_chain_notify(chain, skb, n->nlmsg_seq,
|
||||||
|
Loading…
Reference in New Issue
Block a user