net_sched: destroy proto tp when all filters are gone
[firefly-linux-kernel-4.4.55.git] / net / sched / cls_api.c
index baef987fe2c036ae61f7108455ce1d828ec40e6c..8b0470e418dc6e9475464768d629969087e66b37 100644 (file)
@@ -286,7 +286,7 @@ replay:
                        RCU_INIT_POINTER(*back, next);
 
                        tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER);
-                       tcf_destroy(tp);
+                       tcf_destroy(tp, true);
                        err = 0;
                        goto errout;
                }
@@ -301,14 +301,20 @@ replay:
                        err = -EEXIST;
                        if (n->nlmsg_flags & NLM_F_EXCL) {
                                if (tp_created)
-                                       tcf_destroy(tp);
+                                       tcf_destroy(tp, true);
                                goto errout;
                        }
                        break;
                case RTM_DELTFILTER:
                        err = tp->ops->delete(tp, fh);
-                       if (err == 0)
+                       if (err == 0) {
                                tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER);
+                               if (tcf_destroy(tp, false)) {
+                                       struct tcf_proto *next = rtnl_dereference(tp->next);
+
+                                       RCU_INIT_POINTER(*back, next);
+                               }
+                       }
                        goto errout;
                case RTM_GETTFILTER:
                        err = tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER);
@@ -329,7 +335,7 @@ replay:
                tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER);
        } else {
                if (tp_created)
-                       tcf_destroy(tp);
+                       tcf_destroy(tp, true);
        }
 
 errout: