diff options
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 0759f32e9dca..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) | |||
| 135 | unsigned long cl; | 135 | unsigned long cl; |
| 136 | unsigned long fh; | 136 | unsigned long fh; |
| 137 | int err; | 137 | int err; |
| 138 | int tp_created = 0; | ||
| 138 | 139 | ||
| 139 | if (net != &init_net) | 140 | if (net != &init_net) |
| 140 | return -EINVAL; | 141 | return -EINVAL; |
| @@ -266,10 +267,7 @@ replay: | |||
| 266 | goto errout; | 267 | goto errout; |
| 267 | } | 268 | } |
| 268 | 269 | ||
| 269 | spin_lock_bh(root_lock); | 270 | tp_created = 1; |
| 270 | tp->next = *back; | ||
| 271 | *back = tp; | ||
| 272 | spin_unlock_bh(root_lock); | ||
| 273 | 271 | ||
| 274 | } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) | 272 | } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) |
| 275 | goto errout; | 273 | goto errout; |
| @@ -296,8 +294,11 @@ replay: | |||
| 296 | switch (n->nlmsg_type) { | 294 | switch (n->nlmsg_type) { |
| 297 | case RTM_NEWTFILTER: | 295 | case RTM_NEWTFILTER: |
| 298 | err = -EEXIST; | 296 | err = -EEXIST; |
| 299 | if (n->nlmsg_flags & NLM_F_EXCL) | 297 | if (n->nlmsg_flags & NLM_F_EXCL) { |
| 298 | if (tp_created) | ||
| 299 | tcf_destroy(tp); | ||
| 300 | goto errout; | 300 | goto errout; |
| 301 | } | ||
| 301 | break; | 302 | break; |
| 302 | case RTM_DELTFILTER: | 303 | case RTM_DELTFILTER: |
| 303 | err = tp->ops->delete(tp, fh); | 304 | err = tp->ops->delete(tp, fh); |
| @@ -314,8 +315,18 @@ replay: | |||
| 314 | } | 315 | } |
| 315 | 316 | ||
| 316 | err = tp->ops->change(tp, cl, t->tcm_handle, tca, &fh); | 317 | err = tp->ops->change(tp, cl, t->tcm_handle, tca, &fh); |
| 317 | if (err == 0) | 318 | if (err == 0) { |
| 319 | if (tp_created) { | ||
| 320 | spin_lock_bh(root_lock); | ||
| 321 | tp->next = *back; | ||
| 322 | *back = tp; | ||
| 323 | spin_unlock_bh(root_lock); | ||
| 324 | } | ||
| 318 | tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); | 325 | tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); |
| 326 | } else { | ||
| 327 | if (tp_created) | ||
| 328 | tcf_destroy(tp); | ||
| 329 | } | ||
| 319 | 330 | ||
| 320 | errout: | 331 | errout: |
| 321 | if (cl) | 332 | if (cl) |
