]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
net: sched: don't release block->lock when dumping chains
authorVlad Buslov <vladbu@mellanox.com>
Mon, 25 Feb 2019 15:45:44 +0000 (17:45 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 25 Feb 2019 18:25:02 +0000 (10:25 -0800)
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>
net/sched/cls_api.c

index 97d9312c2ff90e2a907397fdeb9761e818d1ae2e..befc06f658dff4b64da0a1099d335c7867e62cc0 100644 (file)
@@ -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);