diff options
-rw-r--r-- | include/net/sock.h | 12 | ||||
-rw-r--r-- | net/core/filter.c | 4 | ||||
-rw-r--r-- | net/core/sock.c | 2 |
3 files changed, 11 insertions, 7 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 453c79d0915b..b9cfe125c9e6 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -922,14 +922,18 @@ static inline void sk_filter_rcu_free(struct rcu_head *rcu) | |||
922 | * Remove a filter from a socket and release its resources. | 922 | * Remove a filter from a socket and release its resources. |
923 | */ | 923 | */ |
924 | 924 | ||
925 | static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp) | 925 | static inline void sk_filter_release(struct sk_filter *fp) |
926 | { | ||
927 | if (atomic_dec_and_test(&fp->refcnt)) | ||
928 | call_rcu_bh(&fp->rcu, sk_filter_rcu_free); | ||
929 | } | ||
930 | |||
931 | static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) | ||
926 | { | 932 | { |
927 | unsigned int size = sk_filter_len(fp); | 933 | unsigned int size = sk_filter_len(fp); |
928 | 934 | ||
929 | atomic_sub(size, &sk->sk_omem_alloc); | 935 | atomic_sub(size, &sk->sk_omem_alloc); |
930 | 936 | sk_filter_release(fp); | |
931 | if (atomic_dec_and_test(&fp->refcnt)) | ||
932 | call_rcu_bh(&fp->rcu, sk_filter_rcu_free); | ||
933 | } | 937 | } |
934 | 938 | ||
935 | static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp) | 939 | static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp) |
diff --git a/net/core/filter.c b/net/core/filter.c index fd607581ab50..2be1830d3c35 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -429,7 +429,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
429 | } | 429 | } |
430 | 430 | ||
431 | if (fp) | 431 | if (fp) |
432 | sk_filter_release(sk, fp); | 432 | sk_filter_uncharge(sk, fp); |
433 | return err; | 433 | return err; |
434 | } | 434 | } |
435 | 435 | ||
@@ -442,7 +442,7 @@ int sk_detach_filter(struct sock *sk) | |||
442 | filter = rcu_dereference(sk->sk_filter); | 442 | filter = rcu_dereference(sk->sk_filter); |
443 | if (filter) { | 443 | if (filter) { |
444 | rcu_assign_pointer(sk->sk_filter, NULL); | 444 | rcu_assign_pointer(sk->sk_filter, NULL); |
445 | sk_filter_release(sk, filter); | 445 | sk_filter_uncharge(sk, filter); |
446 | ret = 0; | 446 | ret = 0; |
447 | } | 447 | } |
448 | rcu_read_unlock_bh(); | 448 | rcu_read_unlock_bh(); |
diff --git a/net/core/sock.c b/net/core/sock.c index 07101381b8b7..d292b4113d6e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -915,7 +915,7 @@ void sk_free(struct sock *sk) | |||
915 | 915 | ||
916 | filter = rcu_dereference(sk->sk_filter); | 916 | filter = rcu_dereference(sk->sk_filter); |
917 | if (filter) { | 917 | if (filter) { |
918 | sk_filter_release(sk, filter); | 918 | sk_filter_uncharge(sk, filter); |
919 | rcu_assign_pointer(sk->sk_filter, NULL); | 919 | rcu_assign_pointer(sk->sk_filter, NULL); |
920 | } | 920 | } |
921 | 921 | ||