diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2007-10-18 04:22:17 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-10-18 04:22:17 (GMT) |
commit | d3904b739928edd83d117f1eb5bfa69f18d6f046 (patch) | |
tree | e73ddcf5d45f11b3b37031b0fea67d17943ca46b /net/core | |
parent | 309dd5fc872448e35634d510049642312ebc170d (diff) | |
download | linux-d3904b739928edd83d117f1eb5bfa69f18d6f046.tar.xz |
[NET]: Cleanup the error path in sk_attach_filter
The sk_filter_uncharge is called for error handling and
for releasing the former filter, but this will have to
be done in a bit different manner, so cleanup the error
path a bit.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/filter.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index 2be1830..54dddc9 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -398,7 +398,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) */ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) { - struct sk_filter *fp; + struct sk_filter *fp, *old_fp; unsigned int fsize = sizeof(struct sock_filter) * fprog->len; int err; @@ -418,19 +418,18 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) fp->len = fprog->len; err = sk_chk_filter(fp->insns, fp->len); - if (!err) { - struct sk_filter *old_fp; - - rcu_read_lock_bh(); - old_fp = rcu_dereference(sk->sk_filter); - rcu_assign_pointer(sk->sk_filter, fp); - rcu_read_unlock_bh(); - fp = old_fp; + if (err) { + sk_filter_uncharge(sk, fp); + return err; } - if (fp) - sk_filter_uncharge(sk, fp); - return err; + rcu_read_lock_bh(); + old_fp = rcu_dereference(sk->sk_filter); + rcu_assign_pointer(sk->sk_filter, fp); + rcu_read_unlock_bh(); + + sk_filter_uncharge(sk, old_fp); + return 0; } int sk_detach_filter(struct sock *sk) |