net: sched: do not use tcf_proto 'tp' argument from call_rcu
[firefly-linux-kernel-4.4.55.git] / net / sched / cls_fw.c
index 2650285620ee8d583dadeb8911332ab245f5bed1..dbfdfd1f1a9f8cc6d2364bed4c700eef4a029ed3 100644 (file)
@@ -123,10 +123,8 @@ static int fw_init(struct tcf_proto *tp)
 static void fw_delete_filter(struct rcu_head *head)
 {
        struct fw_filter *f = container_of(head, struct fw_filter, rcu);
-       struct tcf_proto *tp = f->tp;
 
-       tcf_unbind_filter(tp, &f->res);
-       tcf_exts_destroy(tp, &f->exts);
+       tcf_exts_destroy(&f->exts);
        kfree(f);
 }
 
@@ -143,6 +141,7 @@ static void fw_destroy(struct tcf_proto *tp)
                while ((f = rtnl_dereference(head->ht[h])) != NULL) {
                        RCU_INIT_POINTER(head->ht[h],
                                         rtnl_dereference(f->next));
+                       tcf_unbind_filter(tp, &f->res);
                        call_rcu(&f->rcu, fw_delete_filter);
                }
        }
@@ -166,6 +165,7 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg)
             fp = &pfp->next, pfp = rtnl_dereference(*fp)) {
                if (pfp == f) {
                        RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
+                       tcf_unbind_filter(tp, &f->res);
                        call_rcu(&f->rcu, fw_delete_filter);
                        return 0;
                }
@@ -223,7 +223,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
 
        return 0;
 errout:
-       tcf_exts_destroy(tp, &e);
+       tcf_exts_destroy(&e);
        return err;
 }
 
@@ -280,6 +280,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
 
                RCU_INIT_POINTER(fnew->next, rtnl_dereference(pfp->next));
                rcu_assign_pointer(*fp, fnew);
+               tcf_unbind_filter(tp, &f->res);
                call_rcu(&f->rcu, fw_delete_filter);
 
                *arg = (unsigned long)fnew;