diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-18 01:31:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-18 01:31:26 -0400 |
commit | 1e0d5a5747772182d1bb2525d8153da640fdfb58 (patch) | |
tree | 266a7c3e9a01728f7661d5b2976cc33d106b463c | |
parent | 3a76e3716b4e571f5d91a20b6afb412560599083 (diff) |
pkt_sched: No longer destroy qdiscs from RCU.
We can now kill them synchronously with all of the
previous dev_deactivate() cures.
This makes netdev destruction and shutdown saner as
the qdiscs hold references to the device.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sch_generic.h | 1 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 27 |
2 files changed, 9 insertions, 19 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 757ab087adbf..84d25f2e6188 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -61,7 +61,6 @@ struct Qdisc | |||
61 | struct gnet_stats_basic bstats; | 61 | struct gnet_stats_basic bstats; |
62 | struct gnet_stats_queue qstats; | 62 | struct gnet_stats_queue qstats; |
63 | struct gnet_stats_rate_est rate_est; | 63 | struct gnet_stats_rate_est rate_est; |
64 | struct rcu_head q_rcu; | ||
65 | int (*reshape_fail)(struct sk_buff *skb, | 64 | int (*reshape_fail)(struct sk_buff *skb, |
66 | struct Qdisc *q); | 65 | struct Qdisc *q); |
67 | 66 | ||
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 30b76aec723b..6f96b7bc0809 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -518,14 +518,19 @@ void qdisc_reset(struct Qdisc *qdisc) | |||
518 | } | 518 | } |
519 | EXPORT_SYMBOL(qdisc_reset); | 519 | EXPORT_SYMBOL(qdisc_reset); |
520 | 520 | ||
521 | /* this is the rcu callback function to clean up a qdisc when there | 521 | /* Under qdisc_lock(qdisc) and BH! */ |
522 | * are no further references to it */ | ||
523 | 522 | ||
524 | static void __qdisc_destroy(struct rcu_head *head) | 523 | void qdisc_destroy(struct Qdisc *qdisc) |
525 | { | 524 | { |
526 | struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu); | ||
527 | const struct Qdisc_ops *ops = qdisc->ops; | 525 | const struct Qdisc_ops *ops = qdisc->ops; |
528 | 526 | ||
527 | if (qdisc->flags & TCQ_F_BUILTIN || | ||
528 | !atomic_dec_and_test(&qdisc->refcnt)) | ||
529 | return; | ||
530 | |||
531 | if (qdisc->parent) | ||
532 | list_del(&qdisc->list); | ||
533 | |||
529 | #ifdef CONFIG_NET_SCHED | 534 | #ifdef CONFIG_NET_SCHED |
530 | qdisc_put_stab(qdisc->stab); | 535 | qdisc_put_stab(qdisc->stab); |
531 | #endif | 536 | #endif |
@@ -542,20 +547,6 @@ static void __qdisc_destroy(struct rcu_head *head) | |||
542 | 547 | ||
543 | kfree((char *) qdisc - qdisc->padded); | 548 | kfree((char *) qdisc - qdisc->padded); |
544 | } | 549 | } |
545 | |||
546 | /* Under qdisc_lock(qdisc) and BH! */ | ||
547 | |||
548 | void qdisc_destroy(struct Qdisc *qdisc) | ||
549 | { | ||
550 | if (qdisc->flags & TCQ_F_BUILTIN || | ||
551 | !atomic_dec_and_test(&qdisc->refcnt)) | ||
552 | return; | ||
553 | |||
554 | if (qdisc->parent) | ||
555 | list_del(&qdisc->list); | ||
556 | |||
557 | call_rcu(&qdisc->q_rcu, __qdisc_destroy); | ||
558 | } | ||
559 | EXPORT_SYMBOL(qdisc_destroy); | 550 | EXPORT_SYMBOL(qdisc_destroy); |
560 | 551 | ||
561 | static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) | 552 | static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) |