summaryrefslogtreecommitdiff
path: root/net/sched
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2019-02-25 17:45:44 +0200
committerDavid S. Miller <davem@davemloft.net>2019-02-25 10:25:02 -0800
commitace4a267e89f280ef5504b29ea10581319c07630 (patch)
tree20ad36c7c541f70b36f9637410b1fb311cf98741 /net/sched
parent6676d5e416eecaf4e823a2c3903aa132ffc2ede0 (diff)
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>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/cls_api.c16
1 files 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 @@ errout_block_locked:
/* 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);