diff options
author | Jarek Poplawski <jarkao2@gmail.com> | 2008-04-12 21:37:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-12 21:37:13 -0400 |
commit | e56cfad132f2ae269082359d279c17230c987e74 (patch) | |
tree | 6867ab5499fe617a16b15f1572b5d22d863d2524 /net/sched/cls_u32.c | |
parent | 028b027524b162eef90839a92ba4b8bddf23e06c (diff) |
[NET_SCHED] cls_u32: refcounting fix for u32_delete()
Deleting of nonroot hnodes mostly doesn't work in u32_delete():
refcnt == 1 is expected, but such hnodes' refcnts are initialized
with 0 and charged only with "link" nodes. Now they'll start with
1 like usual. Thanks to Patrick McHardy for an improving suggestion.
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_u32.c')
-rw-r--r-- | net/sched/cls_u32.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index c5c16b4b6e98..4d755444c449 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -411,8 +411,10 @@ static void u32_destroy(struct tcf_proto *tp) | |||
411 | } | 411 | } |
412 | } | 412 | } |
413 | 413 | ||
414 | for (ht=tp_c->hlist; ht; ht = ht->next) | 414 | for (ht = tp_c->hlist; ht; ht = ht->next) { |
415 | ht->refcnt--; | ||
415 | u32_clear_hnode(tp, ht); | 416 | u32_clear_hnode(tp, ht); |
417 | } | ||
416 | 418 | ||
417 | while ((ht = tp_c->hlist) != NULL) { | 419 | while ((ht = tp_c->hlist) != NULL) { |
418 | tp_c->hlist = ht->next; | 420 | tp_c->hlist = ht->next; |
@@ -441,8 +443,12 @@ static int u32_delete(struct tcf_proto *tp, unsigned long arg) | |||
441 | if (tp->root == ht) | 443 | if (tp->root == ht) |
442 | return -EINVAL; | 444 | return -EINVAL; |
443 | 445 | ||
444 | if (--ht->refcnt == 0) | 446 | if (ht->refcnt == 1) { |
447 | ht->refcnt--; | ||
445 | u32_destroy_hnode(tp, ht); | 448 | u32_destroy_hnode(tp, ht); |
449 | } else { | ||
450 | return -EBUSY; | ||
451 | } | ||
446 | 452 | ||
447 | return 0; | 453 | return 0; |
448 | } | 454 | } |
@@ -568,7 +574,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
568 | if (ht == NULL) | 574 | if (ht == NULL) |
569 | return -ENOBUFS; | 575 | return -ENOBUFS; |
570 | ht->tp_c = tp_c; | 576 | ht->tp_c = tp_c; |
571 | ht->refcnt = 0; | 577 | ht->refcnt = 1; |
572 | ht->divisor = divisor; | 578 | ht->divisor = divisor; |
573 | ht->handle = handle; | 579 | ht->handle = handle; |
574 | ht->prio = tp->prio; | 580 | ht->prio = tp->prio; |