From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vlad Buslov Subject: [PATCH net-next 04/17] net: sched: protect block->chain0 with block->lock Date: Mon, 12 Nov 2018 09:55:33 +0200 Message-ID: <1542009346-23780-5-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]:54908 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728300AbeKLRsA (ORCPT ); Mon, 12 Nov 2018 12:48:00 -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, use block->lock to protect chain0 struct from concurrent modification. Rearrange code in chain0 callback add and del functions to only access chain0 when block->lock is held. Signed-off-by: Vlad Buslov Acked-by: Jiri Pirko --- net/sched/cls_api.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 146a02094905..beffcc2ab1fa 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -260,8 +260,11 @@ static void tcf_chain0_head_change(struct tcf_chain *chain, if (chain->index) return; + + spin_lock(&block->lock); list_for_each_entry(item, &block->chain0.filter_chain_list, list) tcf_chain_head_change_item(item, tp_head); + spin_unlock(&block->lock); } /* Returns true if block can be safely freed. */ @@ -519,8 +522,8 @@ tcf_chain0_head_change_cb_add(struct tcf_block *block, struct tcf_block_ext_info *ei, struct netlink_ext_ack *extack) { - struct tcf_chain *chain0 = block->chain0.chain; struct tcf_filter_chain_list_item *item; + struct tcf_chain *chain0; item = kmalloc(sizeof(*item), GFP_KERNEL); if (!item) { @@ -529,9 +532,14 @@ tcf_chain0_head_change_cb_add(struct tcf_block *block, } item->chain_head_change = ei->chain_head_change; item->chain_head_change_priv = ei->chain_head_change_priv; + + spin_lock(&block->lock); + chain0 = block->chain0.chain; if (chain0 && chain0->filter_chain) tcf_chain_head_change_item(item, chain0->filter_chain); list_add(&item->list, &block->chain0.filter_chain_list); + spin_unlock(&block->lock); + return 0; } @@ -539,20 +547,23 @@ static void tcf_chain0_head_change_cb_del(struct tcf_block *block, struct tcf_block_ext_info *ei) { - struct tcf_chain *chain0 = block->chain0.chain; struct tcf_filter_chain_list_item *item; + spin_lock(&block->lock); list_for_each_entry(item, &block->chain0.filter_chain_list, list) { if ((!ei->chain_head_change && !ei->chain_head_change_priv) || (item->chain_head_change == ei->chain_head_change && item->chain_head_change_priv == ei->chain_head_change_priv)) { - if (chain0) + if (block->chain0.chain) tcf_chain_head_change_item(item, NULL); list_del(&item->list); + spin_unlock(&block->lock); + kfree(item); return; } } + spin_unlock(&block->lock); WARN_ON(1); } -- 2.7.5