From ace4a267e89f280ef5504b29ea10581319c07630 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Mon, 25 Feb 2019 17:45:44 +0200 Subject: [PATCH] net: sched: don't release block->lock when dumping chains Function tc_dump_chain() obtains and releases block->lock on each iteration of its inner loop that dumps all chains on block. Outputting chain template info is fast operation so locking/unlocking mutex multiple times is an overhead when lock is highly contested. Modify tc_dump_chain() to only obtain block->lock once and dump all chains without releasing it. Signed-off-by: Vlad Buslov Suggested-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/cls_api.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 97d9312c2ff9..befc06f658df 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -2912,12 +2912,12 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, /* called with RTNL */ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) { - struct tcf_chain *chain, *chain_prev; struct net *net = sock_net(skb->sk); struct nlattr *tca[TCA_MAX + 1]; struct Qdisc *q = NULL; struct tcf_block *block; struct tcmsg *tcm = nlmsg_data(cb->nlh); + struct tcf_chain *chain; long index_start; long index; u32 parent; @@ -2980,11 +2980,8 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) index_start = cb->args[0]; index = 0; - for (chain = __tcf_get_next_chain(block, NULL); - chain; - chain_prev = chain, - chain = __tcf_get_next_chain(block, chain), - tcf_chain_put(chain_prev)) { + mutex_lock(&block->lock); + list_for_each_entry(chain, &block->chain_list, list) { if ((tca[TCA_CHAIN] && nla_get_u32(tca[TCA_CHAIN]) != chain->index)) continue; @@ -2992,17 +2989,18 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) index++; continue; } + if (tcf_chain_held_by_acts_only(chain)) + continue; err = tc_chain_fill_node(chain->tmplt_ops, chain->tmplt_priv, chain->index, net, skb, block, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWCHAIN); - if (err <= 0) { - tcf_chain_put(chain); + if (err <= 0) break; - } index++; } + mutex_unlock(&block->lock); if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) tcf_block_refcnt_put(block, true);