lkml.org 
[lkml]   [2010]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Regression, bisected: reference leak with IPSec since ~2.6.31
On Tue, Sep 21, 2010 at 12:07:37PM +0200, Eric Dumazet wrote:
> Le mardi 21 septembre 2010 ?? 11:55 +0200, Eric Dumazet a écrit :
> > Le mardi 21 septembre 2010 ?? 09:38 +0000, Jarek Poplawski a écrit :
> > > On Tue, Sep 21, 2010 at 11:21:00AM +0200, Eric Dumazet wrote:
> >
> > > I hope you're right with this.
> > >
> > > >
> > > > I liked the :
> > > >
> > > > <check everything without changing state>
> > > > if something wrong
> > > > goto slow_path
> > > > else
> > > > <OK, lets do destructive things>
> > > >
> > >
> > > But it's an optimization of the "unlikely" case btw. ;-)
> > >
> >
> > This is a bug fix, in a complex function.
> >
> > in -next branch, we can try to be smart, adding more code in slow_path
> > to revert what was done in the hope fast path would be taken.
> > And pray we dont add another bug :)

But if you were honest about caches there is no reason to be smart
no more. ;-)

Below is your patch mostly as an example only that I didn't mean
nothing complex (ipv4 only, not compiled).

Jarek P.
---

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 04b6989..049d61f 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -490,7 +490,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
if (skb_has_frags(skb)) {
struct sk_buff *frag;
int first_len = skb_pagelen(skb);
- int truesizes = 0;

if (first_len - hlen > mtu ||
((first_len - hlen) & 7) ||
@@ -503,18 +502,18 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
if (frag->len > mtu ||
((frag->len & 7) && frag->next) ||
skb_headroom(frag) < hlen)
- goto slow_path;
+ goto slow_path_clean;

/* Partially cloned skb? */
if (skb_shared(frag))
- goto slow_path;
+ goto slow_path_clean;

BUG_ON(frag->sk);
if (skb->sk) {
frag->sk = skb->sk;
frag->destructor = sock_wfree;
+ skb->truesize -= frag->truesize;
}
- truesizes += frag->truesize;
}

/* Everything is OK. Generate! */
@@ -524,7 +523,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
frag = skb_shinfo(skb)->frag_list;
skb_frag_list_init(skb);
skb->data_len = first_len - skb_headlen(skb);
- skb->truesize -= truesizes;
skb->len = first_len;
iph->tot_len = htons(first_len);
iph->frag_off = htons(IP_MF);
@@ -576,6 +574,17 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
}
IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
return err;
+
+slow_path_clean:
+ if (skb->sk) {
+ skb_walk_frags(skb, frag) {
+ if (!frag->sk)
+ break;
+ frag->sk = NULL;
+ frag->destructor = NULL;
+ skb->truesize += frag->truesize;
+ }
+ }
}

slow_path:
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2010-09-21 12:51    [W:0.064 / U:0.200 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site