aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-14 18:45:21 -0500
committerDavid S. Miller <davem@davemloft.net>2007-11-14 18:45:21 -0500
commitfb93134dfc2a6e6fbedc7c270a31da03fce88db9 (patch)
tree92c6d19049162f2f3eb9348a3159b5d0874a9daf /include
parent18b2b7bd09811779309592a10080fe9ffb93144d (diff)
[TCP]: Fix size calculation in sk_stream_alloc_pskb
We round up the header size in sk_stream_alloc_pskb so that TSO packets get zero tail room. Unfortunately this rounding up is not coordinated with the select_size() function used by TCP to calculate the second parameter of sk_stream_alloc_pskb. As a result, we may allocate more than a page of data in the non-TSO case when exactly one page is desired. In fact, rounding up the head room is detrimental in the non-TSO case because it makes memory that would otherwise be available to the payload head room. TSO doesn't need this either, all it wants is the guarantee that there is no tail room. So this patch fixes this by adjusting the skb_reserve call so that exactly the requested amount (which all callers have calculated in a precise way) is made available as tail room. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/net/sock.h10
1 files changed, 6 insertions, 4 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 5504fb9fa88a..567e468d7492 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1235,14 +1235,16 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
1235 gfp_t gfp) 1235 gfp_t gfp)
1236{ 1236{
1237 struct sk_buff *skb; 1237 struct sk_buff *skb;
1238 int hdr_len;
1239 1238
1240 hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header); 1239 skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp);
1241 skb = alloc_skb_fclone(size + hdr_len, gfp);
1242 if (skb) { 1240 if (skb) {
1243 skb->truesize += mem; 1241 skb->truesize += mem;
1244 if (sk_stream_wmem_schedule(sk, skb->truesize)) { 1242 if (sk_stream_wmem_schedule(sk, skb->truesize)) {
1245 skb_reserve(skb, hdr_len); 1243 /*
1244 * Make sure that we have exactly size bytes
1245 * available to the caller, no more, no less.
1246 */
1247 skb_reserve(skb, skb_tailroom(skb) - size);
1246 return skb; 1248 return skb;
1247 } 1249 }
1248 __kfree_skb(skb); 1250 __kfree_skb(skb);