diff options
| author | Robert Richter <robert.richter@amd.com> | 2009-06-10 23:47:10 +0400 |
|---|---|---|
| committer | Robert Richter <robert.richter@amd.com> | 2009-06-10 23:47:10 +0400 |
| commit | 0886751c5d8b19fcee2e65d34ae21c9111e652a9 (patch) | |
| tree | 015e8c2b3d44d46e9e8fccd016340c51bc876d3b /net/sched/cls_api.c | |
| parent | 7e4e0bd50e80df2fe5501f48f872448376cdd997 (diff) | |
| parent | 07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff) | |
| download | linux-0886751c5d8b19fcee2e65d34ae21c9111e652a9.tar.xz | |
Merge commit 'v2.6.30' into oprofile/master
Diffstat (limited to 'net/sched/cls_api.c')
| -rw-r--r-- | net/sched/cls_api.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 173fcc4b050d..09cdcdfe7e91 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; @@ -254,7 +255,7 @@ replay: } tp->ops = tp_ops; tp->protocol = protocol; - tp->prio = nprio ? : tcf_auto_prio(*back); + tp->prio = nprio ? : TC_H_MAJ(tcf_auto_prio(*back)); tp->q = q; tp->classify = tp_ops->classify; tp->classid = parent; @@ -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) |
