diff options
author | Cong Wang <cwang@twopensource.com> | 2015-03-06 11:47:59 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-09 15:35:55 -0400 |
commit | 1e052be69d045c8d0f82ff1116fd3e5a79661745 (patch) | |
tree | c237348cf8f28ca178c3ebfcec0e0013ef18b4c5 /net/sched/cls_tcindex.c | |
parent | fc6c6c2b8a2e1fbaa9e864af62c873dae15420ea (diff) | |
download | linux-1e052be69d045c8d0f82ff1116fd3e5a79661745.tar.gz linux-1e052be69d045c8d0f82ff1116fd3e5a79661745.tar.bz2 linux-1e052be69d045c8d0f82ff1116fd3e5a79661745.zip |
net_sched: destroy proto tp when all filters are gone
Kernel automatically creates a tp for each
(kind, protocol, priority) tuple, which has handle 0,
when we add a new filter, but it still is left there
after we remove our own, unless we don't specify the
handle (literally means all the filters under
the tuple). For example this one is left:
# tc filter show dev eth0
filter parent 8001: protocol arp pref 49152 basic
The user-space is hard to clean up these for kernel
because filters like u32 are organized in a complex way.
So kernel is responsible to remove it after all filters
are gone. Each type of filter has its own way to
store the filters, so each type has to provide its
way to check if all filters are gone.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <cwang@twopensource.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Jamal Hadi Salim<jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_tcindex.c')
-rw-r--r-- | net/sched/cls_tcindex.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index bd49bf547a47..a557dbaf5afe 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -468,11 +468,14 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker) } } -static void tcindex_destroy(struct tcf_proto *tp) +static bool tcindex_destroy(struct tcf_proto *tp, bool force) { struct tcindex_data *p = rtnl_dereference(tp->root); struct tcf_walker walker; + if (!force) + return false; + pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); walker.count = 0; walker.skip = 0; @@ -481,6 +484,7 @@ static void tcindex_destroy(struct tcf_proto *tp) RCU_INIT_POINTER(tp->root, NULL); call_rcu(&p->rcu, __tcindex_destroy); + return true; } |