From 6461f544fd32f47928b6963b489f30ee2198db14 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 17 Oct 2007 21:22:42 -0700 Subject: [PATCH] --- yaml --- r: 71280 b: refs/heads/master c: 47e958eac280c263397582d5581e868c3227a1bd h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/net/sock.h | 12 +----------- trunk/net/core/filter.c | 23 +++++++++++++++++++++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/[refs] b/[refs] index 21af397f82d7..e1db265bd7ff 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d3904b739928edd83d117f1eb5bfa69f18d6f046 +refs/heads/master: 47e958eac280c263397582d5581e868c3227a1bd diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index b9cfe125c9e6..43fc3fa50d62 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -904,16 +904,6 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb) return err; } -/** - * sk_filter_rcu_free: Free a socket filter - * @rcu: rcu_head that contains the sk_filter to free - */ -static inline void sk_filter_rcu_free(struct rcu_head *rcu) -{ - struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); - kfree(fp); -} - /** * sk_filter_release: Release a socket filter * @sk: socket @@ -925,7 +915,7 @@ static inline void sk_filter_rcu_free(struct rcu_head *rcu) static inline void sk_filter_release(struct sk_filter *fp) { if (atomic_dec_and_test(&fp->refcnt)) - call_rcu_bh(&fp->rcu, sk_filter_rcu_free); + kfree(fp); } static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) diff --git a/trunk/net/core/filter.c b/trunk/net/core/filter.c index 54dddc92452d..1f0068eae501 100644 --- a/trunk/net/core/filter.c +++ b/trunk/net/core/filter.c @@ -386,6 +386,25 @@ int sk_chk_filter(struct sock_filter *filter, int flen) return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; } +/** + * sk_filter_rcu_release: Release a socket filter by rcu_head + * @rcu: rcu_head that contains the sk_filter to free + */ +static void sk_filter_rcu_release(struct rcu_head *rcu) +{ + struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); + + sk_filter_release(fp); +} + +static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp) +{ + unsigned int size = sk_filter_len(fp); + + atomic_sub(size, &sk->sk_omem_alloc); + call_rcu_bh(&fp->rcu, sk_filter_rcu_release); +} + /** * sk_attach_filter - attach a socket filter * @fprog: the filter program @@ -428,7 +447,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) rcu_assign_pointer(sk->sk_filter, fp); rcu_read_unlock_bh(); - sk_filter_uncharge(sk, old_fp); + sk_filter_delayed_uncharge(sk, old_fp); return 0; } @@ -441,7 +460,7 @@ int sk_detach_filter(struct sock *sk) filter = rcu_dereference(sk->sk_filter); if (filter) { rcu_assign_pointer(sk->sk_filter, NULL); - sk_filter_uncharge(sk, filter); + sk_filter_delayed_uncharge(sk, filter); ret = 0; } rcu_read_unlock_bh();