From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vlad Buslov Subject: [PATCH net-next 03/17] net: sched: refactor tc_ctl_chain() to use block->lock Date: Mon, 12 Nov 2018 09:55:32 +0200 Message-ID: <1542009346-23780-4-git-send-email-vladbu@mellanox.com> References: <1542009346-23780-1-git-send-email-vladbu@mellanox.com> Cc: jhs@mojatatu.com, xiyou.wangcong@gmail.com, jiri@resnulli.us, davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Vlad Buslov To: netdev@vger.kernel.org Return-path: Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:54855 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727989AbeKLRrz (ORCPT ); Mon, 12 Nov 2018 12:47:55 -0500 In-Reply-To: <1542009346-23780-1-git-send-email-vladbu@mellanox.com> Sender: netdev-owner@vger.kernel.org List-ID: In order to remove dependency on rtnl lock, modify chain API to use block->lock to protect chain from concurrent modification. Rearrange tc_ctl_chain() code to call tcf_chain_hold() while holding block->lock. Signed-off-by: Vlad Buslov Acked-by: Jiri Pirko --- net/sched/cls_api.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index df3326dd33ef..146a02094905 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -2047,6 +2047,8 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, err = -EINVAL; goto errout_block; } + + spin_lock(&block->lock); chain = tcf_chain_lookup(block, chain_index); if (n->nlmsg_type == RTM_NEWCHAIN) { if (chain) { @@ -2058,41 +2060,49 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, } else { NL_SET_ERR_MSG(extack, "Filter chain already exists"); err = -EEXIST; - goto errout_block; + goto errout_block_locked; } } else { if (!(n->nlmsg_flags & NLM_F_CREATE)) { NL_SET_ERR_MSG(extack, "Need both RTM_NEWCHAIN and NLM_F_CREATE to create a new chain"); err = -ENOENT; - goto errout_block; + goto errout_block_locked; } chain = tcf_chain_create(block, chain_index); if (!chain) { NL_SET_ERR_MSG(extack, "Failed to create filter chain"); err = -ENOMEM; - goto errout_block; + goto errout_block_locked; } } } else { if (!chain || tcf_chain_held_by_acts_only(chain)) { NL_SET_ERR_MSG(extack, "Cannot find specified filter chain"); err = -EINVAL; - goto errout_block; + goto errout_block_locked; } tcf_chain_hold(chain); } + if (n->nlmsg_type == RTM_NEWCHAIN) { + /* Modifying chain requires holding parent block lock. In case + * the chain was successfully added, take a reference to the + * chain. This ensures that an empty chain does not disappear at + * the end of this function. + */ + tcf_chain_hold(chain); + chain->explicitly_created = true; + } + spin_unlock(&block->lock); + switch (n->nlmsg_type) { case RTM_NEWCHAIN: err = tc_chain_tmplt_add(chain, net, tca, extack); - if (err) + if (err) { + tcf_chain_put_explicitly_created(chain); goto errout; - /* In case the chain was successfully added, take a reference - * to the chain. This ensures that an empty chain - * does not disappear at the end of this function. - */ - tcf_chain_hold(chain); - chain->explicitly_created = true; + } + tc_chain_notify(chain, NULL, 0, NLM_F_CREATE | NLM_F_EXCL, RTM_NEWCHAIN, false); break; @@ -2127,6 +2137,10 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, /* Replay the request. */ goto replay; return err; + +errout_block_locked: + spin_unlock(&block->lock); + goto errout_block; } /* called with RTNL */ -- 2.7.5