diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_api.c | 5 | ||||
-rw-r--r-- | net/sched/sch_api.c | 10 |
2 files changed, 11 insertions, 4 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index b6ef9a04de06..a75864d93142 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -81,6 +81,11 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops) | |||
81 | struct tcf_proto_ops *t; | 81 | struct tcf_proto_ops *t; |
82 | int rc = -ENOENT; | 82 | int rc = -ENOENT; |
83 | 83 | ||
84 | /* Wait for outstanding call_rcu()s, if any, from a | ||
85 | * tcf_proto_ops's destroy() handler. | ||
86 | */ | ||
87 | rcu_barrier(); | ||
88 | |||
84 | write_lock(&cls_mod_lock); | 89 | write_lock(&cls_mod_lock); |
85 | list_for_each_entry(t, &tcf_proto_base, head) { | 90 | list_for_each_entry(t, &tcf_proto_base, head) { |
86 | if (t == ops) { | 91 | if (t == ops) { |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index ad9eed70bc8f..1e1c89e51a11 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -815,10 +815,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
815 | if (dev->flags & IFF_UP) | 815 | if (dev->flags & IFF_UP) |
816 | dev_deactivate(dev); | 816 | dev_deactivate(dev); |
817 | 817 | ||
818 | if (new && new->ops->attach) { | 818 | if (new && new->ops->attach) |
819 | new->ops->attach(new); | 819 | goto skip; |
820 | num_q = 0; | ||
821 | } | ||
822 | 820 | ||
823 | for (i = 0; i < num_q; i++) { | 821 | for (i = 0; i < num_q; i++) { |
824 | struct netdev_queue *dev_queue = dev_ingress_queue(dev); | 822 | struct netdev_queue *dev_queue = dev_ingress_queue(dev); |
@@ -834,12 +832,16 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
834 | qdisc_destroy(old); | 832 | qdisc_destroy(old); |
835 | } | 833 | } |
836 | 834 | ||
835 | skip: | ||
837 | if (!ingress) { | 836 | if (!ingress) { |
838 | notify_and_destroy(net, skb, n, classid, | 837 | notify_and_destroy(net, skb, n, classid, |
839 | dev->qdisc, new); | 838 | dev->qdisc, new); |
840 | if (new && !new->ops->attach) | 839 | if (new && !new->ops->attach) |
841 | atomic_inc(&new->refcnt); | 840 | atomic_inc(&new->refcnt); |
842 | dev->qdisc = new ? : &noop_qdisc; | 841 | dev->qdisc = new ? : &noop_qdisc; |
842 | |||
843 | if (new && new->ops->attach) | ||
844 | new->ops->attach(new); | ||
843 | } else { | 845 | } else { |
844 | notify_and_destroy(net, skb, n, classid, old, new); | 846 | notify_and_destroy(net, skb, n, classid, old, new); |
845 | } | 847 | } |