From: Vlad Buslov Date: Mon, 11 Feb 2019 08:55:33 +0000 (+0200) Subject: net: sched: protect chain->explicitly_created with block->lock X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=91052fa1c657d83d570a3ab0ca0ddf87713b5cc8;p=openwrt%2Fstaging%2Fblogic.git 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 Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 806e7158a7e8..2ebf8e53038a 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -370,13 +370,22 @@ EXPORT_SYMBOL(tcf_chain_get_by_act); 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; bool is_last, free_block = false; unsigned int refcnt; mutex_lock(&block->lock); + if (explicitly_created) { + if (!chain->explicitly_created) { + mutex_unlock(&block->lock); + return; + } + chain->explicitly_created = false; + } + if (by_act) 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) { - __tcf_chain_put(chain, false); + __tcf_chain_put(chain, false, false); } 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); static void tcf_chain_put_explicitly_created(struct tcf_chain *chain) { - if (chain->explicitly_created) - tcf_chain_put(chain); + __tcf_chain_put(chain, false, true); } static void tcf_chain_flush(struct tcf_chain *chain) @@ -2305,7 +2313,6 @@ replay: * to the chain previously taken during addition. */ tcf_chain_put_explicitly_created(chain); - chain->explicitly_created = false; break; case RTM_GETCHAIN: err = tc_chain_notify(chain, skb, n->nlmsg_seq,