OSDN Git Service

net: sched: protect chain->explicitly_created with block->lock
authorVlad Buslov <vladbu@mellanox.com>
Mon, 11 Feb 2019 08:55:33 +0000 (10:55 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 12 Feb 2019 18:41:32 +0000 (13:41 -0500)
In order to remove dependency on rtnl lock, protect
tcf_chain->explicitly_created flag with block->lock. Consolidate code that
checks and resets 'explicitly_created' flag into __tcf_chain_put() to
execute it atomically with rest of code that puts chain reference.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/cls_api.c

index 806e715..2ebf8e5 100644 (file)
@@ -370,13 +370,22 @@ EXPORT_SYMBOL(tcf_chain_get_by_act);
 
 static void tc_chain_tmplt_del(struct tcf_chain *chain);
 
-static void __tcf_chain_put(struct tcf_chain *chain, bool by_act)
+static void __tcf_chain_put(struct tcf_chain *chain, bool by_act,
+                           bool explicitly_created)
 {
        struct tcf_block *block = chain->block;
        bool is_last, free_block = false;
        unsigned int refcnt;
 
        mutex_lock(&block->lock);
+       if (explicitly_created) {
+               if (!chain->explicitly_created) {
+                       mutex_unlock(&block->lock);
+                       return;
+               }
+               chain->explicitly_created = false;
+       }
+
        if (by_act)
                chain->action_refcnt--;
 
@@ -402,19 +411,18 @@ static void __tcf_chain_put(struct tcf_chain *chain, bool by_act)
 
 static void tcf_chain_put(struct tcf_chain *chain)
 {
-       __tcf_chain_put(chain, false);
+       __tcf_chain_put(chain, false, false);
 }
 
 void tcf_chain_put_by_act(struct tcf_chain *chain)
 {
-       __tcf_chain_put(chain, true);
+       __tcf_chain_put(chain, true, false);
 }
 EXPORT_SYMBOL(tcf_chain_put_by_act);
 
 static void tcf_chain_put_explicitly_created(struct tcf_chain *chain)
 {
-       if (chain->explicitly_created)
-               tcf_chain_put(chain);
+       __tcf_chain_put(chain, false, true);
 }
 
 static void tcf_chain_flush(struct tcf_chain *chain)
@@ -2305,7 +2313,6 @@ replay:
                 * to the chain previously taken during addition.
                 */
                tcf_chain_put_explicitly_created(chain);
-               chain->explicitly_created = false;
                break;
        case RTM_GETCHAIN:
                err = tc_chain_notify(chain, skb, n->nlmsg_seq,