On Sat, May 31, 2003 at 11:41:27PM -0700, David S. Miller wrote: > > I've applied your fix. Thanks a lot. And here is a patch to fix the leak in the flow cache. They used to be pol_put's before the move. And I've made sure it's a -p1 patch :) Thanks, -- Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: include/net/flow.h =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/flow.h,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 flow.h --- include/net/flow.h 27 May 2003 08:38:39 -0000 1.1.1.3 +++ a/include/net/flow.h 1 Jun 2003 04:53:42 -0000 @@ -82,8 +82,10 @@ #define FLOW_DIR_OUT 1 #define FLOW_DIR_FWD 2 +typedef void (*flow_obj_destroy_t)(void *); typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir, - void **objp, atomic_t **obj_refp); + void **objp, atomic_t **obj_refp, + flow_obj_destroy_t *destroyer); extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, flow_resolve_t resolver); Index: include/net/xfrm.h =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/xfrm.h,v retrieving revision 1.1.1.8 diff -u -r1.1.1.8 xfrm.h --- include/net/xfrm.h 27 May 2003 08:38:39 -0000 1.1.1.8 +++ a/include/net/xfrm.h 1 Jun 2003 04:46:35 -0000 @@ -348,7 +348,7 @@ atomic_inc(&policy->refcnt); } -extern void __xfrm_policy_destroy(struct xfrm_policy *policy); +extern void __xfrm_policy_destroy(void *policy); static inline void xfrm_pol_put(struct xfrm_policy *policy) { Index: net/xfrm/xfrm_policy.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_policy.c,v retrieving revision 1.3 diff -u -r1.3 xfrm_policy.c --- net/xfrm/xfrm_policy.c 1 Jun 2003 00:10:13 -0000 1.3 +++ a/net/xfrm/xfrm_policy.c 1 Jun 2003 04:56:48 -0000 @@ -179,8 +188,10 @@ /* Destroy xfrm_policy: descendant resources must be released to this moment. */ -void __xfrm_policy_destroy(struct xfrm_policy *policy) +void __xfrm_policy_destroy(void *data) { + struct xfrm_policy *policy = data; + if (!policy->dead) BUG(); @@ -381,8 +391,9 @@ /* Find policy to apply to this flow. */ -void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, - void **objp, atomic_t **obj_refp) +static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, + void **objp, atomic_t **obj_refp, + flow_obj_destroy_t *obj_destroyp) { struct xfrm_policy *pol; @@ -401,8 +412,10 @@ } } read_unlock_bh(&xfrm_policy_lock); - if ((*objp = (void *) pol) != NULL) + if ((*objp = (void *) pol) != NULL) { *obj_refp = &pol->refcnt; + *obj_destroyp = __xfrm_policy_destroy; + } } struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl) Index: net/core/flow.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/core/flow.c,v retrieving revision 1.2 diff -u -r1.2 flow.c --- net/core/flow.c 1 Jun 2003 00:08:36 -0000 1.2 +++ a/net/core/flow.c 1 Jun 2003 04:54:19 -0000 @@ -22,6 +22,7 @@ u32 genid; void *object; atomic_t *object_ref; + flow_obj_destroy_t object_destroy; }; atomic_t flow_cache_genid = ATOMIC_INIT(0); @@ -48,6 +49,12 @@ #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ) +static inline void flow_obj_put(struct flow_cache_entry *fle) +{ + if (fle->object && atomic_dec_and_test(fle->object_ref)) + fle->object_destroy(fle->object); +} + static void flow_cache_new_hashrnd(unsigned long arg) { int i; @@ -74,8 +81,7 @@ } while ((fle = *flp) != NULL) { *flp = fle->next; - if (fle->object) - atomic_dec(fle->object_ref); + flow_obj_put(fle); kmem_cache_free(flow_cachep, fle); flow_count(cpu)--; } @@ -172,17 +178,18 @@ { void *obj; atomic_t *obj_ref; + flow_obj_destroy_t obj_destroy; - resolver(key, family, dir, &obj, &obj_ref); + resolver(key, family, dir, &obj, &obj_ref, &obj_destroy); if (fle) { fle->genid = atomic_read(&flow_cache_genid); - if (fle->object) - atomic_dec(fle->object_ref); + flow_obj_put(fle); fle->object = obj; fle->object_ref = obj_ref; + fle->object_destroy = obj_destroy; if (obj) atomic_inc(fle->object_ref); } else { @@ -199,6 +206,7 @@ fle->genid = atomic_read(&flow_cache_genid); fle->object = obj; fle->object_ref = obj_ref; + fle->object_destroy = obj_destroy; if (obj) atomic_inc(fle->object_ref);