Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <vladbu@mellanox.com>
Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vlad Buslov and committed by
David S. Miller
ace4a267 6676d5e4

+7 -9
+7 -9
net/sched/cls_api.c
··· 2912 2912 /* called with RTNL */ 2913 2913 static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) 2914 2914 { 2915 - struct tcf_chain *chain, *chain_prev; 2916 2915 struct net *net = sock_net(skb->sk); 2917 2916 struct nlattr *tca[TCA_MAX + 1]; 2918 2917 struct Qdisc *q = NULL; 2919 2918 struct tcf_block *block; 2920 2919 struct tcmsg *tcm = nlmsg_data(cb->nlh); 2920 + struct tcf_chain *chain; 2921 2921 long index_start; 2922 2922 long index; 2923 2923 u32 parent; ··· 2980 2980 index_start = cb->args[0]; 2981 2981 index = 0; 2982 2982 2983 - for (chain = __tcf_get_next_chain(block, NULL); 2984 - chain; 2985 - chain_prev = chain, 2986 - chain = __tcf_get_next_chain(block, chain), 2987 - tcf_chain_put(chain_prev)) { 2983 + mutex_lock(&block->lock); 2984 + list_for_each_entry(chain, &block->chain_list, list) { 2988 2985 if ((tca[TCA_CHAIN] && 2989 2986 nla_get_u32(tca[TCA_CHAIN]) != chain->index)) 2990 2987 continue; ··· 2989 2992 index++; 2990 2993 continue; 2991 2994 } 2995 + if (tcf_chain_held_by_acts_only(chain)) 2996 + continue; 2992 2997 err = tc_chain_fill_node(chain->tmplt_ops, chain->tmplt_priv, 2993 2998 chain->index, net, skb, block, 2994 2999 NETLINK_CB(cb->skb).portid, 2995 3000 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2996 3001 RTM_NEWCHAIN); 2997 - if (err <= 0) { 2998 - tcf_chain_put(chain); 3002 + if (err <= 0) 2999 3003 break; 3000 - } 3001 3004 index++; 3002 3005 } 3006 + mutex_unlock(&block->lock); 3003 3007 3004 3008 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) 3005 3009 tcf_block_refcnt_put(block, true);