diff options
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r-- | net/core/skbuff.c | 37 |
1 files changed, 9 insertions, 28 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fe00d1208167..2ede3cfa8ffa 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -1655,38 +1655,19 @@ static struct page *linear_to_page(struct page *page, unsigned int *len, | |||
1655 | unsigned int *offset, | 1655 | unsigned int *offset, |
1656 | struct sk_buff *skb, struct sock *sk) | 1656 | struct sk_buff *skb, struct sock *sk) |
1657 | { | 1657 | { |
1658 | struct page *p = sk->sk_sndmsg_page; | 1658 | struct page_frag *pfrag = sk_page_frag(sk); |
1659 | unsigned int off; | ||
1660 | 1659 | ||
1661 | if (!p) { | 1660 | if (!sk_page_frag_refill(sk, pfrag)) |
1662 | new_page: | 1661 | return NULL; |
1663 | p = sk->sk_sndmsg_page = alloc_pages(sk->sk_allocation, 0); | ||
1664 | if (!p) | ||
1665 | return NULL; | ||
1666 | |||
1667 | off = sk->sk_sndmsg_off = 0; | ||
1668 | /* hold one ref to this page until it's full */ | ||
1669 | } else { | ||
1670 | unsigned int mlen; | ||
1671 | |||
1672 | /* If we are the only user of the page, we can reset offset */ | ||
1673 | if (page_count(p) == 1) | ||
1674 | sk->sk_sndmsg_off = 0; | ||
1675 | off = sk->sk_sndmsg_off; | ||
1676 | mlen = PAGE_SIZE - off; | ||
1677 | if (mlen < 64 && mlen < *len) { | ||
1678 | put_page(p); | ||
1679 | goto new_page; | ||
1680 | } | ||
1681 | 1662 | ||
1682 | *len = min_t(unsigned int, *len, mlen); | 1663 | *len = min_t(unsigned int, *len, pfrag->size - pfrag->offset); |
1683 | } | ||
1684 | 1664 | ||
1685 | memcpy(page_address(p) + off, page_address(page) + *offset, *len); | 1665 | memcpy(page_address(pfrag->page) + pfrag->offset, |
1686 | sk->sk_sndmsg_off += *len; | 1666 | page_address(page) + *offset, *len); |
1687 | *offset = off; | 1667 | *offset = pfrag->offset; |
1668 | pfrag->offset += *len; | ||
1688 | 1669 | ||
1689 | return p; | 1670 | return pfrag->page; |
1690 | } | 1671 | } |
1691 | 1672 | ||
1692 | static bool spd_can_coalesce(const struct splice_pipe_desc *spd, | 1673 | static bool spd_can_coalesce(const struct splice_pipe_desc *spd, |