diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-02 09:49:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-02 09:49:06 -0700 |
commit | ca55bd7e2905d344bf697f7c2cc347cb42999e7a (patch) | |
tree | f2b45dcfd55e72398d29320d2b3b9c3bace94a85 /net/sched/cls_api.c | |
parent | 4157fd85fc794bb7896b65c0cf686aa89d711d57 (diff) | |
parent | 12186be7d2e1106cede1cc728526e3d7998cbe94 (diff) | |
download | op-kernel-dev-ca55bd7e2905d344bf697f7c2cc347cb42999e7a.zip op-kernel-dev-ca55bd7e2905d344bf697f7c2cc347cb42999e7a.tar.gz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
net_cls: fix unconfigured struct tcf_proto keeps chaining and avoid kernel panic when we use cls_cgroup
e1000: add missing length check to e1000 receive routine
forcedeth: add phy_power_down parameter, leave phy powered up by default (v2)
Bluetooth: Remove useless flush_work() causing lockdep warnings
Diffstat (limited to 'net/sched/cls_api.c')
-rw-r--r-- | net/sched/cls_api.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 0759f32..09cdcdf 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -135,6 +135,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) unsigned long cl; unsigned long fh; int err; + int tp_created = 0; if (net != &init_net) return -EINVAL; @@ -266,10 +267,7 @@ replay: goto errout; } - spin_lock_bh(root_lock); - tp->next = *back; - *back = tp; - spin_unlock_bh(root_lock); + tp_created = 1; } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) goto errout; @@ -296,8 +294,11 @@ replay: switch (n->nlmsg_type) { case RTM_NEWTFILTER: err = -EEXIST; - if (n->nlmsg_flags & NLM_F_EXCL) + if (n->nlmsg_flags & NLM_F_EXCL) { + if (tp_created) + tcf_destroy(tp); goto errout; + } break; case RTM_DELTFILTER: err = tp->ops->delete(tp, fh); @@ -314,8 +315,18 @@ replay: } err = tp->ops->change(tp, cl, t->tcm_handle, tca, &fh); - if (err == 0) + if (err == 0) { + if (tp_created) { + spin_lock_bh(root_lock); + tp->next = *back; + *back = tp; + spin_unlock_bh(root_lock); + } tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); + } else { + if (tp_created) + tcf_destroy(tp); + } errout: if (cl) |