diff options
-rw-r--r-- | include/net/sch_generic.h | 4 | ||||
-rw-r--r-- | net/sched/cls_api.c | 14 | ||||
-rw-r--r-- | net/sched/cls_basic.c | 6 | ||||
-rw-r--r-- | net/sched/cls_bpf.c | 6 | ||||
-rw-r--r-- | net/sched/cls_cgroup.c | 6 | ||||
-rw-r--r-- | net/sched/cls_flow.c | 6 | ||||
-rw-r--r-- | net/sched/cls_fw.c | 11 | ||||
-rw-r--r-- | net/sched/cls_route.c | 12 | ||||
-rw-r--r-- | net/sched/cls_rsvp.h | 12 | ||||
-rw-r--r-- | net/sched/cls_tcindex.c | 6 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 25 | ||||
-rw-r--r-- | net/sched/sch_api.c | 14 |
12 files changed, 99 insertions, 23 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index c605d305c577..6d778efcfdfd 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -213,7 +213,7 @@ struct tcf_proto_ops { | |||
213 | const struct tcf_proto *, | 213 | const struct tcf_proto *, |
214 | struct tcf_result *); | 214 | struct tcf_result *); |
215 | int (*init)(struct tcf_proto*); | 215 | int (*init)(struct tcf_proto*); |
216 | void (*destroy)(struct tcf_proto*); | 216 | bool (*destroy)(struct tcf_proto*, bool); |
217 | 217 | ||
218 | unsigned long (*get)(struct tcf_proto*, u32 handle); | 218 | unsigned long (*get)(struct tcf_proto*, u32 handle); |
219 | int (*change)(struct net *net, struct sk_buff *, | 219 | int (*change)(struct net *net, struct sk_buff *, |
@@ -399,7 +399,7 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, | |||
399 | const struct Qdisc_ops *ops, u32 parentid); | 399 | const struct Qdisc_ops *ops, u32 parentid); |
400 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, | 400 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, |
401 | const struct qdisc_size_table *stab); | 401 | const struct qdisc_size_table *stab); |
402 | void tcf_destroy(struct tcf_proto *tp); | 402 | bool tcf_destroy(struct tcf_proto *tp, bool force); |
403 | void tcf_destroy_chain(struct tcf_proto __rcu **fl); | 403 | void tcf_destroy_chain(struct tcf_proto __rcu **fl); |
404 | 404 | ||
405 | /* Reset all TX qdiscs greater then index of a device. */ | 405 | /* Reset all TX qdiscs greater then index of a device. */ |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index baef987fe2c0..8b0470e418dc 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -286,7 +286,7 @@ replay: | |||
286 | RCU_INIT_POINTER(*back, next); | 286 | RCU_INIT_POINTER(*back, next); |
287 | 287 | ||
288 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); | 288 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); |
289 | tcf_destroy(tp); | 289 | tcf_destroy(tp, true); |
290 | err = 0; | 290 | err = 0; |
291 | goto errout; | 291 | goto errout; |
292 | } | 292 | } |
@@ -301,14 +301,20 @@ replay: | |||
301 | err = -EEXIST; | 301 | err = -EEXIST; |
302 | if (n->nlmsg_flags & NLM_F_EXCL) { | 302 | if (n->nlmsg_flags & NLM_F_EXCL) { |
303 | if (tp_created) | 303 | if (tp_created) |
304 | tcf_destroy(tp); | 304 | tcf_destroy(tp, true); |
305 | goto errout; | 305 | goto errout; |
306 | } | 306 | } |
307 | break; | 307 | break; |
308 | case RTM_DELTFILTER: | 308 | case RTM_DELTFILTER: |
309 | err = tp->ops->delete(tp, fh); | 309 | err = tp->ops->delete(tp, fh); |
310 | if (err == 0) | 310 | if (err == 0) { |
311 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); | 311 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); |
312 | if (tcf_destroy(tp, false)) { | ||
313 | struct tcf_proto *next = rtnl_dereference(tp->next); | ||
314 | |||
315 | RCU_INIT_POINTER(*back, next); | ||
316 | } | ||
317 | } | ||
312 | goto errout; | 318 | goto errout; |
313 | case RTM_GETTFILTER: | 319 | case RTM_GETTFILTER: |
314 | err = tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); | 320 | err = tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); |
@@ -329,7 +335,7 @@ replay: | |||
329 | tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); | 335 | tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); |
330 | } else { | 336 | } else { |
331 | if (tp_created) | 337 | if (tp_created) |
332 | tcf_destroy(tp); | 338 | tcf_destroy(tp, true); |
333 | } | 339 | } |
334 | 340 | ||
335 | errout: | 341 | errout: |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index fc399db86f11..0b8c3ace671f 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -96,11 +96,14 @@ static void basic_delete_filter(struct rcu_head *head) | |||
96 | kfree(f); | 96 | kfree(f); |
97 | } | 97 | } |
98 | 98 | ||
99 | static void basic_destroy(struct tcf_proto *tp) | 99 | static bool basic_destroy(struct tcf_proto *tp, bool force) |
100 | { | 100 | { |
101 | struct basic_head *head = rtnl_dereference(tp->root); | 101 | struct basic_head *head = rtnl_dereference(tp->root); |
102 | struct basic_filter *f, *n; | 102 | struct basic_filter *f, *n; |
103 | 103 | ||
104 | if (!force && !list_empty(&head->flist)) | ||
105 | return false; | ||
106 | |||
104 | list_for_each_entry_safe(f, n, &head->flist, link) { | 107 | list_for_each_entry_safe(f, n, &head->flist, link) { |
105 | list_del_rcu(&f->link); | 108 | list_del_rcu(&f->link); |
106 | tcf_unbind_filter(tp, &f->res); | 109 | tcf_unbind_filter(tp, &f->res); |
@@ -108,6 +111,7 @@ static void basic_destroy(struct tcf_proto *tp) | |||
108 | } | 111 | } |
109 | RCU_INIT_POINTER(tp->root, NULL); | 112 | RCU_INIT_POINTER(tp->root, NULL); |
110 | kfree_rcu(head, rcu); | 113 | kfree_rcu(head, rcu); |
114 | return true; | ||
111 | } | 115 | } |
112 | 116 | ||
113 | static int basic_delete(struct tcf_proto *tp, unsigned long arg) | 117 | static int basic_delete(struct tcf_proto *tp, unsigned long arg) |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 6f7ed8f8e6ee..243c9f225a73 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -137,11 +137,14 @@ static int cls_bpf_delete(struct tcf_proto *tp, unsigned long arg) | |||
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | static void cls_bpf_destroy(struct tcf_proto *tp) | 140 | static bool cls_bpf_destroy(struct tcf_proto *tp, bool force) |
141 | { | 141 | { |
142 | struct cls_bpf_head *head = rtnl_dereference(tp->root); | 142 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
143 | struct cls_bpf_prog *prog, *tmp; | 143 | struct cls_bpf_prog *prog, *tmp; |
144 | 144 | ||
145 | if (!force && !list_empty(&head->plist)) | ||
146 | return false; | ||
147 | |||
145 | list_for_each_entry_safe(prog, tmp, &head->plist, link) { | 148 | list_for_each_entry_safe(prog, tmp, &head->plist, link) { |
146 | list_del_rcu(&prog->link); | 149 | list_del_rcu(&prog->link); |
147 | tcf_unbind_filter(tp, &prog->res); | 150 | tcf_unbind_filter(tp, &prog->res); |
@@ -150,6 +153,7 @@ static void cls_bpf_destroy(struct tcf_proto *tp) | |||
150 | 153 | ||
151 | RCU_INIT_POINTER(tp->root, NULL); | 154 | RCU_INIT_POINTER(tp->root, NULL); |
152 | kfree_rcu(head, rcu); | 155 | kfree_rcu(head, rcu); |
156 | return true; | ||
153 | } | 157 | } |
154 | 158 | ||
155 | static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle) | 159 | static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle) |
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 221697ab0247..ea611b216412 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c | |||
@@ -143,14 +143,18 @@ errout: | |||
143 | return err; | 143 | return err; |
144 | } | 144 | } |
145 | 145 | ||
146 | static void cls_cgroup_destroy(struct tcf_proto *tp) | 146 | static bool cls_cgroup_destroy(struct tcf_proto *tp, bool force) |
147 | { | 147 | { |
148 | struct cls_cgroup_head *head = rtnl_dereference(tp->root); | 148 | struct cls_cgroup_head *head = rtnl_dereference(tp->root); |
149 | 149 | ||
150 | if (!force) | ||
151 | return false; | ||
152 | |||
150 | if (head) { | 153 | if (head) { |
151 | RCU_INIT_POINTER(tp->root, NULL); | 154 | RCU_INIT_POINTER(tp->root, NULL); |
152 | call_rcu(&head->rcu, cls_cgroup_destroy_rcu); | 155 | call_rcu(&head->rcu, cls_cgroup_destroy_rcu); |
153 | } | 156 | } |
157 | return true; | ||
154 | } | 158 | } |
155 | 159 | ||
156 | static int cls_cgroup_delete(struct tcf_proto *tp, unsigned long arg) | 160 | static int cls_cgroup_delete(struct tcf_proto *tp, unsigned long arg) |
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 461410394d08..a620c4e288a5 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -557,17 +557,21 @@ static int flow_init(struct tcf_proto *tp) | |||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
559 | 559 | ||
560 | static void flow_destroy(struct tcf_proto *tp) | 560 | static bool flow_destroy(struct tcf_proto *tp, bool force) |
561 | { | 561 | { |
562 | struct flow_head *head = rtnl_dereference(tp->root); | 562 | struct flow_head *head = rtnl_dereference(tp->root); |
563 | struct flow_filter *f, *next; | 563 | struct flow_filter *f, *next; |
564 | 564 | ||
565 | if (!force && !list_empty(&head->filters)) | ||
566 | return false; | ||
567 | |||
565 | list_for_each_entry_safe(f, next, &head->filters, list) { | 568 | list_for_each_entry_safe(f, next, &head->filters, list) { |
566 | list_del_rcu(&f->list); | 569 | list_del_rcu(&f->list); |
567 | call_rcu(&f->rcu, flow_destroy_filter); | 570 | call_rcu(&f->rcu, flow_destroy_filter); |
568 | } | 571 | } |
569 | RCU_INIT_POINTER(tp->root, NULL); | 572 | RCU_INIT_POINTER(tp->root, NULL); |
570 | kfree_rcu(head, rcu); | 573 | kfree_rcu(head, rcu); |
574 | return true; | ||
571 | } | 575 | } |
572 | 576 | ||
573 | static unsigned long flow_get(struct tcf_proto *tp, u32 handle) | 577 | static unsigned long flow_get(struct tcf_proto *tp, u32 handle) |
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 9d9aa3e82b10..715e01e5910a 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -133,14 +133,20 @@ static void fw_delete_filter(struct rcu_head *head) | |||
133 | kfree(f); | 133 | kfree(f); |
134 | } | 134 | } |
135 | 135 | ||
136 | static void fw_destroy(struct tcf_proto *tp) | 136 | static bool fw_destroy(struct tcf_proto *tp, bool force) |
137 | { | 137 | { |
138 | struct fw_head *head = rtnl_dereference(tp->root); | 138 | struct fw_head *head = rtnl_dereference(tp->root); |
139 | struct fw_filter *f; | 139 | struct fw_filter *f; |
140 | int h; | 140 | int h; |
141 | 141 | ||
142 | if (head == NULL) | 142 | if (head == NULL) |
143 | return; | 143 | return true; |
144 | |||
145 | if (!force) { | ||
146 | for (h = 0; h < HTSIZE; h++) | ||
147 | if (rcu_access_pointer(head->ht[h])) | ||
148 | return false; | ||
149 | } | ||
144 | 150 | ||
145 | for (h = 0; h < HTSIZE; h++) { | 151 | for (h = 0; h < HTSIZE; h++) { |
146 | while ((f = rtnl_dereference(head->ht[h])) != NULL) { | 152 | while ((f = rtnl_dereference(head->ht[h])) != NULL) { |
@@ -152,6 +158,7 @@ static void fw_destroy(struct tcf_proto *tp) | |||
152 | } | 158 | } |
153 | RCU_INIT_POINTER(tp->root, NULL); | 159 | RCU_INIT_POINTER(tp->root, NULL); |
154 | kfree_rcu(head, rcu); | 160 | kfree_rcu(head, rcu); |
161 | return true; | ||
155 | } | 162 | } |
156 | 163 | ||
157 | static int fw_delete(struct tcf_proto *tp, unsigned long arg) | 164 | static int fw_delete(struct tcf_proto *tp, unsigned long arg) |
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index bb8a60235d01..08a3b0a6f5ab 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -277,13 +277,20 @@ route4_delete_filter(struct rcu_head *head) | |||
277 | kfree(f); | 277 | kfree(f); |
278 | } | 278 | } |
279 | 279 | ||
280 | static void route4_destroy(struct tcf_proto *tp) | 280 | static bool route4_destroy(struct tcf_proto *tp, bool force) |
281 | { | 281 | { |
282 | struct route4_head *head = rtnl_dereference(tp->root); | 282 | struct route4_head *head = rtnl_dereference(tp->root); |
283 | int h1, h2; | 283 | int h1, h2; |
284 | 284 | ||
285 | if (head == NULL) | 285 | if (head == NULL) |
286 | return; | 286 | return true; |
287 | |||
288 | if (!force) { | ||
289 | for (h1 = 0; h1 <= 256; h1++) { | ||
290 | if (rcu_access_pointer(head->table[h1])) | ||
291 | return false; | ||
292 | } | ||
293 | } | ||
287 | 294 | ||
288 | for (h1 = 0; h1 <= 256; h1++) { | 295 | for (h1 = 0; h1 <= 256; h1++) { |
289 | struct route4_bucket *b; | 296 | struct route4_bucket *b; |
@@ -308,6 +315,7 @@ static void route4_destroy(struct tcf_proto *tp) | |||
308 | } | 315 | } |
309 | RCU_INIT_POINTER(tp->root, NULL); | 316 | RCU_INIT_POINTER(tp->root, NULL); |
310 | kfree_rcu(head, rcu); | 317 | kfree_rcu(head, rcu); |
318 | return true; | ||
311 | } | 319 | } |
312 | 320 | ||
313 | static int route4_delete(struct tcf_proto *tp, unsigned long arg) | 321 | static int route4_delete(struct tcf_proto *tp, unsigned long arg) |
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index edd8ade3fbc1..02fa82792dab 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -291,13 +291,20 @@ rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) | |||
291 | kfree_rcu(f, rcu); | 291 | kfree_rcu(f, rcu); |
292 | } | 292 | } |
293 | 293 | ||
294 | static void rsvp_destroy(struct tcf_proto *tp) | 294 | static bool rsvp_destroy(struct tcf_proto *tp, bool force) |
295 | { | 295 | { |
296 | struct rsvp_head *data = rtnl_dereference(tp->root); | 296 | struct rsvp_head *data = rtnl_dereference(tp->root); |
297 | int h1, h2; | 297 | int h1, h2; |
298 | 298 | ||
299 | if (data == NULL) | 299 | if (data == NULL) |
300 | return; | 300 | return true; |
301 | |||
302 | if (!force) { | ||
303 | for (h1 = 0; h1 < 256; h1++) { | ||
304 | if (rcu_access_pointer(data->ht[h1])) | ||
305 | return false; | ||
306 | } | ||
307 | } | ||
301 | 308 | ||
302 | RCU_INIT_POINTER(tp->root, NULL); | 309 | RCU_INIT_POINTER(tp->root, NULL); |
303 | 310 | ||
@@ -319,6 +326,7 @@ static void rsvp_destroy(struct tcf_proto *tp) | |||
319 | } | 326 | } |
320 | } | 327 | } |
321 | kfree_rcu(data, rcu); | 328 | kfree_rcu(data, rcu); |
329 | return true; | ||
322 | } | 330 | } |
323 | 331 | ||
324 | static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) | 332 | static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) |
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) | |||
468 | } | 468 | } |
469 | } | 469 | } |
470 | 470 | ||
471 | static void tcindex_destroy(struct tcf_proto *tp) | 471 | static bool tcindex_destroy(struct tcf_proto *tp, bool force) |
472 | { | 472 | { |
473 | struct tcindex_data *p = rtnl_dereference(tp->root); | 473 | struct tcindex_data *p = rtnl_dereference(tp->root); |
474 | struct tcf_walker walker; | 474 | struct tcf_walker walker; |
475 | 475 | ||
476 | if (!force) | ||
477 | return false; | ||
478 | |||
476 | pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); | 479 | pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); |
477 | walker.count = 0; | 480 | walker.count = 0; |
478 | walker.skip = 0; | 481 | walker.skip = 0; |
@@ -481,6 +484,7 @@ static void tcindex_destroy(struct tcf_proto *tp) | |||
481 | 484 | ||
482 | RCU_INIT_POINTER(tp->root, NULL); | 485 | RCU_INIT_POINTER(tp->root, NULL); |
483 | call_rcu(&p->rcu, __tcindex_destroy); | 486 | call_rcu(&p->rcu, __tcindex_destroy); |
487 | return true; | ||
484 | } | 488 | } |
485 | 489 | ||
486 | 490 | ||
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 09487afbfd51..375e51b71c80 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -460,13 +460,35 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht) | |||
460 | return -ENOENT; | 460 | return -ENOENT; |
461 | } | 461 | } |
462 | 462 | ||
463 | static void u32_destroy(struct tcf_proto *tp) | 463 | static bool ht_empty(struct tc_u_hnode *ht) |
464 | { | ||
465 | unsigned int h; | ||
466 | |||
467 | for (h = 0; h <= ht->divisor; h++) | ||
468 | if (rcu_access_pointer(ht->ht[h])) | ||
469 | return false; | ||
470 | |||
471 | return true; | ||
472 | } | ||
473 | |||
474 | static bool u32_destroy(struct tcf_proto *tp, bool force) | ||
464 | { | 475 | { |
465 | struct tc_u_common *tp_c = tp->data; | 476 | struct tc_u_common *tp_c = tp->data; |
466 | struct tc_u_hnode *root_ht = rtnl_dereference(tp->root); | 477 | struct tc_u_hnode *root_ht = rtnl_dereference(tp->root); |
467 | 478 | ||
468 | WARN_ON(root_ht == NULL); | 479 | WARN_ON(root_ht == NULL); |
469 | 480 | ||
481 | if (!force) { | ||
482 | if (root_ht) { | ||
483 | if (root_ht->refcnt > 1) | ||
484 | return false; | ||
485 | if (root_ht->refcnt == 1) { | ||
486 | if (!ht_empty(root_ht)) | ||
487 | return false; | ||
488 | } | ||
489 | } | ||
490 | } | ||
491 | |||
470 | if (root_ht && --root_ht->refcnt == 0) | 492 | if (root_ht && --root_ht->refcnt == 0) |
471 | u32_destroy_hnode(tp, root_ht); | 493 | u32_destroy_hnode(tp, root_ht); |
472 | 494 | ||
@@ -491,6 +513,7 @@ static void u32_destroy(struct tcf_proto *tp) | |||
491 | } | 513 | } |
492 | 514 | ||
493 | tp->data = NULL; | 515 | tp->data = NULL; |
516 | return true; | ||
494 | } | 517 | } |
495 | 518 | ||
496 | static int u32_delete(struct tcf_proto *tp, unsigned long arg) | 519 | static int u32_delete(struct tcf_proto *tp, unsigned long arg) |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 243b7d169d61..ad9eed70bc8f 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -1858,11 +1858,15 @@ reclassify: | |||
1858 | } | 1858 | } |
1859 | EXPORT_SYMBOL(tc_classify); | 1859 | EXPORT_SYMBOL(tc_classify); |
1860 | 1860 | ||
1861 | void tcf_destroy(struct tcf_proto *tp) | 1861 | bool tcf_destroy(struct tcf_proto *tp, bool force) |
1862 | { | 1862 | { |
1863 | tp->ops->destroy(tp); | 1863 | if (tp->ops->destroy(tp, force)) { |
1864 | module_put(tp->ops->owner); | 1864 | module_put(tp->ops->owner); |
1865 | kfree_rcu(tp, rcu); | 1865 | kfree_rcu(tp, rcu); |
1866 | return true; | ||
1867 | } | ||
1868 | |||
1869 | return false; | ||
1866 | } | 1870 | } |
1867 | 1871 | ||
1868 | void tcf_destroy_chain(struct tcf_proto __rcu **fl) | 1872 | void tcf_destroy_chain(struct tcf_proto __rcu **fl) |
@@ -1871,7 +1875,7 @@ void tcf_destroy_chain(struct tcf_proto __rcu **fl) | |||
1871 | 1875 | ||
1872 | while ((tp = rtnl_dereference(*fl)) != NULL) { | 1876 | while ((tp = rtnl_dereference(*fl)) != NULL) { |
1873 | RCU_INIT_POINTER(*fl, tp->next); | 1877 | RCU_INIT_POINTER(*fl, tp->next); |
1874 | tcf_destroy(tp); | 1878 | tcf_destroy(tp, true); |
1875 | } | 1879 | } |
1876 | } | 1880 | } |
1877 | EXPORT_SYMBOL(tcf_destroy_chain); | 1881 | EXPORT_SYMBOL(tcf_destroy_chain); |