aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c37
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))
1662new_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
1692static bool spd_can_coalesce(const struct splice_pipe_desc *spd, 1673static bool spd_can_coalesce(const struct splice_pipe_desc *spd,