]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/core/sock.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux.git] / net / core / sock.c
index 79c6aee6af9b817bd7086f04ae8f46342a3bf4b6..727f924b7f91f495d9e7a4e7297c9c937d3258ed 100644 (file)
 
 #include <trace/events/sock.h>
 
-#ifdef CONFIG_INET
 #include <net/tcp.h>
-#endif
-
 #include <net/busy_poll.h>
 
 static DEFINE_MUTEX(proto_list_mutex);
@@ -1803,28 +1800,24 @@ EXPORT_SYMBOL(skb_set_owner_w);
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
  * But we also want to keep skb->sk set because some packet schedulers
- * rely on it (sch_fq for example). So we set skb->truesize to a small
- * amount (1) and decrease sk_wmem_alloc accordingly.
+ * rely on it (sch_fq for example).
  */
 void skb_orphan_partial(struct sk_buff *skb)
 {
-       /* If this skb is a TCP pure ACK or already went here,
-        * we have nothing to do. 2 is already a very small truesize.
-        */
-       if (skb->truesize <= 2)
+       if (skb_is_tcp_pure_ack(skb))
                return;
 
-       /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
-        * so we do not completely orphan skb, but transfert all
-        * accounted bytes but one, to avoid unexpected reorders.
-        */
        if (skb->destructor == sock_wfree
 #ifdef CONFIG_INET
            || skb->destructor == tcp_wfree
 #endif
                ) {
-               atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
-               skb->truesize = 1;
+               struct sock *sk = skb->sk;
+
+               if (atomic_inc_not_zero(&sk->sk_refcnt)) {
+                       atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
+                       skb->destructor = sock_efree;
+               }
        } else {
                skb_orphan(skb);
        }