net: sched: do not use tcf_proto 'tp' argument from call_rcu
[firefly-linux-kernel-4.4.55.git] / net / sched / cls_basic.c
index fe20826a79e743a9a18de5d3568d0ea3d27d8f71..cd61280941e5c72d8c22e4dfe18ec517e90cba53 100644 (file)
@@ -91,11 +91,9 @@ static int basic_init(struct tcf_proto *tp)
 static void basic_delete_filter(struct rcu_head *head)
 {
        struct basic_filter *f = container_of(head, struct basic_filter, rcu);
-       struct tcf_proto *tp = f->tp;
 
-       tcf_unbind_filter(tp, &f->res);
        tcf_exts_destroy(&f->exts);
-       tcf_em_tree_destroy(tp, &f->ematches);
+       tcf_em_tree_destroy(&f->ematches);
        kfree(f);
 }
 
@@ -106,6 +104,7 @@ static void basic_destroy(struct tcf_proto *tp)
 
        list_for_each_entry_safe(f, n, &head->flist, link) {
                list_del_rcu(&f->link);
+               tcf_unbind_filter(tp, &f->res);
                call_rcu(&f->rcu, basic_delete_filter);
        }
        RCU_INIT_POINTER(tp->root, NULL);
@@ -120,6 +119,7 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg)
        list_for_each_entry(t, &head->flist, link)
                if (t == f) {
                        list_del_rcu(&t->link);
+                       tcf_unbind_filter(tp, &t->res);
                        call_rcu(&t->rcu, basic_delete_filter);
                        return 0;
                }
@@ -222,6 +222,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
 
        if (fold) {
                list_replace_rcu(&fold->link, &fnew->link);
+               tcf_unbind_filter(tp, &fold->res);
                call_rcu(&fold->rcu, basic_delete_filter);
        } else {
                list_add_rcu(&fnew->link, &head->flist);