diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2012-05-02 14:18:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-03 01:34:37 -0400 |
commit | 2996d31f9f292cce67cd9105dc0a4a5ee43d2f14 (patch) | |
tree | 4368e35e13d083a40530c88de554de8d88c0aa41 /net/ipv4 | |
parent | b081f85c2977b1cbb6e635d53d9512f1ef985972 (diff) |
net: Stop decapitating clones that have a head_frag
This change is meant ot prevent stealing the skb->head to use as a page in
the event that the skb->head was cloned. This allows the other clones to
track each other via shinfo->dataref.
Without this we break down to two methods for tracking the reference count,
one being dataref, the other being the page count. As a result it becomes
difficult to track how many references there are to skb->head.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_input.c | 9 |
1 files changed, 2 insertions, 7 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2f696ef13dcd..c6f78e2b590f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4589,7 +4589,7 @@ copyfrags: | |||
4589 | to->data_len += len; | 4589 | to->data_len += len; |
4590 | goto merge; | 4590 | goto merge; |
4591 | } | 4591 | } |
4592 | if (from->head_frag) { | 4592 | if (from->head_frag && !skb_cloned(from)) { |
4593 | struct page *page; | 4593 | struct page *page; |
4594 | unsigned int offset; | 4594 | unsigned int offset; |
4595 | 4595 | ||
@@ -4599,12 +4599,7 @@ copyfrags: | |||
4599 | offset = from->data - (unsigned char *)page_address(page); | 4599 | offset = from->data - (unsigned char *)page_address(page); |
4600 | skb_fill_page_desc(to, skb_shinfo(to)->nr_frags, | 4600 | skb_fill_page_desc(to, skb_shinfo(to)->nr_frags, |
4601 | page, offset, skb_headlen(from)); | 4601 | page, offset, skb_headlen(from)); |
4602 | 4602 | *fragstolen = true; | |
4603 | if (skb_cloned(from)) | ||
4604 | get_page(page); | ||
4605 | else | ||
4606 | *fragstolen = true; | ||
4607 | |||
4608 | delta = len; /* we dont know real truesize... */ | 4603 | delta = len; /* we dont know real truesize... */ |
4609 | goto copyfrags; | 4604 | goto copyfrags; |
4610 | } | 4605 | } |