Problems with buffers in 2.0.31-10

Philip Gladstone (philip@raptor.com)
Wed, 15 Oct 1997 09:19:35 -0400


This is a multi-part message in MIME format.

--------------122E5912125A
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I find that the attached patch helps with some network
drivers. For me it fixed the 'kfree_skb while still on list'
problem.

YMMV

Philip

-- 
Philip Gladstone                           +1 617 487 7700
Raptor Systems, Waltham, MA         http://www.raptor.com/

--------------122E5912125A Content-Type: text/plain; charset=us-ascii; name="p5_tcp.rpf" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="p5_tcp.rpf"

--- linux/net/ipv4/tcp_input.c.orig Tue Sep 30 14:55:45 1997 +++ linux/net/ipv4/tcp_input.c Wed Oct 1 13:29:15 1997 @@ -1394,6 +1396,7 @@ */ for (;;) { + int was_locked; struct sk_buff * skb = sk->send_head; if (!skb) break; @@ -1465,10 +1468,22 @@ * We may need to remove this from the dev send list. */ cli(); - if (skb->next) + was_locked = skb_device_locked(skb); + + if (was_locked) { + /* In this case, we are relying on the fact that kfree_skb + * will just set the free flag to be 3, and increment + * a counter. It will not actually free anything, and + * will not take much time + */ + kfree_skb(skb, FREE_WRITE); + } else { skb_unlink(skb); + } sti(); - kfree_skb(skb, FREE_WRITE); /* write. */ + + if (!was_locked) + kfree_skb(skb, FREE_WRITE); /* write. */ if (!sk->dead) sk->write_space(sk); } --- linux/net/ipv4/tcp_output.c.zz Wed Oct 1 13:51:40 1997 +++ linux/net/ipv4/tcp_output.c Wed Oct 1 14:03:44 1997 @@ -441,6 +441,7 @@ struct tcphdr *th; struct iphdr *iph; int size; + unsigned long flags; dev = skb->dev; IS_SKB(skb); @@ -456,8 +457,18 @@ /* effect is that we'll send some unnecessary data, */ /* but the alternative is disastrous... */ - if (skb_device_locked(skb)) + save_flags(flags); + cli(); + + if (skb_device_locked(skb)) { + restore_flags(flags); break; + } + + /* Unlink from any chain */ + skb_unlink(skb); + + restore_flags(flags); /* * Discard the surplus MAC header @@ -623,14 +634,15 @@ * We still add up the counts as the round trip time wants * adjusting. */ - if (sk && !skb_device_locked(skb)) + if (!skb_device_locked(skb)) { - /* Remove it from any existing driver queue first! */ - skb_unlink(skb); /* Now queue it */ ip_statistics.IpOutRequests++; dev_queue_xmit(skb, dev, sk->priority); sk->packets_out++; + } else { + /* This shouldn't happen as we skip out above if the buffer is locked */ + printk(KERN_WARNING "tcp_do_retransmit: sk_buff (%p) became locked\n", skb); } } }

--------------122E5912125A--