From: Stephen Hemminger <hidden> Date: 2006-11-10 19:55:23
On Fri, 10 Nov 2006 12:17:45 -0700
Erik Andersen [off-list ref] wrote:
I have a Pegasos2 powerpc system acting as my home server. With
2.6.16.x it was 100% stable and I had months of uptime, rebooting
only to periodically apply security updates to the kernel.
With 2.6.17 and 2.6.18, after an uptime of no more than 2 days,
and usually much less, I get a kernel panic, with nothing in the
log. I finally caught it in the act, and took a picture.
http://codepoet.org/oops.jpg
A quick transcription of the Oops in the screenshot follows:
--------------------------------------------
The code int mv643xx_eth_start_xmit is not safe on SMP it was checking for space outside of lock.
Does the following (untested) fix it?
0. Fix race where space check is outside of lock.
1. Eliminate bogus BUG_ON()'s
2. Use proper transmit routine return values
3. Cleanup potential kernel log overrun if hit with unaligned frags
4. Compare with actual space needed rather than worst case
5. Use correct return code for case of linearize() failure.
---
drivers/net/mv643xx_eth.c | 30 ++++++++++++++----------------
1 files changed, 14 insertions(+), 16 deletions(-)
skb_linearize is documented to free skb on failure.
__skb_linearize
-> __pskb_pull_tail
-> pskb_expand_head
[...]
data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
if (!data)
goto nodata;
[...]
nodata:
return -ENOMEM;
I don't see where the skb is freed on this path.
Btw, the same __skb_linearize() is followed by a kfree_skb() in
drivers/net/via-velocity.c since 364c6badde0dd62a0a38e5ed67f85d87d6665780
I may be wrong but the source code does not seem completely right either.
--
Ueimor
From: Stephen Hemminger <hidden> Date: 2006-11-10 21:36:00
On Fri, 10 Nov 2006 22:30:43 +0100
Francois Romieu [off-list ref] wrote:
Stephen Hemminger [off-list ref] :
[...]
quoted
skb_linearize is documented to free skb on failure.
__skb_linearize
-> __pskb_pull_tail
-> pskb_expand_head
[...]
data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
if (!data)
goto nodata;
[...]
nodata:
return -ENOMEM;
I don't see where the skb is freed on this path.
Btw, the same __skb_linearize() is followed by a kfree_skb() in
drivers/net/via-velocity.c since 364c6badde0dd62a0a38e5ed67f85d87d6665780
I may be wrong but the source code does not seem completely right either.
Your correct, it does leave the skb alone. so it would be a leak.
Better documentation in skb_linearize would help.
--
Stephen Hemminger [off-list ref]
The data is not released.
drivers/net/mv643xx_eth.c apart, each current caller issues
kfree_skb() when required.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Yes it is.
If the non-linear SKB has data in pages, we copy that data from the
pages into the new linear skb->data area and release the paged data.
Right. The documentation talks about the skb _data_ so there is no
reason to imagine that the function could freed the skb on failure.
I'll leave Stephen reformulate the documentation if he feels the need to.
--
Ueimor