]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Fix output framentation of paged-skbs
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 22 Aug 2006 20:41:18 +0000 (13:41 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 8 Sep 2006 21:51:36 +0000 (14:51 -0700)
[INET]: Use pskb_trim_unique when trimming paged unique skbs

The IPv4/IPv6 datagram output path was using skb_trim to trim paged
packets because they know that the packet has not been cloned yet
(since the packet hasn't been given to anything else in the system).

This broke because skb_trim no longer allows paged packets to be
trimmed.  Paged packets must be given to one of the pskb_trim functions
instead.

This patch adds a new pskb_trim_unique function to cover the IPv4/IPv6
datagram output path scenario and replaces the corresponding skb_trim
calls with it.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
include/linux/skbuff.h
net/ipv4/ip_output.c
net/ipv6/ip6_output.c

index 2c31bb0797a63e12bf390371e88474e2cfe61f54..a1ce8434df09a27cd5f75b488b4cade030827ba9 100644 (file)
@@ -1008,6 +1008,21 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
        return (len < skb->len) ? __pskb_trim(skb, len) : 0;
 }
 
+/**
+ *     pskb_trim_unique - remove end from a paged unique (not cloned) buffer
+ *     @skb: buffer to alter
+ *     @len: new length
+ *
+ *     This is identical to pskb_trim except that the caller knows that
+ *     the skb is not cloned so we should never get an error due to out-
+ *     of-memory.
+ */
+static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)
+{
+       int err = pskb_trim(skb, len);
+       BUG_ON(err);
+}
+
 /**
  *     skb_orphan - orphan a buffer
  *     @skb: buffer to orphan
index cff9c3a72daf254013b7ae80cb5761e04a733a2f..d987a274b78817638b2256edbd3ba08da3f1e9d5 100644 (file)
@@ -946,7 +946,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
 
                        copy = datalen - transhdrlen - fraggap;
@@ -1139,7 +1139,7 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                                        data, fraggap, 0);
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
 
                        /*
index e46048974f37d217e4182f6ca20b252b0c137c53..56eddb34b932c6bb92c2b2da7a060caa38f83e31 100644 (file)
@@ -1047,7 +1047,7 @@ alloc_new_skb:
                                skb_prev->csum = csum_sub(skb_prev->csum,
                                                          skb->csum);
                                data += fraggap;
-                               skb_trim(skb_prev, maxfraglen);
+                               pskb_trim_unique(skb_prev, maxfraglen);
                        }
                        copy = datalen - transhdrlen - fraggap;
                        if (copy < 0) {